mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-07 16:58:48 +02:00

SynEdit: fix mark gutter, calculating width of mark-image ........ git-svn-id: branches/fixes_1_8@56241 -
218 lines
6.2 KiB
ObjectPascal
218 lines
6.2 KiB
ObjectPascal
unit SynGutterMarks;
|
|
|
|
{$I synedit.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Graphics, LCLType, LCLIntf, LCLProc, Controls, ImgList,
|
|
math, SynGutterBase, SynEditMiscClasses, SynEditMarks;
|
|
|
|
type
|
|
|
|
{ TSynGutterMarks }
|
|
|
|
TSynGutterMarks = class(TSynGutterPartBase)
|
|
private
|
|
FColumnCount: Integer;
|
|
FColumnWidth: Integer;
|
|
FDebugMarksImageIndex: Integer;
|
|
FInternalImage: TSynInternalImage;
|
|
FNoInternalImage: Boolean;
|
|
protected
|
|
FBookMarkOpt: TSynBookMarkOpt;
|
|
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;
|
|
|
|
property ColumnWidth: Integer read FColumnWidth; // initialized in Paint
|
|
property ColumnCount: Integer read FColumnCount;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
|
|
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer); override;
|
|
property DebugMarksImageIndex: Integer read FDebugMarksImageIndex write FDebugMarksImageIndex;
|
|
end;
|
|
|
|
implementation
|
|
uses
|
|
SynEdit;
|
|
|
|
|
|
{ TSynGutterMarks }
|
|
|
|
constructor TSynGutterMarks.Create(AOwner: TComponent);
|
|
begin
|
|
FInternalImage := nil;
|
|
FDebugMarksImageIndex := -1;
|
|
FNoInternalImage := False;
|
|
inherited Create(AOwner);
|
|
end;
|
|
|
|
procedure TSynGutterMarks.Init;
|
|
begin
|
|
inherited Init;
|
|
FBookMarkOpt := TCustomSynEdit(SynEdit).BookMarkOptions;
|
|
end;
|
|
|
|
function TSynGutterMarks.PreferedWidth: Integer;
|
|
begin
|
|
Result := 22 + FBookMarkOpt.LeftMargin
|
|
end;
|
|
|
|
destructor TSynGutterMarks.Destroy;
|
|
begin
|
|
FreeAndNil(FInternalImage);
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TSynGutterMarks.PaintMarks(aScreenLine: Integer; Canvas : TCanvas;
|
|
AClip : TRect; var aFirstCustomColumnIdx: integer): Boolean;
|
|
var
|
|
LineHeight: Integer;
|
|
|
|
procedure DoPaintMark(CurMark: TSynEditMark; aRect: TRect);
|
|
var
|
|
img: TCustomImageList;
|
|
begin
|
|
if CurMark.InternalImage or
|
|
( (not assigned(FBookMarkOpt.BookmarkImages)) and
|
|
(not assigned(CurMark.ImageList)) )
|
|
then begin
|
|
// draw internal image
|
|
if CurMark.ImageIndex in [0..9] then
|
|
begin
|
|
try
|
|
if (not Assigned(FInternalImage)) and (not FNoInternalImage) then
|
|
FInternalImage := TSynInternalImage.Create('SynEditInternalImages',10);
|
|
except
|
|
FNoInternalImage := True;
|
|
end;
|
|
if Assigned(FInternalImage) then
|
|
FInternalImage.DrawMark(Canvas, CurMark.ImageIndex, aRect.Left, aRect.Top,
|
|
LineHeight);
|
|
end;
|
|
end
|
|
else begin
|
|
// draw from ImageList
|
|
if assigned(CurMark.ImageList) then
|
|
img := CurMark.ImageList
|
|
else
|
|
img := FBookMarkOpt.BookmarkImages;
|
|
|
|
if (CurMark.ImageIndex <= img.Count) and (CurMark.ImageIndex >= 0) then begin
|
|
if LineHeight > img.Height then
|
|
aRect.Top := (aRect.Top + aRect.Bottom - img.Height) div 2;
|
|
|
|
img.Draw(Canvas, aRect.Left, aRect.Top, CurMark.ImageIndex, True);
|
|
end;
|
|
end
|
|
end;
|
|
|
|
var
|
|
j: Integer;
|
|
MLine: TSynEditMarkLine;
|
|
MarkRect: TRect;
|
|
LastMarkIsBookmark: Boolean;
|
|
begin
|
|
Result := False;
|
|
aFirstCustomColumnIdx := 0;
|
|
if FBookMarkOpt.DrawBookmarksFirst then
|
|
aFirstCustomColumnIdx := 1;
|
|
j := FoldView.TextIndex[aScreenLine];
|
|
if (j < 0) or (j >= TCustomSynEdit(SynEdit).Lines.Count) then
|
|
exit;
|
|
MLine := TCustomSynEdit(SynEdit).Marks.Line[j + 1];
|
|
if MLine = nil then
|
|
exit;
|
|
|
|
if FBookMarkOpt.DrawBookmarksFirst then
|
|
MLine.Sort(smsoBookmarkFirst, smsoPriority)
|
|
else
|
|
MLine.Sort(smsoBookMarkLast, smsoPriority);
|
|
|
|
LineHeight := TCustomSynEdit(SynEdit).LineHeight;
|
|
//Gutter.Paint always supplies AClip.Left = GutterPart.Left
|
|
MarkRect := Rect(AClip.Left + FBookMarkOpt.LeftMargin,
|
|
AClip.Top,
|
|
AClip.Left + FColumnWidth,
|
|
AClip.Top + LineHeight);
|
|
|
|
|
|
LastMarkIsBookmark := FBookMarkOpt.DrawBookmarksFirst;
|
|
for j := 0 to MLine.Count - 1 do begin
|
|
if (not MLine[j].Visible) or
|
|
(MLine[j].IsBookmark and (not FBookMarkOpt.GlyphsVisible))
|
|
then
|
|
continue;
|
|
|
|
if (MLine[j].IsBookmark <> LastMarkIsBookmark) and
|
|
(j = 0) and (FColumnCount > 1)
|
|
then begin
|
|
// leave one column empty
|
|
MarkRect.Left := MarkRect.Right;
|
|
MarkRect.Right := Min(MarkRect.Right + FColumnWidth, AClip.Right);
|
|
end;
|
|
|
|
DoPaintMark(MLine[j], MarkRect);
|
|
MarkRect.Left := MarkRect.Right;
|
|
MarkRect.Right := Max(MarkRect.Right + FColumnWidth, AClip.Right);
|
|
|
|
Result := Result or (not MLine[j].IsBookmark); // Line has a none-bookmark glyph
|
|
if (MLine[j].IsBookmark <> LastMarkIsBookmark) and
|
|
(not MLine[j].IsBookmark) and (j > 0)
|
|
then
|
|
aFirstCustomColumnIdx := j; // first none-bookmark column
|
|
|
|
if j >= ColumnCount then break;
|
|
LastMarkIsBookmark := MLine[j].IsBookmark;
|
|
end;
|
|
end;
|
|
|
|
procedure TSynGutterMarks.PaintLine(aScreenLine: Integer; Canvas: TCanvas; AClip: TRect);
|
|
var
|
|
aGutterOffs: Integer;
|
|
begin
|
|
aGutterOffs := 0;
|
|
PaintMarks(aScreenLine, Canvas, AClip, aGutterOffs);
|
|
end;
|
|
|
|
procedure TSynGutterMarks.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));
|
|
|
|
if assigned(FBookMarkOpt) and assigned(FBookMarkOpt.BookmarkImages) then
|
|
FColumnWidth := FBookMarkOpt.BookmarkImages.Width
|
|
else
|
|
FColumnWidth := Width;
|
|
FColumnCount := Max((Width+1) div FColumnWidth, 1); // full columns
|
|
|
|
rcLine := AClip;
|
|
rcLine.Bottom := rcLine.Top;
|
|
if FBookMarkOpt.GlyphsVisible and (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.
|
|
|