diff --git a/components/synedit/syneditmarks.pp b/components/synedit/syneditmarks.pp index 257d9f0e83..a6d21aeebb 100644 --- a/components/synedit/syneditmarks.pp +++ b/components/synedit/syneditmarks.pp @@ -5,7 +5,7 @@ unit SynEditMarks; interface uses - Classes, SysUtils, math, SynEditMiscClasses, SynEditTextBase, LCLProc; + Classes, Controls, SysUtils, math, SynEditMiscClasses, SynEditTextBase, LCLProc; const // Max number of book/gutter marks returned from GetEditMarksForLine - that @@ -50,6 +50,7 @@ type TSynEditMark = class private + FImageList: TImageList; FMarkLine: TSynEditMarkLine; FMarkList: TSynEditMarkList; FLine: Integer; // Only valid, if not part of a TSynEditMarkLine @@ -86,15 +87,24 @@ type procedure DecChangeLock; property OwnerEdit: TSynEditBase read FOwnerEdit write SetOwnerEdit; + + property OldLine: integer read FOldLine; // not used, if synedit insert/delete lines property Line: integer read GetLine write SetLine; - property OldLine: integer read FOldLine; property Column: integer read FColumn write SetColumn; property Priority: integer read FPriority write SetPriority; - property ImageIndex: integer read FImage write SetImage; - property BookmarkNumber: integer read FBookmarkNum write fBookmarkNum; property Visible: boolean read FVisible write SetVisible; - property InternalImage: boolean read FInternalImage write SetInternalImage; + + property BookmarkNumber: integer read FBookmarkNum write fBookmarkNum; property IsBookmark: boolean read GetIsBookmark; + + // InternalImage: Use Internal bookmark image 0..9; + // Ignore "BookMarkOpt.BookmarkImages" or "ImageList" + property InternalImage: boolean read FInternalImage write SetInternalImage; + // ImageIndex: Index in "BookMarkOpt.BookmarkImages" or "ImageList" + property ImageIndex: integer read FImage write SetImage; + // ImageList: If assigned, then use instead of "BookMarkOpt.BookmarkImages" + // Must have same width as "BookMarkOpt.BookmarkImages" + property ImageList: TImageList read FImageList write FImageList; end; { TSynEditMarkLine } @@ -574,7 +584,7 @@ end; function CompareSynEditMarks(Mark1, Mark2: Pointer): Integer; var m1: TSynEditMark absolute Mark1; - m2: TSynEditMark absolute Mark1; + m2: TSynEditMark absolute Mark2; begin case m1.MarkLine.FCurrentSort1 of smsoColumn: Result := m2.Column - m1.Column; @@ -633,7 +643,7 @@ begin exit; FCurrentSort1 := PrimaryOrder; - FCurrentSort1 := SecondaryOrder; + FCurrentSort2 := SecondaryOrder; if PrimaryOrder = smsoUnsorted then exit; diff --git a/components/synedit/synguttermarks.pp b/components/synedit/synguttermarks.pp index 91e4c62f20..a0df3f7e24 100644 --- a/components/synedit/synguttermarks.pp +++ b/components/synedit/synguttermarks.pp @@ -5,8 +5,8 @@ unit SynGutterMarks; interface uses - Classes, SysUtils, Graphics, LCLType, LCLIntf, LCLProc, SynGutterBase, - SynEditMiscClasses, SynEditMarks; + Classes, SysUtils, Graphics, LCLType, LCLIntf, LCLProc, Controls, math, + SynGutterBase, SynEditMiscClasses, SynEditMarks; type @@ -14,6 +14,8 @@ type TSynGutterMarks = class(TSynGutterPartBase) private + FColumnCount: Integer; + FColumnWidth: Integer; FDebugMarksImageIndex: Integer; FInternalImage: TSynInternalImage; protected @@ -22,8 +24,11 @@ type 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 aGutterOffs: integer): Boolean; + var aFirstCustomColumnIdx: integer): Boolean; Procedure PaintLine(aScreenLine: Integer; Canvas : TCanvas; AClip : TRect); virtual; + + property ColumnWidth: Integer read FColumnWidth; + property ColumnCount: Integer read FColumnCount; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; @@ -64,74 +69,97 @@ begin end; function TSynGutterMarks.PaintMarks(aScreenLine: Integer; Canvas : TCanvas; - AClip : TRect; var aGutterOffs: integer): Boolean; + AClip : TRect; var aFirstCustomColumnIdx: integer): Boolean; var LineHeight: Integer; - procedure DoPaintMark(CurMark: TSynEditMark); + procedure DoPaintMark(CurMark: TSynEditMark; aRect: TRect); var - itop : Longint; + img: TImageList; begin - iTop := 0; - 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 := AClip.Left - else - if aGutterOffs = 0 then - aGutterOffs := 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, - iTop + aScreenLine * LineHeight, CurMark.ImageIndex, True); - - Inc(aGutterOffs, FBookMarkOpt.BookmarkImages.Width); - end; - end - else - 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 if not Assigned(FInternalImage) then FInternalImage := TSynInternalImage.Create('SynEditInternalImages',10); - if aGutterOffs = 0 then - aGutterOffs := AClip.Left; - FInternalImage.DrawMark(Canvas, CurMark.ImageIndex, - FBookMarkOpt.LeftMargin + aGutterOffs, aScreenLine * LineHeight, - LineHeight); - Inc(aGutterOffs, FBookMarkOpt.Xoffset); + FInternalImage.DrawMark(Canvas, CurMark.ImageIndex, aRect.Left, aRect.Top, + LineHeight); end; - 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 - iLine, j: Integer; + j: Integer; MLine: TSynEditMarkLine; + MarkRect: TRect; + LastMarkIsBookmark: Boolean; begin Result := False; - - LineHeight := TSynEdit(SynEdit).LineHeight; - iLine := FoldView.TextIndex[aScreenLine] + 1; - - MLine := TSynEdit(SynEdit).Marks.Line[iLine]; + aFirstCustomColumnIdx := 0; + if FBookMarkOpt.DrawBookmarksFirst then + aFirstCustomColumnIdx := 1; + MLine := TSynEdit(SynEdit).Marks.Line[FoldView.TextIndex[aScreenLine] + 1]; if MLine = nil then exit; - if FBookMarkOpt.DrawBookmarksFirst then - MLine.Sort(smsoBookmarkFirst, smsoColumn) - else - MLine.Sort(smsoBookMarkLast, smsoColumn); + if FBookMarkOpt.DrawBookmarksFirst then + MLine.Sort(smsoBookmarkFirst, smsoPriority) + else + MLine.Sort(smsoBookMarkLast, smsoPriority); + + LineHeight := TSynEdit(SynEdit).LineHeight; + //Gutter.Paint always supplies AClip.Left = GutterPart.Left + MarkRect := Rect(AClip.Left + FBookMarkOpt.LeftMargin, + aScreenLine * LineHeight, + AClip.Left + FColumnWidth, + (aScreenLine+1) * LineHeight); + + + LastMarkIsBookmark := FBookMarkOpt.DrawBookmarksFirst; for j := 0 to MLine.Count - 1 do begin - if not MLine[j].Visible then + if (not MLine[j].Visible) or + (MLine[j].IsBookmark and (not FBookMarkOpt.GlyphsVisible)) + then continue; - if MLine[j].IsBookmark and not FBookMarkOpt.GlyphsVisible then - continue; - DoPaintMark(MLine[j]); - Result := Result or not MLine[j].IsBookmark; + + 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; @@ -154,7 +182,9 @@ begin Canvas.Brush.Color := Gutter.Color; LCLIntf.SetBkColor(Canvas.Handle, Canvas.Brush.Color); - // now the gutter marks + FColumnWidth := FBookMarkOpt.BookmarkImages.Width; + FColumnCount := Max((Width+1) div FColumnWidth, 1); // full columns + if FBookMarkOpt.GlyphsVisible and (LastLine >= FirstLine) then begin for i := FirstLine to LastLine do diff --git a/ide/sourcesyneditor.pas b/ide/sourcesyneditor.pas index 59c240ccbd..736ce79eb1 100644 --- a/ide/sourcesyneditor.pas +++ b/ide/sourcesyneditor.pas @@ -610,25 +610,19 @@ var itop : Longint; LineHeight: LongInt; begin - iTop := 0; if Line < 0 then Exit; if Assigned(FBookMarkOpt.BookmarkImages) and (DebugMarksImageIndex <= FBookMarkOpt.BookmarkImages.Count) and (DebugMarksImageIndex >= 0) then begin LineHeight := TSynEdit(SynEdit).LineHeight; - if not FBookMarkOpt.DrawBookmarksFirst then - aGutterOffs := AClip.Left - else - if aGutterOffs = 0 then - aGutterOffs := FBookMarkOpt.BookmarkImages.Width + AClip.Left; + iTop := 0; if LineHeight > FBookMarkOpt.BookmarkImages.Height then iTop := (LineHeight - FBookMarkOpt.BookmarkImages.Height) div 2; - with FBookMarkOpt do - BookmarkImages.Draw(Canvas, LeftMargin + aGutterOffs, - iTop + Line * LineHeight, DebugMarksImageIndex, True); - Inc(aGutterOffs, FBookMarkOpt.BookmarkImages.Width); + FBookMarkOpt.BookmarkImages.Draw + (Canvas, FBookMarkOpt.LeftMargin + aGutterOffs * ColumnWidth, + iTop + Line * LineHeight, DebugMarksImageIndex, True); end end;