mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 06:39:31 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			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 := Max(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.
 | 
						|
 |