mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-06-06 02:38:14 +02:00
194 lines
5.5 KiB
ObjectPascal
194 lines
5.5 KiB
ObjectPascal
unit SynGutterMarks;
|
|
|
|
{$I synedit.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Graphics, LCLType, LCLIntf, SynGutterBase,
|
|
SynEditMiscClasses, SynEditMiscProcs, SynEditFoldedView, SynEditMarks;
|
|
|
|
type
|
|
|
|
{ TSynGutterMarks }
|
|
|
|
TSynGutterMarks = class(TSynGutterPartBase)
|
|
private
|
|
FDebugMarksImageIndex: Integer;
|
|
FFoldView: TSynEditFoldedView;
|
|
FBookMarkOpt: TSynBookMarkOpt;
|
|
FInternalImage: TSynInternalImage;
|
|
protected
|
|
procedure DoChange(Sender: TObject); override;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer); override;
|
|
function RealGutterWidth(CharWidth: integer): integer; override;
|
|
property DebugMarksImageIndex: Integer read FDebugMarksImageIndex write FDebugMarksImageIndex;
|
|
end;
|
|
|
|
implementation
|
|
uses
|
|
SynEdit;
|
|
|
|
|
|
{ TSynGutterMarks }
|
|
|
|
procedure TSynGutterMarks.DoChange(Sender: TObject);
|
|
begin
|
|
if AutoSize then
|
|
FWidth := RealGutterWidth(0);
|
|
inherited DoChange(Sender);
|
|
end;
|
|
|
|
constructor TSynGutterMarks.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FFoldView := Gutter.FoldView;
|
|
FBookMarkOpt := TSynEdit(SynEdit).BookMarkOptions;
|
|
FInternalImage := nil;
|
|
FDebugMarksImageIndex := -1;
|
|
|
|
FWidth := 23;
|
|
end;
|
|
|
|
destructor TSynGutterMarks.Destroy;
|
|
begin
|
|
FreeAndNil(FInternalImage);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TSynGutterMarks.RealGutterWidth(CharWidth: integer) : integer;
|
|
begin
|
|
if Visible then
|
|
Result := 22 + FBookMarkOpt.LeftMargin
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
procedure TSynGutterMarks.Paint(Canvas : TCanvas; AClip : TRect; FirstLine, LastLine : integer);
|
|
var
|
|
i, j, iLine: integer;
|
|
aGutterOffs: PIntArray;
|
|
dc: HDC;
|
|
LineHeight: Integer;
|
|
Marks: TSynEditMarks;
|
|
HasAnyMark: Boolean;
|
|
|
|
procedure DrawMark(CurMark: TSynEditMark);
|
|
var
|
|
iLine: integer;
|
|
itop : Longint;
|
|
begin
|
|
iTop := 0;
|
|
if (CurMark.Line<1) or (CurMark.Line > SynEdit.Lines.Count) then exit;
|
|
if FFoldView.FoldedAtTextIndex[CurMark.Line-1] then exit;
|
|
iLine := FFoldView.TextIndexToScreenLine(CurMark.Line-1);
|
|
if iLine < 0 then Exit;
|
|
|
|
if Assigned(FBookMarkOpt.BookmarkImages) and not CurMark.InternalImage then
|
|
begin
|
|
if (CurMark.ImageIndex <= FBookMarkOpt.BookmarkImages.Count) and
|
|
(CurMark.ImageIndex >= 0) then
|
|
begin
|
|
if CurMark.IsBookmark = FBookMarkOpt.DrawBookmarksFirst then
|
|
aGutterOffs^[iLine] := AClip.Left
|
|
else
|
|
if aGutterOffs^[iLine] = 0 then
|
|
aGutterOffs^[iLine] := FBookMarkOpt.BookmarkImages.Width + AClip.Left;
|
|
if LineHeight > FBookMarkOpt.BookmarkImages.Height then
|
|
iTop := (LineHeight - FBookMarkOpt.BookmarkImages.Height) div 2;
|
|
with FBookMarkOpt do
|
|
BookmarkImages.Draw(Canvas, LeftMargin + aGutterOffs^[iLine],
|
|
iTop + iLine * LineHeight, CurMark.ImageIndex, True);
|
|
|
|
Inc(aGutterOffs^[iLine], FBookMarkOpt.BookmarkImages.Width);
|
|
end;
|
|
end
|
|
else
|
|
begin
|
|
if CurMark.ImageIndex in [0..9] then
|
|
begin
|
|
if not Assigned(FInternalImage) then
|
|
FInternalImage := TSynInternalImage.Create('SynEditInternalImages',10);
|
|
if aGutterOffs^[iLine] = 0 then
|
|
aGutterOffs^[iLine] := AClip.Left;
|
|
FInternalImage.DrawMark(Canvas, CurMark.ImageIndex,
|
|
FBookMarkOpt.LeftMargin + aGutterOffs^[iLine], iLine * LineHeight,
|
|
LineHeight);
|
|
Inc(aGutterOffs^[iLine], FBookMarkOpt.Xoffset);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure DrawDebugMark(Line: Integer);
|
|
var
|
|
itop : Longint;
|
|
begin
|
|
iTop := 0;
|
|
if Line < 0 then Exit;
|
|
if Assigned(FBookMarkOpt.BookmarkImages) and
|
|
(DebugMarksImageIndex <= FBookMarkOpt.BookmarkImages.Count) and
|
|
(DebugMarksImageIndex >= 0) then
|
|
begin
|
|
if not FBookMarkOpt.DrawBookmarksFirst then
|
|
aGutterOffs^[Line] := AClip.Left
|
|
else
|
|
if aGutterOffs^[Line] = 0 then
|
|
aGutterOffs^[Line] := FBookMarkOpt.BookmarkImages.Width + AClip.Left;
|
|
if LineHeight > FBookMarkOpt.BookmarkImages.Height then
|
|
iTop := (LineHeight - FBookMarkOpt.BookmarkImages.Height) div 2;
|
|
with FBookMarkOpt do
|
|
BookmarkImages.Draw(Canvas, LeftMargin + aGutterOffs^[Line],
|
|
iTop + Line * LineHeight, DebugMarksImageIndex, True);
|
|
|
|
Inc(aGutterOffs^[Line], FBookMarkOpt.BookmarkImages.Width);
|
|
end
|
|
end;
|
|
|
|
begin
|
|
if not Visible then exit;
|
|
LineHeight := TSynEdit(SynEdit).LineHeight;
|
|
if MarkupInfo.Background <> clNone then
|
|
Canvas.Brush.Color := MarkupInfo.Background
|
|
else
|
|
Canvas.Brush.Color := Gutter.Color;
|
|
dc := Canvas.Handle;
|
|
{$IFDEF SYN_LAZARUS}
|
|
LCLIntf.SetBkColor(dc,Canvas.Brush.Color);
|
|
{$ENDIF}
|
|
|
|
|
|
// now the gutter marks
|
|
if FBookMarkOpt.GlyphsVisible and (LastLine >= FirstLine) then
|
|
begin
|
|
aGutterOffs := AllocMem((LastLine + 1) * SizeOf(integer));
|
|
try
|
|
for i := FirstLine to LastLine do
|
|
begin
|
|
iLine := FFoldView.TextIndex[i] + 1;
|
|
TSynEdit(SynEdit).Marks.GetMarksForLine(iLine, Marks);
|
|
HasAnyMark := False;
|
|
for j := Low(Marks) to High(Marks) do
|
|
begin
|
|
if Marks[j] = nil then
|
|
break;
|
|
if not Marks[j].Visible then
|
|
continue;
|
|
DrawMark(Marks[j]);
|
|
HasAnyMark := HasAnyMark or not Marks[j].IsBookmark;
|
|
end;
|
|
if not HasAnyMark and TSynEdit(SynEdit).HasDebugMark(iLine) then
|
|
DrawDebugMark(i);
|
|
end;
|
|
finally
|
|
FreeMem(aGutterOffs);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|