Skip to content

Commit 31f5c73

Browse files
committed
fix: improve VirtualTreeView hints on Qt
1 parent 1b057bd commit 31f5c73

2 files changed

Lines changed: 151 additions & 5 deletions

File tree

source/apphelpers.pas

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1553,7 +1553,6 @@ procedure FixVT(VT: TVirtualStringTree; IsResultGrid: Boolean=False);
15531553

15541554
if IsResultGrid then begin
15551555
VT.Colors.GridLineColor := clGray; // 50% black grid lines, should fit on both light and dark theme
1556-
VT.HintMode := hmHint; // Show cell contents with linebreakds in datagrid and querygrid's
15571556
if AppSettings.ReadBool(asIncrementalSearch) then begin
15581557
// Apply case insensitive incremental search event
15591558
VT.IncrementalSearch := isInitializedOnly;
@@ -1562,9 +1561,21 @@ procedure FixVT(VT: TVirtualStringTree; IsResultGrid: Boolean=False);
15621561
else begin
15631562
VT.IncrementalSearch := isNone;
15641563
end;
1565-
end
1564+
end;
1565+
1566+
{$IFDEF LINUX}
1567+
{$if defined(LCLQt) or defined(LCLQt5) or defined(LCLQt6)}
1568+
if (VT is THeidiVirtualStringTree) and
1569+
(toGridExtensions in VT.TreeOptions.MiscOptions) then
1570+
VT.HintMode := hmHint
15661571
else
1567-
VT.HintMode := hmTooltip; // Just a quick tooltip for clipped nodes
1572+
{$endif}
1573+
{$ENDIF}
1574+
if IsResultGrid then
1575+
VT.HintMode := hmHint
1576+
else
1577+
VT.HintMode := hmTooltip;
1578+
15681579
VT.OnStartOperation := Mainform.AnyGridStartOperation;
15691580
VT.OnEndOperation := Mainform.AnyGridEndOperation;
15701581
VT.BorderStyle := bsNone; // Cosmetic
@@ -1573,6 +1584,7 @@ procedure FixVT(VT: TVirtualStringTree; IsResultGrid: Boolean=False);
15731584
VT.OnContextPopup := MainForm.AnyGridContextPopup;
15741585
end;
15751586

1587+
15761588
function GetTextHeight(Font: TFont): Integer;
15771589
var
15781590
Bmp: Graphics.TBitmap;

source/lazaruscompat.pas

Lines changed: 136 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ interface
1212

1313
uses
1414
Classes, SysUtils, SynEdit, SynEditKeyCmds, SynEditHighlighter, laz.VirtualTrees,
15-
Graphics, SynCompletion, Types;
15+
Graphics, SynCompletion, Types
16+
{$IFDEF HEIDI_LINUX_QT}
17+
, Forms, LMessages
18+
{$ENDIF};
1619

1720
type
1821

