Skip to content

Commit 3d1254d

Browse files
committed
feat: icons, colors and padding in completion proposal
Refs #2534
1 parent 2171b58 commit 3d1254d

5 files changed

Lines changed: 149 additions & 37 deletions

File tree

source/apphelpers.pas

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,6 @@ TAppSettings = class(TObject)
423423
function GetThemeColor(Color: TColor): TColor;
424424
function ThemeIsDark: Boolean;
425425
function ProcessExists(pid: Cardinal; ExeNamePattern: String): Boolean;
426-
function SynCompletionProposalPrettyText(ImageIndex: Integer; LeftText, CenterText, RightText: String; LeftColor: TColor=-1; CenterColor: TColor=-1; RightColor: TColor=-1): String;
427426
function PopupComponent(Sender: TObject): TComponent;
428427
procedure FindComponentInstances(BaseForm: TComponent; ClassType: TClass; var List: TComponentList);
429428
function GetOS: String;
@@ -2874,19 +2873,6 @@ function ProcessExists(pid: Cardinal; ExeNamePattern: String): Boolean;
28742873
end;
28752874

28762875

2877-
function SynCompletionProposalPrettyText(ImageIndex: Integer; LeftText, CenterText, RightText: String;
2878-
LeftColor: TColor=-1; CenterColor: TColor=-1; RightColor: TColor=-1): String;
2879-
const
2880-
LineFormat = '\image{%d}\hspace{5}\color{%s}%s\column{}\color{%s}%s\hspace{10}\color{%s}\style{+i}%s';
2881-
begin
2882-
// Return formatted item string for a TSynCompletionProposal
2883-
if LeftColor = -1 then LeftColor := clGrayText;
2884-
if CenterColor = -1 then CenterColor := clWindowText;
2885-
if RightColor = -1 then RightColor := clGrayText;
2886-
Result := Format(LineFormat, [ImageIndex, ColorToString(LeftColor), LeftText, ColorToString(CenterColor), CenterText, ColorToString(RightColor), RightText]);
2887-
end;
2888-
2889-
28902876
function PopupComponent(Sender: TObject): TComponent;
28912877
var
28922878
Menu: TObject;

source/generic_types.pas

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ TAppColorSchemes = class(TObjectList<TAppColorScheme>)
5353
procedure ApplyDark;
5454
end;
5555

56+
TProposalItem = class(TObject)
57+
public
58+
InsertText: string;
59+
LeftText, CenterText, RightText: String;
60+
ImageIndex: Integer;
61+
LeftColor, CenterColor, RightColor: TColor;
62+
end;
63+
TProposalItemList = class(TObjectList<TProposalItem>)
64+
public
65+
function AddNew(InsertText: String; ImageIndex: Integer; LeftText, CenterText: String; RightText: String=''; LeftColor: TColor=-1): TProposalItem;
66+
end;
67+
5668
TFileExtImageIndex = record
5769
Ext: String;
5870
ImageIndex: Integer;
@@ -80,6 +92,7 @@ TFileExtImageIndex = record
8092
(Ext: 'sqlite3'; ImageIndex: 196)
8193
);
8294

95+
8396
var
8497
AppColorSchemes: TAppColorSchemes;
8598

@@ -344,6 +357,26 @@ procedure TAppColorSchemes.ApplyDark;
344357
end;
345358
end;
346359

360+
361+
function TProposalItemList.AddNew(InsertText: String; ImageIndex: Integer;
362+
LeftText, CenterText: String; RightText: String=''; LeftColor: TColor=-1): TProposalItem;
363+
begin
364+
Result := TProposalItem.Create;
365+
Result.InsertText := InsertText;
366+
Result.ImageIndex := ImageIndex;
367+
Result.LeftText := LeftText;
368+
Result.CenterText := CenterText;
369+
Result.RightText := RightText;
370+
if LeftColor = -1 then
371+
Result.LeftColor := clGrayText
372+
else
373+
Result.LeftColor := LeftColor;
374+
Result.CenterColor := clWindowText;
375+
Result.RightColor := clGrayText;
376+
Add(Result);
377+
end;
378+
379+
347380
initialization
348381

