replace the gutter markspart with a simpler equivalent

more adapted to multiple and dynamic columns
This commit is contained in:
Basile Burg 2021-04-15 02:38:33 +02:00
parent b0da20f068
commit 2b1ef5b439
4 changed files with 193 additions and 6 deletions

View File

@ -7,6 +7,8 @@
## Bugs fixed
- editor, gutter: cases where warnings icons were not always updated. (#80)
- editor, gutter: prevent overlap of icons. first column is used for D-Scanner, second and third for debugging.
## Other
- D2 highlighter: remove the keywords `body` (deprecated), `typedef` (deprecated), `macro` (unused).

View File

@ -549,7 +549,7 @@
<PackageName Value="LCL"/>
</Item8>
</RequiredPackages>
<Units Count="61">
<Units Count="62">
<Unit0>
<Filename Value="dexed.lpr"/>
<IsPartOfProject Value="True"/>
@ -870,6 +870,10 @@
<Filename Value="..\src\u_dexed_d.pas"/>
<IsPartOfProject Value="True"/>
</Unit60>
<Unit61>
<Filename Value="..\src\u_synmultiguttermarks.pas"/>
<IsPartOfProject Value="True"/>
</Unit61>
</Units>
</ProjectOptions>
<CompilerOptions>

View File

@ -10,11 +10,12 @@ uses
SynHighlighterLFM, SynEditHighlighter, SynEditMouseCmds, SynEditFoldedView,
SynEditMarks, SynEditTypes, SynHighlighterJScript, SynBeautifier, dialogs,
md5, Spin, LCLIntf, LazFileUtils, LMessages, SynHighlighterCpp, math,
SynGutterMarks, SynGutterBase,
//SynEditMarkupFoldColoring,
Clipbrd, fpjson, jsonparser, LazUTF8, LazUTF8Classes, Buttons, StdCtrls,
u_common, u_writableComponent, u_d2syn, u_txtsyn, u_dialogs,
u_sharedres, u_dlang, u_stringrange, u_dbgitf, u_observer, u_diff,
u_processes;
u_processes, u_synmultiguttermarks;
type
@ -253,6 +254,7 @@ type
fDscannerEnabled: boolean;
fScrollPreview: boolean;
fDiffDialogWillClose: boolean;
fMultiGutterMarks: TSynMultiGutterMarks;
procedure showHintEvent(Sender: TObject; HintInfo: PHintInfo);
procedure setGutterTransparent(value: boolean);
procedure decCallTipsLvl;
@ -1153,9 +1155,18 @@ begin
fModified := false;
TextBuffer.AddNotifyHandler(senrUndoRedoAdded, @changeNotify);
Gutter.MarksPart.AutoSize:=false;
Gutter.MarksPart.Width := ScaleX(20,96);
Gutter.MarksPart.Visible:=false;
fMultiGutterMarks := TSynMultiGutterMarks.Create(Gutter.Parts);
fMultiGutterMarks.columnCount := 2;
fMultiGutterMarks.columnWidth := ScaleX(20,96);
fMultiGutterMarks.AutoSize := true;
fMultiGutterMarks.Index := 1;
fImages := TImageList.Create(self);
fMultiGutterMarks.images := fImages;
z := GetIconScaledSize;
case z of
iss16:
@ -3901,7 +3912,7 @@ var
p: TPoint;
begin
p := ScreenToClient(mouse.CursorPos);
if p.x > Gutter.MarksPart.Width then
if p.x > fMultiGutterMarks.Width then
exit;
p := self.PixelsToRowColumn(p);
showWarningForLine(p.y);
@ -3935,6 +3946,19 @@ begin
exit(true);
end;
function gutterIconKindToColumn(value: TGutterIcon): integer;
begin
case value of
giBreakSet : result := 1;
giBulletGreen : result := 2;
giBulletBlack : result := 2;
giBreakReached : result := 2;
giStep : result := 2;
giWatch : result := 2;
giWarn : result := 0;
end;
end;
function TDexedMemo.findBreakPoint(line: integer): boolean;
begin
result := isGutterIconSet(line, giBreakSet);
@ -3963,7 +3987,8 @@ begin
begin
n := m.Items[i];
s := n.ImageIndex = longint(value);
n.Visible := s;
if s then
n.Visible := true;
end;
if not s then
begin
@ -3972,6 +3997,7 @@ begin
n.ImageList := fImages;
n.ImageIndex := longint(value);
n.Visible := true;
n.Column:= gutterIconKindToColumn(value);
Marks.Add(n);
end;
end;
@ -4001,6 +4027,7 @@ var
i: integer;
m: TSynEditMark;
begin
fMultiGutterMarks.columnCount := 3;
fDebugger := debugger;
fDebugger.removeBreakPoints(fileName);
for i := 0 to marks.count - 1 do
@ -4013,6 +4040,7 @@ end;
procedure TDexedMemo.debugStop;
begin
fMultiGutterMarks.columnCount := 2;
removeDebugTimeMarks;
end;
@ -4042,6 +4070,8 @@ begin
if fname <> fFilename then
exit;
showPage;
// newly opened source has not 3 cols yet
fMultiGutterMarks.columnCount := 3;
caretY := line;
EnsureCursorPosVisible;
removeDebugTimeMarks;

View File

@ -0,0 +1,151 @@
unit u_synmultiguttermarks;
{$I u_defines.inc}
interface
uses
Classes, SysUtils, Graphics, LCLType, LCLIntf, LCLProc, Controls, ImgList,
math, SynGutterBase, SynEditMiscClasses, SynEditMarks;
type
TSynMultiGutterMarks = class(TSynGutterPartBase)
private
fColumnCount: Integer;
fColumnWidth: Integer;
fImages: TCustomImageList;
procedure setColumnCount(value: integer);
procedure setColumnWidth(value: integer);
procedure setImages(value: TCustomImageList);
protected
procedure Init; override;
function PreferedWidth: Integer; override;
// PaintMarks: True, if it has any Mark, that is *not* a bookmark
function PaintMarks(aScreenLine: Integer; Canvas : TCanvas; AClip : TRect;
var aFirstCustomColumnIdx: integer): Boolean;
Procedure PaintLine(aScreenLine: Integer; Canvas : TCanvas; AClip : TRect); virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer); override;
property columnWidth: integer read fColumnWidth write SetColumnWidth;
property columnCount: integer read fColumnCount write setColumnCount;
property images: TCustomImageList read fImages write setImages;
end;
implementation
uses
SynEdit;
constructor TSynMultiGutterMarks.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
destructor TSynMultiGutterMarks.Destroy;
begin
inherited Destroy;
end;
procedure TSynMultiGutterMarks.Init;
begin
inherited Init;
end;
function TSynMultiGutterMarks.PreferedWidth: Integer;
begin
Result := ScaleX(20, 96) * fColumnCount;
end;
procedure TSynMultiGutterMarks.setColumnCount(value: integer);
begin
if value = fColumnCount then
exit;
fColumnCount := value;
TCustomSynEdit(SynEdit).Gutter.DoAutoSize();
end;
procedure TSynMultiGutterMarks.setColumnWidth(value: integer);
begin
fColumnWidth := value;
end;
procedure TSynMultiGutterMarks.setImages(value: TCustomImageList);
begin
fImages := value;
end;
function TSynMultiGutterMarks.PaintMarks(aScreenLine: Integer; Canvas : TCanvas;
AClip : TRect; var aFirstCustomColumnIdx: integer): Boolean;
var
markLine: TSynEditMarkLine;
markRect: TRect;
mark : TSynEditMark;
i, h, w : integer;
begin
Result := False;
aFirstCustomColumnIdx := 0;
i := FoldView.TextIndex[aScreenLine];
if (i < 0) or (i >= TCustomSynEdit(SynEdit).Lines.Count) then
exit;
markLine := TCustomSynEdit(SynEdit).Marks.Line[i + 1];
if markLine = nil then
exit;
h := TCustomSynEdit(SynEdit).LineHeight;
w := ScaleX(20, 96);
for i := 0 to markLine.Count - 1 do
begin
mark := markLine[i];
if (not mark.visible) or (mark.ImageIndex = -1) or (mark.ImageList = nil) then
continue;
markRect := Rect(AClip.Left + 2 + mark.Column * w, AClip.Top, AClip.Left + 500, AClip.Top + h);
mark.ImageList.draw(canvas, markRect.Left, markRect.Top, mark.ImageIndex);
Result := true;
end;
end;
procedure TSynMultiGutterMarks.PaintLine(aScreenLine: Integer; Canvas: TCanvas; AClip: TRect);
var
aGutterOffs: Integer;
begin
aGutterOffs := 0;
PaintMarks(aScreenLine, Canvas, AClip, aGutterOffs);
end;
procedure TSynMultiGutterMarks.Paint(Canvas : TCanvas; AClip : TRect; FirstLine, LastLine : integer);
var
i: integer;
LineHeight: Integer;
rcLine: TRect;
begin
if not Visible then exit;
if MarkupInfo.Background <> clNone then
Canvas.Brush.Color := MarkupInfo.Background
else
Canvas.Brush.Color := Gutter.Color;
LCLIntf.SetBkColor(Canvas.Handle, TColorRef(Canvas.Brush.Color));
rcLine := AClip;
rcLine.Bottom := rcLine.Top;
if (LastLine >= FirstLine) then
begin
LineHeight := TCustomSynEdit(SynEdit).LineHeight;
for i := FirstLine to LastLine do begin
rcLine.Top := rcLine.Bottom;
rcLine.Bottom := Min(AClip.Bottom, rcLine.Top + LineHeight);
PaintLine(i, Canvas, rcLine);
end;
end;
end;
end.
end.