@@ -30,6 +33,10 @@ THeidiVirtualStringTree = class(TLazVirtualStringTree)
3033
function BlendQtColor(BaseColor, AccentColor: TColor; AccentPercent: Byte): TColor;
3134
procedure DrawQtSolidLine(Canvas: TCanvas; Left, Top, Right, Bottom: Integer);
3235
protected
36+
procedure CMHintShow(var Message: TCMHintShow); message CM_HINTSHOW;
37+
procedure CMHintShowPause(var Message: TCMHintShowPause); message CM_HINTSHOWPAUSE;
38+
function QtHintMaxWidth: Integer;
39+
function WrapQtHintLongTokens(const S: String; MaxWidth: Integer): String;
3340
procedure DoBeforeCellPaint(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
3441
CellPaintMode: TVTCellPaintMode; CellRect: TRect; var ContentRect: TRect); override;
3542
procedure DoAfterCellPaint(Canvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
@@ -208,7 +215,134 @@ implementation
208215

209216
{$IFDEF HEIDI_LINUX_QT}
210217
uses
211-
Math;
218+
Math, LazUTF8;
219+
const
220+
QtHintInitialPauseMs = 250;
221+
QtHintKeepAliveMs = 24 * 60 * 60 * 1000;
222+
223+
function THeidiVirtualStringTree.QtHintMaxWidth: Integer;
224+
var
225+
Monitor: TMonitor;
226+
WorkWidth, PreferredWidth, MinimumWidth, ScreenCap: Integer;
227+
begin
228+
PreferredWidth := Canvas.TextWidth(StringOfChar('0', 96)) + 24;
229+
MinimumWidth := Canvas.TextWidth(StringOfChar('0', 48)) + 24;
230+
Monitor := Screen.MonitorFromWindow(Handle);
231+
if Assigned(Monitor) then
232+
WorkWidth := Monitor.WorkareaRect.Right - Monitor.WorkareaRect.Left
233+
else
234+
WorkWidth := Screen.Width;
235+
236+
Result := PreferredWidth;
237+
if WorkWidth > 0 then begin
238+
ScreenCap := (WorkWidth * 2) div 3;
239+
if ScreenCap < MinimumWidth then
240+
Result := ScreenCap
241+
else
242+
Result := Min(Result, ScreenCap);
243+
end;
244+
Result := Max(240, Result);
245+
end;
246+
247+
function THeidiVirtualStringTree.WrapQtHintLongTokens(const S: String; MaxWidth: Integer): String;
248+
const
249+
BreakChars = '.,;:/\_-+=)]}>';
250+
251+
function WrapToken(Token: String): String;
252+
var
253+
CharCount, LowPos, HighPos, MidPos, FitPos, BreakPos, I: Integer;
254+
Prefix, C: String;
255+
begin
256+
Result := '';
257+
while (Token <> '') and (Canvas.TextWidth(Token) > MaxWidth) do begin
258+
CharCount := UTF8Length(Token);
259+
if CharCount <= 1 then
260+
Break;
261+
262+
LowPos := 1;
263+
HighPos := CharCount;
264+
FitPos := 1;
265+
while LowPos <= HighPos do begin
266+
MidPos := (LowPos + HighPos) div 2;
267+
Prefix := UTF8Copy(Token, 1, MidPos);
268+
if Canvas.TextWidth(Prefix) <= MaxWidth then begin
269+
FitPos := MidPos;
270+
LowPos := MidPos + 1;
271+
end
272+
else
273+
HighPos := MidPos - 1;
274+
end;
275+
276+
BreakPos := FitPos;
277+
for I := FitPos downto Max(1, (FitPos * 3) div 4) do begin
278+
C := UTF8Copy(Token, I, 1);
279+
if Pos(C, BreakChars) > 0 then begin
280+
BreakPos := I;
281+
Break;
282+
end;
283+
end;
284+
285+
Result := Result + UTF8Copy(Token, 1, BreakPos) + LineEnding;
286+
Token := UTF8Copy(Token, BreakPos + 1, CharCount - BreakPos);
287+
end;
288+
Result := Result + Token;
289+
end;
290+
291+
var
292+
I, TokenStart: Integer;
293+
Token: String;
294+
begin
295+
if (S = '') or (MaxWidth <= 0) then begin
296+
Result := S;
297+
Exit;
298+
end;
299+
300+
Result := '';
301+
TokenStart := 1;
302+
I := 1;
303+
while I <= Length(S) do begin
304+
if S[I] in [#9, #10, #13, ' '] then begin
305+
if I > TokenStart then begin
306+
Token := Copy(S, TokenStart, I - TokenStart);
307+
Result := Result + WrapToken(Token);
308+
end;
309+
Result := Result + S[I];
310+
Inc(I);
311+
TokenStart := I;
312+
end
313+
else
314+
Inc(I);
315+
end;
316+
if TokenStart <= Length(S) then begin
317+
Token := Copy(S, TokenStart, Length(S) - TokenStart + 1);
318+
Result := Result + WrapToken(Token);
319+
end;
320+
end;
321+
322+
procedure THeidiVirtualStringTree.CMHintShowPause(var Message: TCMHintShowPause);
323+
begin
324+
if Assigned(Message.Pause) and (Message.WasActive = 0) and
325+
(Message.Pause^ > QtHintInitialPauseMs) then
326+
Message.Pause^ := QtHintInitialPauseMs;
327+
Message.Result := 0;
328+
end;
329+
330+
procedure THeidiVirtualStringTree.CMHintShow(var Message: TCMHintShow);
331+
var
332+
MaxWidth: Integer;
333+
begin
334+
LastHintRect := Rect(0, 0, 0, 0);
335+
inherited;
336+
337+
if (Message.Result <> 0) or not Assigned(Message.HintInfo) then
338+
Exit;
339+
340+
MaxWidth := QtHintMaxWidth;
341+
Message.HintInfo^.HintMaxWidth := MaxWidth;
342+
Message.HintInfo^.HideTimeout := QtHintKeepAliveMs;
343+
Message.HintInfo^.ReshowTimeout := 0;
344+
Message.HintInfo^.HintStr := WrapQtHintLongTokens(Message.HintInfo^.HintStr, Max(1, MaxWidth - 16));
345+
end;
212346

213347
function THeidiVirtualStringTree.BlendQtColor(BaseColor, AccentColor: TColor;
214348
AccentPercent: Byte): TColor;

0 commit comments

Comments
 (0)