diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7373f1fc..7e4a40fd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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).
diff --git a/lazproj/dexed.lpi b/lazproj/dexed.lpi
index dc73ed7e..e6f23484 100644
--- a/lazproj/dexed.lpi
+++ b/lazproj/dexed.lpi
@@ -549,7 +549,7 @@
-
+
@@ -870,6 +870,10 @@
+
+
+
+
diff --git a/src/u_synmemo.pas b/src/u_synmemo.pas
index 8b3956ca..1136bcf9 100644
--- a/src/u_synmemo.pas
+++ b/src/u_synmemo.pas
@@ -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;
diff --git a/src/u_synmultiguttermarks.pas b/src/u_synmultiguttermarks.pas
new file mode 100644
index 00000000..7d7fd5d7
--- /dev/null
+++ b/src/u_synmultiguttermarks.pas
@@ -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.
+