349382
SetJSONInstanceType(jitNumberFloat, TJSONFloatNumberUntouched);

source/lazaruscompat.pas

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ interface
66

77
uses
88
Classes, SysUtils, SynEdit, SynEditKeyCmds, SynEditHighlighter, laz.VirtualTrees,
9-
Graphics;
9+
Graphics, SynCompletion;
1010

1111
type
1212

@@ -27,6 +27,10 @@ TSynHighlighterAttributesHelper = class helper for TSynHighlighterAttributes
2727
public
2828
procedure AssignColorAndStyle(Source: TSynHighlighterAttributes);
2929
end;
30+
TSynCompletionHelper = class helper for TSynCompletion
31+
public
32+
function IndexFromVisibleIndex(AIndex: Integer): Integer;
33+
end;
3034

3135
TVTHeaderHelper = class helper for TVTHeader
3236
public
@@ -226,6 +230,12 @@ procedure TSynHighlighterAttributesHelper.AssignColorAndStyle(Source: TSynHighli
226230
Changed;
227231
end;
228232

233+
function TSynCompletionHelper.IndexFromVisibleIndex(AIndex: Integer): Integer;
234+
begin
235+
Result := PtrInt(ItemList.Objects[AIndex]);
236+
end;
237+
238+
229239
procedure TVTHeaderHelper.AutoFitColumnsWithHeaderMin;
230240
var
231241
cnv: TCanvas;

source/main.lfm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20346,13 +20346,16 @@ object MainForm: TMainForm
2034620346
end
2034720347
object SynCompletionProposal: TSynCompletion
2034820348
OnExecute = SynCompletionProposalExecute
20349+
OnPaintItem = SynCompletionProposalPaintItem
20350+
OnMeasureItem = SynCompletionProposalMeasureItem
2034920351
Position = -1
2035020352
LinesInWindow = 6
2035120353
OnSearchPosition = SynCompletionProposalSearchPosition
2035220354
OnPositionChanged = SynCompletionProposalChange
2035320355
SelectedColor = clHighlight
2035420356
CaseSensitive = False
20355-
Width = 262
20357+
Width = 350
20358+
LongLineHintTime = 500
2035620359
ShowSizeDrag = True
2035720360
AutoUseSingleIdent = False
2035820361
ShortCut = 16416

source/main.pas

Lines changed: 101 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,11 @@ TMainForm = class(TExtForm)
866866
procedure actDataCancelChangesExecute(Sender: TObject);
867867
procedure actExportDataExecute(Sender: TObject);
868868
procedure actDataPreviewExecute(Sender: TObject);
869+
function SynCompletionProposalMeasureItem(const AKey: string;
870+
ACanvas: TCanvas; Selected: boolean; Index: integer): TPoint;
871+
function SynCompletionProposalPaintItem(const AKey: string;
872+
ACanvas: TCanvas; X, Y: integer; Selected: boolean; Index: integer
873+
): boolean;
869874
procedure UpdatePreviewPanel;
870875
procedure actInsertFilesExecute(Sender: TObject);
871876
procedure actDataDeleteExecute(Sender: TObject);
@@ -1309,7 +1314,10 @@ TMainForm = class(TExtForm)
13091314
FCommandStatsQueryCount: Int64;
13101315
FCommandStatsServerUptime: Integer;
13111316
FVariableNames, FSessionVars, FGlobalVars: TStringList;
1312-
FProposalItems: TStringList;
1317+
FProposalItems: TProposalItemList;
1318+
FProposalCol1Width: Integer;
1319+
FProposalCol2Width: Integer;
1320+
FProposalCol3Width: Integer;
13131321
FProposalTriggeredByDot: Boolean;
13141322

13151323
procedure SetDelimiter(Value: String);
@@ -1794,6 +1802,7 @@ procedure TMainForm.FormDestroy(Sender: TObject);
17941802
AppSettings.WriteString(asDelimiter, FDelimiter);
17951803
AppSettings.WriteInt(asQuerymemoheight, ScaleFormToDesign(pnlQueryMemo.Height));
17961804
AppSettings.WriteInt(asQueryhelperswidth, ScaleFormToDesign(pnlQueryHelpers.Width));
1805+
// This saves a too small width (mostly 15), probably because the proposal is not visible now:
17971806
AppSettings.WriteInt(asCompletionProposalWidth, ScaleFormToDesign(SynCompletionProposal.Width));
17981807
AppSettings.WriteInt(asCompletionProposalNbLinesInWindow, SynCompletionProposal.LinesInWindow);
17991808
AppSettings.WriteInt(asDbtreewidth, ScaleFormToDesign(pnlLeft.width));
@@ -2071,9 +2080,9 @@ procedure TMainForm.FormCreate(Sender: TObject);
20712080
// We already store and restore the dimensions DPI aware.
20722081
{SynCompletionProposal.Form.Scaled := False;
20732082
SynCompletionProposal.TimerInterval := AppSettings.ReadInt(asCompletionProposalInterval);}
2074-
SynCompletionProposal.Width := Min(AppSettings.ReadInt(asCompletionProposalWidth), 1000);
2083+
//SynCompletionProposal.Width := AppSettings.ReadInt(asCompletionProposalWidth);
20752084
SynCompletionProposal.LinesInWindow := AppSettings.ReadInt(asCompletionProposalNbLinesInWindow);
2076-
FProposalItems := TStringList.Create;
2085+
FProposalItems := TProposalItemList.Create;
20772086
FProposalTriggeredByDot := False;
20782087

20792088
// Place progressbar on the statusbar
@@ -3586,6 +3595,85 @@ procedure TMainForm.actDataPreviewExecute(Sender: TObject);
35863595
UpdatePreviewPanel;
35873596
end;
35883597

3598+
function TMainForm.SynCompletionProposalMeasureItem(const AKey: string;
3599+
ACanvas: TCanvas; Selected: boolean; Index: integer): TPoint;
3600+
var
3601+
i, X, Y: Integer;
3602+
It: TProposalItem;
3603+
begin
3604+
FProposalCol1Width := 0;
3605+
FProposalCol2Width := 0;
3606+
3607+
ACanvas.Font.Style := [fsBold];
3608+
for i := 0 to SynCompletionProposal.ItemList.Count - 1 do
3609+
begin
3610+
It := FProposalItems[SynCompletionProposal.IndexFromVisibleIndex(i)];
3611+
FProposalCol1Width := Max(FProposalCol1Width, ACanvas.TextWidth(It.LeftText));
3612+
end;
3613+
3614+
ACanvas.Font.Style := [fsItalic];
3615+
for i := 0 to SynCompletionProposal.ItemList.Count - 1 do
3616+
begin
3617+
It := FProposalItems[SynCompletionProposal.IndexFromVisibleIndex(i)];
3618+
FProposalCol2Width := Max(FProposalCol2Width, ACanvas.TextWidth(It.CenterText));
3619+
end;
3620+
3621+
//if SynCompletionProposal.Width < 100 then begin
3622+
// SynCompletionProposal.Width := ImageListMain.Width + FProposalCol1Width + FProposalCol2Width + 100;
3623+
//end;
3624+
3625+
ACanvas.Font.Style := [];
3626+
It := FProposalItems[SynCompletionProposal.IndexFromVisibleIndex(Index)];
3627+
X := ImageListMain.Width + 5 + FProposalCol1Width + 10;
3628+
if It.RightText.IsEmpty then
3629+
Inc(X, ACanvas.TextWidth(It.CenterText))
3630+
else
3631+
Inc(X, FProposalCol2Width + 10 + ACanvas.TextWidth(It.RightText));
3632+
Y := Max(ImageListMain.Height, ACanvas.TextHeight('Wy')) + 4;
3633+
Result := Point(X, Y);
3634+
end;
3635+
3636+
function TMainForm.SynCompletionProposalPaintItem(const AKey: string;
3637+
ACanvas: TCanvas; X, Y: integer; Selected: boolean; Index: integer): boolean;
3638+
var
3639+
It: TProposalItem;
3640+
X1, X2, X3: Integer;
3641+
begin
3642+
It := FProposalItems[SynCompletionProposal.IndexFromVisibleIndex(Index)];
3643+
3644+
if (It.ImageIndex >= 0) and (It.ImageIndex < ImageListMain.Count) then
3645+
ImageListMain.Draw(ACanvas, X + 4, Y + 2, It.ImageIndex, True);
3646+
3647+
X1 := X + ImageListMain.Width + 5;
3648+
X2 := X1 + FProposalCol1Width + 10;
3649+
X3 := X2 + FProposalCol2Width + 10;
3650+
3651+
ACanvas.Brush.Style := bsClear;
3652+
3653+
ACanvas.Font.Style := [];
3654+
if Selected then
3655+
ACanvas.Font.Color := clWhite
3656+
else
3657+
ACanvas.Font.Color := It.LeftColor;
3658+
ACanvas.TextOut(X1, Y + 1, It.LeftText);
3659+
3660+
ACanvas.Font.Style := [];
3661+
if Selected then
3662+
ACanvas.Font.Color := clWhite
3663+
else
3664+
ACanvas.Font.Color := It.CenterColor;
3665+
ACanvas.TextOut(X2, Y + 1, It.CenterText);
3666+
3667+
ACanvas.Font.Style := [fsItalic];
3668+
if Selected then
3669+
ACanvas.Font.Color := clWhite
3670+
else
3671+
ACanvas.Font.Color := It.RightColor;
3672+
ACanvas.TextOut(X3, Y + 1, It.RightText);
3673+
3674+
Result := True;
3675+
end;
3676+
35893677

35903678
procedure TMainForm.UpdatePreviewPanel;
35913679
var
@@ -6832,7 +6920,6 @@ procedure TMainForm.SynCompletionProposalExecute(Sender: TObject);
68326920
Conn: TDBConnection;
68336921
RoutineEditor: TfrmRoutineEditor;
68346922
Param: TRoutineParam;
6835-
DisplayText: String;
68366923
SQLFunc: TSQLFunction;
68376924
DummyPos: Integer=0;
68386925

@@ -6857,8 +6944,7 @@ procedure TMainForm.SynCompletionProposalExecute(Sender: TObject);
68576944
FuncParams.Free;
68586945
end;
68596946

6860-
DisplayText := SynCompletionProposalPrettyText(Obj.ImageIndex, _(LowerCase(Obj.ObjType)), Obj.Name, FunctionDeclaration);
6861-
FProposalItems.Add(Obj.Name+FunctionDeclaration);
6947+
FProposalItems.AddNew(Obj.Name+FunctionDeclaration, Obj.ImageIndex, _(LowerCase(Obj.ObjType)), Obj.Name, FunctionDeclaration);
68626948
end;
68636949

68646950
procedure AddColumns(const LeftToken: String);
@@ -6897,11 +6983,10 @@ procedure TMainForm.SynCompletionProposalExecute(Sender: TObject);
68976983
end;
68986984
end;
68996985
// Put formatted text and icon into proposal
6900-
DisplayText := SynCompletionProposalPrettyText(ColumnIcon, LowerCase(Col.DataType.Name), Col.Name, Col.Comment, AppColorSchemes.First.GridNullColors[Col.DataType.Category]);
69016986
//if CurrentInput.StartsWith(Conn.QuoteChar) then
69026987
// Proposal.ItemList.Add(Conn.QuoteChar + Col.Name)
69036988
//else
6904-
FProposalItems.Add(Col.Name);
6989+
FProposalItems.AddNew(Col.Name, ColumnIcon, LowerCase(Col.DataType.Name), Col.Name, Col.Comment, AppColorSchemes.First.GridNullColors[Col.DataType.Category]);
69056990
Inc(ColumnsInList);
69066991
end;
69076992
Columns.Free;
@@ -6942,8 +7027,7 @@ procedure TMainForm.SynCompletionProposalExecute(Sender: TObject);
69427027
try
69437028
Results := Conn.GetResults('SHOW '+UpperCase(rx.Match[1])+' VARIABLES');
69447029
while not Results.Eof do begin
6945-
DisplayText := SynCompletionProposalPrettyText(ICONINDEX_PRIMARYKEY, _('Variable'), Results.Col(0), StringReplace(Results.Col(1), '\', '\\', [rfReplaceAll]));
6946-
FProposalItems.Add(Results.Col(1));
7030+
FProposalItems.AddNew(Results.Col(1), ICONINDEX_PRIMARYKEY, _('Variable'), Results.Col(0), StringReplace(Results.Col(1), '\', '\\', [rfReplaceAll]));
69477031
Results.Next;
69487032
end;
69497033
except
@@ -7039,8 +7123,7 @@ procedure TMainForm.SynCompletionProposalExecute(Sender: TObject);
70397123

70407124
// All databases
70417125
for i:=0 to Conn.AllDatabases.Count-1 do begin
7042-
DisplayText := SynCompletionProposalPrettyText(ICONINDEX_DB, _('database'), Conn.AllDatabases[i], '');
7043-
FProposalItems.Add(Conn.AllDatabases[i]);
7126+
FProposalItems.AddNew(Conn.AllDatabases[i], ICONINDEX_DB, _('database'), Conn.AllDatabases[i]);
70447127
end;
70457128

70467129
// Tables from current db
@@ -7056,15 +7139,13 @@ procedure TMainForm.SynCompletionProposalExecute(Sender: TObject);
70567139

70577140
// Functions
70587141
for SQLFunc in Conn.SQLFunctions do begin
7059-
DisplayText := SynCompletionProposalPrettyText(ICONINDEX_FUNCTION, _('function'), SQLFunc.Name, SQLFunc.Declaration);
7060-
FProposalItems.Add(SQLFunc.Name + SQLFunc.Declaration);
7142+
FProposalItems.AddNew(SQLFunc.Name + SQLFunc.Declaration, ICONINDEX_FUNCTION, _('function'), SQLFunc.Name, SQLFunc.Declaration);
70617143
end;
70627144

70637145

70647146
// Keywords
70657147
for i:=0 to MySQLKeywords.Count-1 do begin
7066-
DisplayText := SynCompletionProposalPrettyText(ICONINDEX_KEYWORD, _('keyword'), MySQLKeywords[i], '');
7067-
FProposalItems.Add(MySQLKeywords[i]);
7148+
FProposalItems.AddNew(MySQLKeywords[i], ICONINDEX_KEYWORD, _('keyword'), MySQLKeywords[i]);
70687149
end;
70697150

70707151
// Procedure params
@@ -7075,8 +7156,7 @@ procedure TMainForm.SynCompletionProposalExecute(Sender: TObject);
70757156
else if Param.Context = 'OUT' then ImageIndex := 121
70767157
else if Param.Context = 'INOUT' then ImageIndex := 122
70777158
else ImageIndex := -1;
7078-
DisplayText := SynCompletionProposalPrettyText(ImageIndex, Param.Datatype, Param.Name, '');
7079-
FProposalItems.Add(Param.Name);
7159+
FProposalItems.AddNew(Param.Name, ImageIndex, Param.Datatype, Param.Name);
70807160
end;
70817161
end;
70827162

@@ -7105,10 +7185,10 @@ procedure TMainForm.SynCompletionProposalSearchPosition(var APosition: integer);
71057185
//logsql('SynCompletionProposalSearchPosition CurrentString:'+CurrentStr+' StartsText:');
71067186
for i:=0 to FProposalItems.Count-1 do begin
71077187
if CurrentStr.IsEmpty
7108-
or (SearchOnMid and LowerCase(FProposalItems[i]).Contains(LowerCase(CurrentStr)))
7109-
or ((not SearchOnMid) and LazStartsText(CurrentStr, FProposalItems[i]))
7188+
or (SearchOnMid and LowerCase(FProposalItems[i].InsertText).Contains(LowerCase(CurrentStr)))
7189+
or ((not SearchOnMid) and LazStartsText(CurrentStr, FProposalItems[i].InsertText))
71107190
then
7111-
Proposal.ItemList.Add(FProposalItems[i]);
7191+
Proposal.ItemList.AddObject(FProposalItems[i].InsertText, TObject(PtrInt(i)));
71127192
end;
71137193
Proposal.ItemList.EndUpdate;
71147194
end;

0 commit comments

Comments
 (0)