Multi-line headers for TTabSheet? - windows

I have a TPageControl with several tabs. On one page, the header is a bit too long and appears clipped on a single line. Is it possible to have the tab header be multi-line (ie. like the WordWrap property on buttons)?
In the image below the caption has been set to "This text is too long to fit onto one row". Ideally, this should appear on two rows:
This text is too long to fit
onto one row
For the example below I have set:
TabWidth := 185;
TabHeight := 60;
* EDIT *
The example above does not apply any theme. When a skin is applied (in this case the 3rd party product VCLSkin) and I insert a newline character at runtime, then it works:
Product_Sheet.Caption := (
'This text is too long' + #13#10 + 'to fit onto one row');
Based on the comments below, this suggests that in the absence of a skin, this will need to be custom-drawn.

Related

Ace editor - how do I remove/reset indent?

I want to change the behavior of the editor such that when the user presses enter on an empty list bullet, their cursor position is reset to the start of the line (rather than leaving them at the indented amount).
I've tried:
aceEdit.moveCursorTo(rowToUpdate, 0)
aceEdit.getSession().indentRows(rowToUpdate, rowToUpdate, "")
aceEdit.getSession().replace(range(rowToUpdate, 0, rowToUpdate, 0), "")
However, all three of these leave the cursor at the previous indent level. How do I reset the indent level for the line?
Update: adding example.
* list
* list
* list
* <- user presses enter here
_
Cursor is where I placed the underscore above, and can't be reset programmatically to the start of the line using what I listed above. (User can backspace the indents to get back to the start.)
You can use editor.setOption("enableAutoIndent", false) to disable automatic indentation.
If you want a way to keep autoIndent in all cases except the list, try creating an issue on ace's github page
If you want to remove the indentation on particular line you can do
var range = ace.Range
var cursor = editor.getCursorPosition()
var line = editor.session.getLine(cursor.row)
var match = /^\s*\*\s*/
if (match) {
editor.session.replace(new Range(cursor.row, 0, cursor.row, cursor.column), "")
}
If you are making a custom mode, you can give it a custom $outdent and related methods - see MatchingBraceOutdent, for example. I think the full set of indentation-related Mode methods is:
getNextLineIndent
checkOutdent
autoOutdent

rinohtype export to PDF - document header with chapter name and title

I'd like to define and style header as shown on the picture - the light part contains chapter name, document title is in the dark one.
Now I can only have the light grey section with text aligned to the right.
How can I define header style to achieve this? Also how can I insert those squares into the layout?
Thanks
I'd like to define and style header as shown on the picture - the light part contains chapter name, document title is in the dark one.
Unfortunately, this functionality is not yet documented well. Here are the steps necessary to obtain this:
Set a custom template configuration in conf.py if you haven't done so yet
rinoh_documents = [dict(doc='index', target='manual', template='my_template.rtt')]
Define the page header content in the template configuration (my_template.rtt)
[TEMPLATE_CONFIGURATION]
name = My Template
template = article
stylesheet = my_stylesheet.rts
[contents_page]
header_text = '\t' '{SECTION_TITLE(1)}' (header section title)
'\t' '{DOCUMENT_TITLE}' (header document title)
Style the header text and adjust the tab stop positions and alignment in the style sheet (my_stylesheet.rts)
[STYLESHEET]
name = My Style Sheet
base = sphinx_article
[header]
tab_stops=12cm RIGHT, 100% RIGHT
[header section title : StyledText('header section title')]
base = default
font_weight = bold
[header document title : StyledText('header document title')]
base = header section title
font_slant = italic
Also how can I insert those squares (in front of the text) into the layout?
For black squares, you can insert a unicode character, for example the aptly named BLACK SQUARE character using python-style escape sequences or simply pasting the character into the template configuration:
[contents_page]
header_text = '\t' '\N{BLACK SQUARE} {SECTION_TITLE(1)}' (header section title)
'\t' '■' (header square) ' {DOCUMENT_TITLE}' (header document title)
As you can see, you an style the square differently (e.g. larger font).
You can also use inline images, if unicode (or the font) doesn't cover your needs:
[contents_page]
header_text = '\t' IMAGE('img/square.png', scale=0.3) ' {SECTION_TITLE(1)}' (header section title)
'\t' IMAGE('img/circle.png', scale=0.3) '{DOCUMENT_TITLE}' (header document title)
Also how can I insert those squares into the layout? Adding a background for the page headers
You can set a background image on the page template in your template configuration. You can draw this in a vector drawing application such as Inkscape and export it to PDF.
[contents_page]
background='img/contents_background.pdf' scale=fill
You can adjust the placement of the header text by adjusting the margins and header_footer_distance in the page template configuration and .

optimalfill of a label

I have two forms in my application, form1 sending a long string (more than 300 characters) or short string (less than 50 characthers) to a label on form2 with a click of a button, I'm using a label because I can't find a memo component with transparent background, and Canvas stuff requires a long code compared with the label properties.
Some label properties
Align == alClient
Alignment = taCenter
Layout = tlCenter
WordWrap = True
AutoSize = True
OptimalFill = True
The idea is to adjust the height of the text with OptimalFill, but when I send a long string to the label, the font size, goes all wrong, sometimes the label fills right (when I repeat a long string after a short string for example).
With a:
showMessage(IntToStr(label.Font.Size));
I've got some weird changes on the font size, if I send a string with 100 chars for the first time I got a font like 18, if I send a string with 20 I got a font like 30 and if I send the same string with 100 chars, I got a 22 (numbers are just an example, not the real / right ones), and not even what they should be btw
IF I change the Caption, the text height goes bad (still the font size of the first string that I've used), it only changes when I send a small string, things just go strange.
Following the above example will be something like:
string with 100 chars returns a font size of 20
string with 70 chars returns a font size of 20 //should be arround 25 or so
string with 10 chars returns a font size of 40
string with 100 chars returns a font size of 22
Already tried:
// to 'reset' the font size then put the string on the caption and later the real string
Caption: = '';
Caption: = # 0;
Caption: = ' ';
Caption: = '-';
Label.Update; // to update the 'math'
Label.Refresh; // to update the 'math'
Label.Repaint; //one by one and all togheter
Label.AdjustSize
Application.ProcessMessages
Form2.Update
Label.UpdateBaseBound
Labe.AdjustFontForOptimalFill;
I tried after and before the 'on click sent string to'
label.Caption: = stringGrid.Cells [0, stringGrid.Row];
Also tried enable and disable the label to 'reset' everything.
Nothing works right, things have a strange value (font size) and the font size depends on the length of the sequence.
How can I make it work right and create the right source calculation each time Legend changes?
Arch Linux X64 with the latest Lazarus (QT) using Gnome 3.22.3 (not sure if this is relevant)

Pango select multiples fonts

I have three fonts i want to use in my software with pango:
Font1: latin, Cryllic characters
Font2: Korean characters
Font3: Japanese characters
Pango render the text correctly but i want select a font
There any way to indicate this preference pango font?
I use: linux and pango 1.29
The simplest way is to use PangoMarkup to set the fonts you want:
// See documentation for Pango markup for details
char *pszMarkup = "<span face=\"{font family name goes here}\">"
"{text requiring font goes here}"
"</span>"; // Split for clarity
char *pszText; // Pointer for text without markup tags
PangoAttrList *pAttr; // Attribute list - will be populated with tag info
pango_parse_markup (pszMarkup, -1, 0, &attr_list, &pszText, NULL, NULL);
You now have a buffer of regular text and an attribute list. If you want to set these up by hand (without going through the parser), you will need one PangoAttribute per instance of the font and set PangoAttribute.start_index and PangoAttribute.end_index by hand.
However you get them, you now give them to a PangoLayout:
// pWidget is the windowed widget in which the text is displayed:
PangoContext *pCtxt = gtk_widget_get_pango_context (pWidget);
PangoLayout *pLayout = pango_layout_new (pCtxt);
pango_layout_set_attributes(pLayout, pAttr);
pango_layout_set_text (pLayout, pszText, -1);
That's it. Use pango_cairo_show_layout (cr, pLayout) to display the results. The setup only needs changing when the content changes - it maintains the values across draw signals.

How to properly set the size of a ListView column according to its content?

I have a number of list view controls (TListView) that are used to display data. All these list view are set to "Detail" mode and all have TImageList assigned to their "SmallIcons" properties.
I'm trying to set the width of these column based on their contents exactly in the same way as if the user double-clicked on the separator slider at the end of each of the column headers.
First, I tried to set the column width to "-1" and "-2" for auto-sizing them: not only did that fail to work perfectly (some columns containing local characters - I'm using D6 and that means ANSI strings - are too low) but it also made the display of the column extremely slow (up to 30 seconds to display a list view with 6 column and 150 items when it's instantaneous with fixed width).
I have tried to use GetTextExtent on each cell to obtain the expected width of the text, adding some margin (from 2 to 10 pixels) and the expand the width of the column if it is lower than the calculated text width. Special treatment is applied to the first column (Items.caption) to take into account the display of the icon (I add the width of the icon, plus margin, to the width of the cell's text).
That didn't work either: in many cases (for instance, displaying the date in "yyyy/mm/dd hh:nn:ss" format results in a text too large to fit in the column).
Thinking that the issue could come from the window theme engine, I've switched to use GetThemeTextExtent instead of GetTextExtent but obtained the same result.
The only thing that seems to work is to add an arbitrary large margin (20 pixels) to each column width but, of course, that produces columns that are larger than they should be.
So, is there any alternative strategy ? I don't need anything but something that will calculate the correct width once: when the list is first populated. The code behind "clicking the column separator" works just fine but I can't find how to trigger it by code (well, I guess I could send the double click messages to the header directly as a hack)
For clarification, here are the things I tried the following code:
(in call case, there is a call made to ListView.canvas.Font.Assign(ListView.font). It is not in theses functions because a single assignment is enough but the code loops on all non-autosized columns of the listview).
Edit
My initial attempt using Windows Theme API:
function _GetTextWidth1(AText: widestring; IsHeader: boolean = false): Integer;
var
ATheme: HTheme;
rValue: TRect;
iPartID: integer;
AWidetext: WideString;
const
LVP_GROUPHEADER = 6;
begin
// try to get text width using theme API
ZeroMemory(#rValue, SizeOf(rValue));
ATheme := OpenThemeData(ListView.Handle, 'LISTVIEW');
try
if not IsHeader then
iPartID := LVP_LISTITEM
else
iPartID := LVP_GROUPHEADER;
AWidetext := AText;
GetThemeTextExtent( ATheme,
ListView.Canvas.Handle,
iPartID,
LIS_NORMAL,
PWideChar(AWidetext),
-1,
DT_LEFT or DT_SINGLELINE or DT_CALCRECT,
nil,
rValue
);
finally // wrap up
CloseThemeData(ATheme);
end; // try/finally
result := rValue.Right;
end;
next attempt using DrawText/DrawTextW:
function _GetTextWidth2(AText: widestring; IsHeader: boolean = false): Integer;
var
rValue: TRect;
lFlags: Integer;
begin
// try to get text width using DrawText/DrawTextW
rValue := Rect(0, 0, 0, 0);
lFlags := DT_CALCRECT or DT_EXPANDTABS or DT_NOPREFIX or DT_LEFT or DT_EXTERNALLEADING;
DrawText(ListView.canvas.Handle, PChar(AText), Length(AText), rValue, lFlags);
//DrawTextW(ListView.canvas.Handle, PWideChar(AText), Length(AText), rValue, lFlags);
result := rValue.Right;
end;
Third attempt using delphi's TextWidth function
function _GetTextWidth3(AText: widestring; IsHeader: boolean = false): Integer;
begin
// try to get text width using delphi wrapped around GetTextExtentPoint32
result := ListView.canvas.TextWidth(Atext);
end;
In all cases, I add a margin to the resulting width: I tried values as high as 20 pixels. I also take into account the possibility that the view use icons (in which case I add the width of the icon plus the margin again to the first column).
You could use canvas.TextWidth method. But be sure to use TListView canvas (not other, i.e. TForm) and first assign a font to canvas from TListView.
For example:
var
s: integer;
begin
ListView1.AddItem('test example item', nil);
ListView1.canvas.Font.Assign(ListView1.font);
s := ListView1.canvas.TextWidth(ListView1.Items[0].Caption) + 10; //this "+10" is a small additional margin
if s > ListView1.Columns[0].Width then
ListView1.Columns[0].Width := s;
It works fine for me.

Resources