mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-11 10:35:58 +02:00
SynEdit: refactor the Gutter code, moved drawing code into separate classes
git-svn-id: trunk@17533 -
This commit is contained in:
parent
c34259d476
commit
62a3b51538
@ -77,6 +77,7 @@ uses
|
||||
SynEditMarkup, SynEditMarkupHighAll, SynEditMarkupBracket,
|
||||
SynEditMarkupCtrlMouseLink, SynEditMarkupSpecialLine, SynEditMarkupSelection,
|
||||
SynEditTextBase, SynEditTextTrimmer, SynEditFoldedView,
|
||||
SynGutter,
|
||||
{$ENDIF}
|
||||
SynEditMiscClasses, SynEditTextBuffer, SynEditHighlighter, SynTextDrawer;
|
||||
|
||||
@ -117,10 +118,6 @@ const
|
||||
// maximum scroll range
|
||||
MAX_SCROLL = 32767;
|
||||
|
||||
// Max number of book/gutter marks returned from GetEditMarksForLine - that
|
||||
// really should be enough.
|
||||
maxMarks = 16;
|
||||
|
||||
SYNEDIT_CLIPBOARD_FORMAT = 'SynEdit Control Block Type';
|
||||
|
||||
{$IFNDEF SYN_LAZARUS}
|
||||
@ -270,64 +267,13 @@ type
|
||||
|
||||
TCustomSynEdit = class;
|
||||
|
||||
TSynEditMark = class
|
||||
protected
|
||||
fLine, fColumn, fImage: Integer;
|
||||
fEdit: TCustomSynEdit;
|
||||
fVisible: boolean;
|
||||
fInternalImage: boolean;
|
||||
fBookmarkNum: integer;
|
||||
function GetEdit: TCustomSynEdit; virtual;
|
||||
procedure SetColumn(const Value: Integer); virtual;
|
||||
procedure SetImage(const Value: Integer); virtual;
|
||||
procedure SetLine(const Value: Integer); virtual;
|
||||
procedure SetVisible(const Value: boolean); {$IFDEF SYN_LAZARUS}virtual;{$ENDIF} //MWE: Laz needs to know when a line gets visible, so the editor color can be updated
|
||||
procedure SetInternalImage(const Value: boolean);
|
||||
function GetIsBookmark: boolean;
|
||||
public
|
||||
constructor Create(AOwner: TCustomSynEdit);
|
||||
property Line: integer read fLine write SetLine;
|
||||
property Column: integer read fColumn write SetColumn;
|
||||
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 IsBookmark: boolean read GetIsBookmark;
|
||||
end;
|
||||
{ Make them visible for Units that use TSynEdit }
|
||||
TSynEditMark = SynGutter.TSynEditMark;
|
||||
TPlaceMarkEvent = SynGutter.TPlaceMarkEvent;
|
||||
TSynEditMarks = SynGutter.TSynEditMarks;
|
||||
TSynEditMarkList = SynGutter.TSynEditMarkList;
|
||||
TGutterClickEvent = SynGutter.TGutterClickEvent;
|
||||
|
||||
TPlaceMarkEvent = procedure(Sender: TObject; var Mark: TSynEditMark)
|
||||
of object;
|
||||
|
||||
TSynEditMarks = array[1..maxMarks] of TSynEditMark;
|
||||
|
||||
{ A list of mark objects. Each object cause a litle picture to be drawn in the
|
||||
gutter. }
|
||||
TSynEditMarkList = class(TList)
|
||||
protected
|
||||
fEdit: TCustomSynEdit;
|
||||
fOnChange: TNotifyEvent;
|
||||
procedure DoChange;
|
||||
function Get(Index: Integer): TSynEditMark;
|
||||
procedure Put(Index: Integer; Item: TSynEditMark);
|
||||
public
|
||||
constructor Create(AOwner: TCustomSynEdit);
|
||||
destructor Destroy; override;
|
||||
function Add(Item: TSynEditMark): Integer;
|
||||
procedure ClearLine(line: integer);
|
||||
procedure Delete(Index: Integer);
|
||||
function First: TSynEditMark;
|
||||
procedure GetMarksForLine(line: integer; var Marks: TSynEditMarks);
|
||||
procedure Insert(Index: Integer; Item: TSynEditMark);
|
||||
function Last: TSynEditMark;
|
||||
procedure Place(Mark: TSynEditMark);
|
||||
function Remove(Item: TSynEditMark): Integer;
|
||||
public
|
||||
property Items[Index: Integer]: TSynEditMark read Get write Put; default;
|
||||
property OnChange: TNotifyEvent read FOnChange write FOnChange;
|
||||
end;
|
||||
|
||||
TGutterClickEvent = procedure(Sender: TObject; X, Y, Line: integer;
|
||||
mark: TSynEditMark) of object;
|
||||
|
||||
TSynEditPlugin = class(TObject)
|
||||
private
|
||||
@ -359,7 +305,7 @@ type
|
||||
|
||||
{ TCustomSynEdit }
|
||||
|
||||
TCustomSynEdit = class(TCustomControl)
|
||||
TCustomSynEdit = class(TSynEditBase)
|
||||
private
|
||||
procedure WMDropFiles(var Msg: TMessage); message WM_DROPFILES;
|
||||
procedure WMEraseBkgnd(var Msg: TMessage); message WM_ERASEBKGND;
|
||||
@ -481,7 +427,6 @@ type
|
||||
fOnClearMark: TPlaceMarkEvent; // djlp 2000-08-29
|
||||
fOnCommandProcessed: TProcessCommandEvent;
|
||||
fOnDropFiles: TDropFilesEvent;
|
||||
fOnGutterClick: TGutterClickEvent;
|
||||
fOnPaint: TPaintEvent;
|
||||
fOnPlaceMark: TPlaceMarkEvent;
|
||||
fOnProcessCommand: TProcessCommandEvent;
|
||||
@ -521,9 +466,11 @@ type
|
||||
function GetIncrementColor : TSynSelectedColor;
|
||||
function GetLineHighlightColor: TSynSelectedColor;
|
||||
function GetLineNumberColor: TSynSelectedColor;
|
||||
function GetOnGutterClick : TGutterClickEvent;
|
||||
function GetSelectedColor : TSynSelectedColor;
|
||||
function GetBracketMatchColor : TSynSelectedColor;
|
||||
function GetMouseLinkColor : TSynSelectedColor;
|
||||
procedure SetOnGutterClick(const AValue : TGutterClickEvent);
|
||||
procedure SetRealLines(const AValue : TStrings);
|
||||
procedure SetSelectedColor(const AValue : TSynSelectedColor);
|
||||
procedure SetSpecialLineColors(const AValue : TSpecialLineColorsEvent);
|
||||
@ -698,7 +645,6 @@ type
|
||||
var AChar: {$IFDEF SYN_LAZARUS}TUTF8Char{$ELSE}Char{$ENDIF};
|
||||
Data: pointer); virtual;
|
||||
procedure Paint; override;
|
||||
procedure PaintGutter(AClip: TRect; FirstLine, LastLine: integer); virtual;
|
||||
procedure PaintTextLines(AClip: TRect; FirstLine, LastLine,
|
||||
FirstCol, LastCol: integer); virtual;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
@ -721,7 +667,6 @@ type
|
||||
procedure UndoItem; //sbs 2000-11-19
|
||||
protected
|
||||
fGutterWidth: Integer;
|
||||
fInternalImage: TSynInternalImage;
|
||||
{$IFDEF EnableDoubleBuf}
|
||||
BufferBitmap: TBitmap; // the double buffer
|
||||
{$ENDIF}
|
||||
@ -731,7 +676,6 @@ type
|
||||
AChar: {$IFDEF SYN_LAZARUS}TUTF8Char{$ELSE}Char{$ENDIF};
|
||||
Data: pointer); virtual;
|
||||
// no method DoOnDropFiles, intercept the WM_DROPFILES instead
|
||||
procedure DoOnGutterClick(X, Y: integer); virtual;
|
||||
procedure DoOnPaint; virtual;
|
||||
procedure DoOnPlaceMark(var Mark: TSynEditMark); virtual;
|
||||
procedure DoOnProcessCommand(var Command: TSynEditorCommand;
|
||||
@ -1001,7 +945,7 @@ type
|
||||
read fOnCommandProcessed write fOnCommandProcessed;
|
||||
property OnDropFiles: TDropFilesEvent read fOnDropFiles write fOnDropFiles;
|
||||
property OnGutterClick: TGutterClickEvent
|
||||
read fOnGutterClick write fOnGutterClick;
|
||||
read GetOnGutterClick write SetOnGutterClick;
|
||||
property OnPaint: TPaintEvent read fOnPaint write fOnPaint;
|
||||
property OnPlaceBookmark: TPlaceMarkEvent
|
||||
read FOnPlaceMark write FOnPlaceMark;
|
||||
@ -1509,11 +1453,12 @@ begin
|
||||
fSelectedColor := TSynSelectedColor.Create;
|
||||
fSelectedColor.OnChange := {$IFDEF FPC}@{$ENDIF}SelectedColorsChanged;
|
||||
{$ENDIF}
|
||||
fTextDrawer := TheTextDrawer.Create([fsBold], fFontDummy);
|
||||
fBookMarkOpt := TSynBookMarkOpt.Create(Self);
|
||||
fBookMarkOpt.OnChange := {$IFDEF FPC}@{$ENDIF}BookMarkOptionsChanged;
|
||||
// fRightEdge has to be set before FontChanged is called for the first time
|
||||
fRightEdge := 80;
|
||||
fGutter := TSynGutter.Create;
|
||||
fGutter := TSynGutter.Create(self, fTextView, fBookMarkOpt, fTextDrawer);
|
||||
fGutter.OnChange := {$IFDEF FPC}@{$ENDIF}GutterChanged;
|
||||
fGutterWidth := fGutter.Width;
|
||||
fTextOffset := fGutterWidth + 2;
|
||||
@ -1558,7 +1503,6 @@ begin
|
||||
fFontDummy.CharSet := DEFAULT_CHARSET;
|
||||
{$ENDIF}
|
||||
{$ENDIF}
|
||||
fTextDrawer := TheTextDrawer.Create([fsBold], fFontDummy);
|
||||
Font.Assign(fFontDummy);
|
||||
Font.OnChange := {$IFDEF FPC}@{$ENDIF}FontChanged;
|
||||
FontChanged(nil);
|
||||
@ -1714,7 +1658,6 @@ begin
|
||||
fRedoList.Free;
|
||||
fGutter.Free;
|
||||
fTextDrawer.Free;
|
||||
fInternalImage.Free;
|
||||
fFontDummy.Free;
|
||||
Lines.Free;
|
||||
{$ELSE}
|
||||
@ -1730,7 +1673,6 @@ begin
|
||||
FreeAndNil(fRedoList);
|
||||
FreeAndNil(fGutter);
|
||||
FreeAndNil(fTextDrawer);
|
||||
FreeAndNil(fInternalImage);
|
||||
FreeAndNil(fFontDummy);
|
||||
FreeAndNil(fTextView);
|
||||
FreeAndNil(fTrimLines);
|
||||
@ -1813,6 +1755,11 @@ begin
|
||||
Result := fGutter.MarkupInfoLineNumber;
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.GetOnGutterClick : TGutterClickEvent;
|
||||
begin
|
||||
Result := fGutter.OnGutterClick;
|
||||
end;
|
||||
|
||||
function TCustomSynEdit.GetSelectedColor : TSynSelectedColor;
|
||||
begin
|
||||
result := fMarkupSelection.MarkupInfoSeletion;
|
||||
@ -1845,6 +1792,11 @@ begin
|
||||
Result := fMarkupCtrlMouse.MarkupInfo;
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.SetOnGutterClick(const AValue : TGutterClickEvent);
|
||||
begin
|
||||
fGutter.OnGutterClick := AValue;
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.SetRealLines(const AValue : TStrings);
|
||||
begin
|
||||
if HandleAllocated then
|
||||
@ -2570,7 +2522,7 @@ begin
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
if (X < fGutterWidth) and (Button=mbLeft) then begin
|
||||
Include(fStateFlags, sfPossibleGutterClick);
|
||||
DoOnGutterClick(X, Y);
|
||||
fGutter.DoOnGutterClick(X, Y);
|
||||
end;
|
||||
LCLIntf.SetFocus(Handle);
|
||||
UpdateCaret;
|
||||
@ -2798,7 +2750,7 @@ begin
|
||||
{$IFDEF SYN_LAZARUS}and (Button = mbLeft){$ENDIF} then
|
||||
begin
|
||||
{$IFNDEF SYN_LAZARUS}
|
||||
DoOnGutterClick(X, Y);
|
||||
fGutter.DoOnGutterClick(X, Y);
|
||||
{$ENDIF}
|
||||
end else
|
||||
if fStateFlags * [sfDblClicked,
|
||||
@ -2812,6 +2764,7 @@ begin
|
||||
{$ELSE}CaretXY{$ENDIF});
|
||||
Exclude(fStateFlags, sfWaitForDragging);
|
||||
end;
|
||||
|
||||
if (Button=mbLeft)
|
||||
and (fStateFlags * [sfWaitForDragging] = []) then
|
||||
begin
|
||||
@ -2839,62 +2792,6 @@ begin
|
||||
//DebugLn('TCustomSynEdit.MouseUp END Mouse=',X,',',Y,' Caret=',CaretX,',',CaretY,', BlockBegin=',BlockBegin.X,',',BlockBegin.Y,' BlockEnd=',BlockEnd.X,',',BlockEnd.Y);
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.DoOnGutterClick(X, Y: integer);
|
||||
var
|
||||
i : integer;
|
||||
offs : integer;
|
||||
line : integer;
|
||||
allmrk: TSynEditMarks;
|
||||
mark : TSynEditMark;
|
||||
begin
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
line := PixelsToRowColumn(Point(X, Y)).Y;
|
||||
//debugln('TCustomSynEdit.DoOnGutterClick A ',dbgs(line));
|
||||
if line <= Lines.Count then begin
|
||||
mark := nil;
|
||||
if Gutter.ShowCodeFolding and (X<Gutter.CodeFoldingWidth) then begin
|
||||
CodeFoldAction(line);
|
||||
end else begin
|
||||
Marks.GetMarksForLine(line, allmrk);
|
||||
offs := 0;
|
||||
for i := 1 to maxMarks do begin
|
||||
if assigned(allmrk[i]) then begin
|
||||
Inc(offs, BookMarkOptions.XOffset);
|
||||
if X < offs then begin
|
||||
mark := allmrk[i];
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if Assigned(fOnGutterClick) then begin
|
||||
// for compatibility invoke this only on the markable area
|
||||
fOnGutterClick(Self, X, Y, line, mark);
|
||||
end;
|
||||
end;
|
||||
{$ELSE}
|
||||
if Assigned(fOnGutterClick) then begin
|
||||
line := PixelsToRowColumn(Point(X, Y)).Y;
|
||||
if line <= Lines.Count then begin
|
||||
mark := nil;
|
||||
Marks.GetMarksForLine(line, allmrk);
|
||||
offs := 0;
|
||||
mark := nil;
|
||||
for i := 1 to maxMarks do begin
|
||||
if assigned(allmrk[i]) then begin
|
||||
Inc(offs, BookMarkOptions.XOffset);
|
||||
if X < offs then begin
|
||||
mark := allmrk[i];
|
||||
break;
|
||||
end;
|
||||
end;
|
||||
end; //for
|
||||
fOnGutterClick(Self, X, Y, line, mark);
|
||||
end;
|
||||
end;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.Paint;
|
||||
var
|
||||
rcClip, rcDraw: TRect;
|
||||
@ -2941,7 +2838,7 @@ begin
|
||||
if (rcClip.Left < fGutterWidth) then begin
|
||||
rcDraw := rcClip;
|
||||
rcDraw.Right := fGutterWidth;
|
||||
PaintGutter(rcDraw, nL1, nL2);
|
||||
fGutter.Paint(Canvas, rcDraw, nL1, nL2);
|
||||
end;
|
||||
// Then paint the text area if it was (partly) invalidated.
|
||||
if (rcClip.Right > fGutterWidth) then begin
|
||||
@ -3001,343 +2898,6 @@ begin
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
procedure TCustomSynEdit.PaintGutter(AClip: TRect; FirstLine, LastLine: integer);
|
||||
var
|
||||
i, iLine: integer;
|
||||
rcLine: TRect;
|
||||
bHasOtherMarks: boolean;
|
||||
aGutterOffs: PIntArray;
|
||||
s: string;
|
||||
dc: HDC;
|
||||
rcCodeFold: TRect;
|
||||
tmp: TSynEditCodeFoldType;
|
||||
CodeFoldOffset: Integer;
|
||||
ShowDot: boolean;
|
||||
|
||||
procedure DrawMark(iMark: integer);
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
var
|
||||
iLine: integer;
|
||||
itop : Longint;
|
||||
CurMark: TSynEditMark;
|
||||
begin
|
||||
iTop := 0;
|
||||
CurMark:=Marks[iMark];
|
||||
if (CurMark.Line<1) or (CurMark.Line>Lines.Count) then exit;
|
||||
if fTextView.FoldedAtTextIndex[CurMark.Line-1] then exit;
|
||||
iLine := fTextView.TextIndexToScreenLine(CurMark.Line-1);
|
||||
|
||||
if Assigned(fBookMarkOpt.BookmarkImages) and not CurMark.InternalImage
|
||||
then begin
|
||||
if (CurMark.ImageIndex <= fBookMarkOpt.BookmarkImages.Count) then begin
|
||||
if CurMark.IsBookmark = BookMarkOptions.DrawBookmarksFirst then
|
||||
aGutterOffs^[iLine] := CodeFoldOffset
|
||||
else if aGutterOffs^[iLine] = 0 then
|
||||
aGutterOffs^[iLine] := fBookMarkOpt.BookmarkImages.Width + CodeFoldOffset;
|
||||
if fTextHeight > fBookMarkOpt.BookmarkImages.Height then
|
||||
iTop := (fTextHeight - fBookMarkOpt.BookmarkImages.Height) div 2;
|
||||
with fBookMarkOpt do
|
||||
BookmarkImages.Draw(Canvas, LeftMargin + aGutterOffs^[iLine],
|
||||
iTop + iLine * fTextHeight, 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 begin
|
||||
fInternalImage := TSynInternalImage.Create('SynEditInternalImages',10);
|
||||
end;
|
||||
if (aGutterOffs^[iLine]=0) and Gutter.ShowCodeFolding then
|
||||
aGutterOffs^[iLine]:=Gutter.CodeFoldingWidth;
|
||||
fInternalImage.DrawMark(Canvas, CurMark.ImageIndex,
|
||||
fBookMarkOpt.LeftMargin + aGutterOffs^[iLine], iLine * fTextHeight,
|
||||
fTextHeight);
|
||||
Inc(aGutterOffs^[iLine], fBookMarkOpt.Xoffset);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$ELSE below: not SYN_LAZARUS}
|
||||
var
|
||||
iLine: integer;
|
||||
itop : Longint;
|
||||
begin
|
||||
iTop := 0;
|
||||
if Assigned(fBookMarkOpt.BookmarkImages) and not Marks[i].InternalImage
|
||||
then begin
|
||||
if Marks[iMark].ImageIndex <= fBookMarkOpt.BookmarkImages.Count then begin
|
||||
iLine := Marks[iMark].Line - TopLine;
|
||||
// if Marks[iMark].IsBookmark then
|
||||
if Marks[iMark].IsBookmark = BookMarkOptions.DrawBookmarksFirst then //mh 2000-10-12
|
||||
aGutterOffs^[iLine] := 0
|
||||
else if aGutterOffs^[iLine] = 0 then
|
||||
aGutterOffs^[iLine] := fBookMarkOpt.XOffset;
|
||||
If fTextHeight > fBookMarkOpt.BookmarkImages.Height then
|
||||
iTop := (fTextHeight - fBookMarkOpt.BookmarkImages.Height) div 2;
|
||||
with fBookMarkOpt do
|
||||
if not TSynEditStringList(fLines).Folded[iLine] then
|
||||
BookmarkImages.Draw(Canvas, LeftMargin + aGutterOffs^[iLine], iTop + iLine * fTextHeight, Marks[iMark].ImageIndex,true);
|
||||
|
||||
Inc(aGutterOffs^[iLine], fBookMarkOpt.XOffset);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
if Marks[iMark].ImageIndex in [0..9] then begin
|
||||
iLine := Marks[iMark].Line - TopLine;
|
||||
if not Assigned(fInternalImage) then begin
|
||||
fInternalImage := TSynInternalImage.Create('SynEditInternalImages',
|
||||
10);
|
||||
end;
|
||||
fInternalImage.DrawMark(Canvas, Marks[iMark].ImageIndex, fBookMarkOpt.LeftMargin + aGutterOffs^[iLine], iLine * fTextHeight, fTextHeight);
|
||||
Inc(aGutterOffs^[iLine], fBookMarkOpt.XOffset);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
procedure DrawNodeBox(rcCodeFold: TRect; Collapsed: boolean);
|
||||
const cNodeOffset = 3;
|
||||
var
|
||||
rcNode: TRect;
|
||||
ptCenter : TPoint;
|
||||
iSquare: integer;
|
||||
begin
|
||||
//center of the draw area
|
||||
ptCenter.X := (rcCodeFold.Left + rcCodeFold.Right) div 2;
|
||||
ptCenter.Y := (rcCodeFold.Top + rcCodeFold.Bottom) div 2;
|
||||
|
||||
//make node rect square
|
||||
iSquare := Max(0, rcCodeFold.Bottom - rcCodeFold.Top - 14) div 2;
|
||||
|
||||
//area of drawbox
|
||||
rcNode.Right := rcCodeFold.Right - cNodeOffset + 1;
|
||||
rcNode.Left := rcCodeFold.Left + cNodeOffset;
|
||||
rcNode.Top := rcCodeFold.Top + cNodeOffset + iSquare;
|
||||
rcNode.Bottom := rcCodeFold.Bottom - cNodeOffset - iSquare + 1;
|
||||
|
||||
Canvas.Brush.Color:=clWhite;
|
||||
Canvas.Rectangle(rcNode);
|
||||
|
||||
//draw bottom handle to paragraph line
|
||||
Canvas.MoveTo((rcNode.Left + rcNode.Right) div 2, rcNode.Bottom);
|
||||
Canvas.LineTo((rcNode.Left + rcNode.Right) div 2, rcCodeFold.Bottom);
|
||||
|
||||
//draw unfolded sign in node box
|
||||
Canvas.MoveTo(ptCenter.X - 2, ptCenter.Y);
|
||||
Canvas.LineTo(ptCenter.X + 3, ptCenter.Y);
|
||||
|
||||
//draw folded sign
|
||||
if Collapsed then
|
||||
begin
|
||||
Canvas.MoveTo(ptCenter.X, ptCenter.Y - 2);
|
||||
Canvas.LineTo(ptCenter.X, ptCenter.Y + 3);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure DrawParagraphContinue(rcCodeFold: TRect);
|
||||
var
|
||||
iCenter : integer;
|
||||
begin
|
||||
//center of the draw area
|
||||
iCenter := (rcCodeFold.Left + rcCodeFold.Right) div 2;
|
||||
|
||||
Canvas.MoveTo(iCenter, rcCodeFold.Top);
|
||||
Canvas.LineTo(iCenter, rcCodeFold.Bottom);
|
||||
end;
|
||||
|
||||
procedure DrawParagraphEnd(rcCodeFold: TRect);
|
||||
var
|
||||
ptCenter : TPoint;
|
||||
begin
|
||||
//center of the draw area
|
||||
ptCenter.X := (rcCodeFold.Left + rcCodeFold.Right) div 2;
|
||||
ptCenter.Y := (rcCodeFold.Top + rcCodeFold.Bottom) div 2;
|
||||
|
||||
Canvas.MoveTo(ptCenter.X, rcCodeFold.Top);
|
||||
Canvas.LineTo(ptCenter.X, ptCenter.Y);
|
||||
Canvas.LineTo(rcCodeFold.Right, ptCenter.Y);
|
||||
end;
|
||||
|
||||
begin
|
||||
{$IFNDEF SYN_LAZARUS}
|
||||
if (FirstLine = 1) and (LastLine = 0) then
|
||||
LastLine := 1;
|
||||
{$ENDIF}
|
||||
// Changed to use fTextDrawer.BeginDrawing and fTextDrawer.EndDrawing only
|
||||
// when absolutely necessary. Note: Never change brush / pen / font of the
|
||||
// canvas inside of this block (only through methods of fTextDrawer)!
|
||||
Canvas.Brush.Color := Gutter.Color;
|
||||
// If we have to draw the line numbers then we don't want to erase
|
||||
// the background first. Do it line by line with TextRect instead
|
||||
// and fill only the area after the last visible line.
|
||||
dc := Canvas.Handle;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
LCLIntf.SetBkColor(dc,Canvas.Brush.Color);
|
||||
if Gutter.ShowCodeFolding then
|
||||
CodeFoldOffset:=Gutter.CodeFoldingWidth
|
||||
else
|
||||
CodeFoldOffset:=0;
|
||||
{$ENDIF}
|
||||
if fGutter.ShowLineNumbers then
|
||||
begin
|
||||
fTextDrawer.BeginDrawing(dc);
|
||||
try
|
||||
if FGutter.MarkupInfoLineNumber.Background <> clNone then
|
||||
fTextDrawer.SetBackColor(FGutter.MarkupInfoLineNumber.Background)
|
||||
else
|
||||
fTextDrawer.SetBackColor(FGutter.Color);
|
||||
if FGutter.MarkupInfoLineNumber.Foreground <> clNone then
|
||||
fTextDrawer.SetForeColor(FGutter.MarkupInfoLineNumber.Foreground)
|
||||
else
|
||||
fTextDrawer.SetForeColor(Self.Font.Color);
|
||||
fTextDrawer.Style := FGutter.MarkupInfoLineNumber.Style;
|
||||
// prepare the rect initially
|
||||
rcLine := AClip;
|
||||
rcLine.Right := fGutterWidth - 2;
|
||||
//rcLine.Right := Max(rcLine.Right, fGutterWidth - 2);
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
rcLine.Bottom := FirstLine * fTextHeight;
|
||||
rcLine.Left := CodeFoldOffset + fGutter.LeftOffset;
|
||||
for i := FirstLine to LastLine do
|
||||
begin
|
||||
iLine := fTextView.DisplayNumber[i];
|
||||
// next line rect
|
||||
rcLine.Top := rcLine.Bottom;
|
||||
// Must show a dot instead of line number if
|
||||
// line number is not the first, the last, the current line
|
||||
// or a multiple of Gutter.ShowOnlyLineNumbersMultiplesOf
|
||||
ShowDot := ((iLine mod fGutter.ShowOnlyLineNumbersMultiplesOf) <> 0)
|
||||
and (iLine <> CaretY) and (iLine <> 1) and (iLine <> Lines.Count);
|
||||
// Get the formatted line number or dot
|
||||
s := fGutter.FormatLineNumber(iLine, ShowDot);
|
||||
Inc(rcLine.Bottom, fTextHeight);
|
||||
// erase the background and draw the line number string in one go
|
||||
fTextDrawer.ExtTextOut(rcLine.Left, rcLine.Top, ETO_OPAQUE, rcLine,
|
||||
PChar(Pointer(S)),Length(S));
|
||||
end;
|
||||
{$ELSE}
|
||||
rcLine.Bottom := (FirstLine - TopLine) * fTextHeight;
|
||||
for iLine := FirstLine to LastLine do begin
|
||||
// next line rect
|
||||
rcLine.Top := rcLine.Bottom;
|
||||
s := fGutter.FormatLineNumber(iLine, false);
|
||||
Inc(rcLine.Bottom, fTextHeight);
|
||||
// erase the background and draw the line number string in one go
|
||||
Windows.ExtTextOut(DC, fGutter.LeftOffset, rcLine.Top, ETO_OPAQUE,
|
||||
@rcLine, PChar(s), Length(s), nil);
|
||||
end;
|
||||
{$ENDIF}
|
||||
// now erase the remaining area if any
|
||||
if AClip.Bottom > rcLine.Bottom then
|
||||
begin
|
||||
rcLine.Top := rcLine.Bottom;
|
||||
rcLine.Bottom := AClip.Bottom;
|
||||
with rcLine do
|
||||
fTextDrawer.ExtTextOut(Left, Top, ETO_OPAQUE, rcLine, nil, 0);
|
||||
end;
|
||||
// restore original style
|
||||
fTextDrawer.SetBackColor(fGutter.Color);
|
||||
fTextDrawer.SetForeColor(Self.Font.Color);
|
||||
if AClip.Left < rcLine.Left then
|
||||
begin
|
||||
rcLine.Right := rcLine.Left;
|
||||
rcLine.Left := AClip.Left;
|
||||
rcLine.Top := AClip.Top;
|
||||
rcLine.Bottom := AClip.Bottom;
|
||||
with rcLine do
|
||||
fTextDrawer.ExtTextOut(Left, Top, ETO_OPAQUE, rcLine, nil, 0);
|
||||
end;
|
||||
finally
|
||||
fTextDrawer.EndDrawing;
|
||||
end;
|
||||
end else
|
||||
InternalFillRect(dc, AClip);
|
||||
|
||||
//draw the code folding marks
|
||||
if fGutter.ShowCodeFolding then
|
||||
begin
|
||||
with Canvas do
|
||||
begin
|
||||
Pen.Color := clDkGray;
|
||||
Pen.Width := 1;
|
||||
|
||||
rcLine.Bottom := FirstLine * fTextHeight;
|
||||
for iLine := FirstLine to LastLine do
|
||||
begin
|
||||
// next line rect
|
||||
rcLine.Top := rcLine.Bottom;
|
||||
Inc(rcLine.Bottom, fTextHeight);
|
||||
|
||||
rcCodeFold.Left := 0;
|
||||
rcCodeFold.Right := 14;
|
||||
rcCodeFold.Top := rcLine.Top;
|
||||
rcCodeFold.Bottom := rcLine.Bottom;
|
||||
|
||||
//DebugLn(['** GUTTER at ',iLine,' scrline=',fTextView.TextIndexToScreenLine(iLine-1),' type ', SynEditCodeFoldTypeNames[fTextView.FoldType[fTextView.TextIndexToScreenLine(iLine-1)]]]);
|
||||
tmp := fTextView.FoldType[iLine];
|
||||
|
||||
case tmp of
|
||||
cfCollapsed: DrawNodeBox(rcCodeFold, True);
|
||||
cfExpanded: DrawNodeBox(rcCodeFold, False);
|
||||
cfContinue: DrawParagraphContinue(rcCodeFold);
|
||||
cfEnd: DrawParagraphEnd(rcCodeFold);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
// the gutter separator if visible
|
||||
if AClip.Right >= fGutterWidth - 2 then
|
||||
with Canvas do begin
|
||||
Pen.Color := {$IFDEF SYN_LAZARUS}clWhite{$ELSE}clBtnHighlight{$ENDIF};
|
||||
Pen.Width := 1;
|
||||
with AClip do begin
|
||||
MoveTo(fGutterWidth - 2, Top);
|
||||
LineTo(fGutterWidth - 2, Bottom);
|
||||
Pen.Color := {$IFDEF SYN_LAZARUS}clDkGray{$ELSE}clBtnShadow{$ENDIF};
|
||||
MoveTo(fGutterWidth - 1, Top);
|
||||
LineTo(fGutterWidth - 1, Bottom);
|
||||
end;
|
||||
end;
|
||||
// now the gutter marks
|
||||
if BookMarkOptions.GlyphsVisible and (Marks.Count > 0)
|
||||
and (LastLine >= FirstLine)
|
||||
then begin
|
||||
aGutterOffs := AllocMem((LastLine+1{$IFNDEF SYN_LAZARUS}-TopLine{$ENDIF}) * SizeOf(integer));
|
||||
try
|
||||
// Instead of making a two pass loop we look while drawing the bookmarks
|
||||
// whether there is any other mark to be drawn
|
||||
bHasOtherMarks := FALSE;
|
||||
for i := 0 to Marks.Count - 1 do with Marks[i] do
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
if Visible and (Line >= fTextView.TextIndex[FirstLine]+1) and (Line <= fTextView.TextIndex[LastLine]+1) then
|
||||
{$ELSE}
|
||||
if Visible and (Line >= FirstLine) and (Line <= LastLine) then
|
||||
{$ENDIF}
|
||||
begin
|
||||
if IsBookmark <> BookMarkOptions.DrawBookmarksFirst then //mh 2000-10-12
|
||||
bHasOtherMarks := TRUE
|
||||
else
|
||||
DrawMark(i);
|
||||
end;
|
||||
if bHasOtherMarks then
|
||||
for i := 0 to Marks.Count - 1 do with Marks[i] do
|
||||
begin
|
||||
if Visible and (IsBookmark <> BookMarkOptions.DrawBookmarksFirst) //mh 2000-10-12
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
and (Line >= fTextView.TextIndex[FirstLine]+1) and (Line <= fTextView.TextIndex[LastLine]+1)
|
||||
{$ELSE}
|
||||
and (Line >= FirstLine) and (Line <= LastLine)
|
||||
{$ENDIF}
|
||||
then
|
||||
DrawMark(i);
|
||||
end;
|
||||
finally
|
||||
FreeMem(aGutterOffs);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TCustomSynEdit.PaintTextLines(AClip: TRect; FirstLine, LastLine,
|
||||
FirstCol, LastCol: integer);
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
@ -11471,174 +11031,6 @@ begin
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
{ TSynEditMark }
|
||||
|
||||
function TSynEditMark.GetEdit: TCustomSynEdit;
|
||||
begin
|
||||
if FEdit <> nil then try
|
||||
if FEdit.Marks.IndexOf(self) = -1 then
|
||||
FEdit := nil;
|
||||
except
|
||||
FEdit := nil;
|
||||
end;
|
||||
Result := FEdit;
|
||||
end;
|
||||
|
||||
function TSynEditMark.GetIsBookmark: boolean;
|
||||
begin
|
||||
Result := (fBookmarkNum >= 0);
|
||||
end;
|
||||
|
||||
procedure TSynEditMark.SetColumn(const Value: Integer);
|
||||
begin
|
||||
FColumn := Value;
|
||||
end;
|
||||
|
||||
procedure TSynEditMark.SetImage(const Value: Integer);
|
||||
begin
|
||||
FImage := Value;
|
||||
if fVisible and Assigned(fEdit) then
|
||||
fEdit.InvalidateGutterLines(fLine, fLine);
|
||||
end;
|
||||
|
||||
procedure TSynEditMark.SetInternalImage(const Value: boolean);
|
||||
begin
|
||||
fInternalImage := Value;
|
||||
if fVisible and Assigned(fEdit) then
|
||||
fEdit.InvalidateGutterLines(fLine, fLine);
|
||||
end;
|
||||
|
||||
procedure TSynEditMark.SetLine(const Value: Integer);
|
||||
begin
|
||||
if fVisible and Assigned(fEdit) then begin
|
||||
if fLine > 0 then
|
||||
fEdit.InvalidateGutterLines(fLine, fLine);
|
||||
fLine := Value;
|
||||
fEdit.InvalidateGutterLines(fLine, fLine);
|
||||
end else
|
||||
fLine := Value;
|
||||
end;
|
||||
|
||||
procedure TSynEditMark.SetVisible(const Value: boolean);
|
||||
begin
|
||||
if fVisible <> Value then begin
|
||||
fVisible := Value;
|
||||
if Assigned(fEdit) then
|
||||
fEdit.InvalidateGutterLines(fLine, fLine);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TSynEditMark.Create(AOwner: TCustomSynEdit);
|
||||
begin
|
||||
inherited Create;
|
||||
fBookmarkNum := -1;
|
||||
fEdit := AOwner;
|
||||
end;
|
||||
|
||||
{ TSynEditMarkList }
|
||||
|
||||
function TSynEditMarkList.Add(Item: TSynEditMark): Integer;
|
||||
begin
|
||||
Result := inherited Add(Item);
|
||||
DoChange;
|
||||
end;
|
||||
|
||||
procedure TSynEditMarkList.ClearLine(Line: integer);
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
for i := Count - 1 downto 0 do
|
||||
if not Items[i].IsBookmark and (Items[i].Line = Line) then Delete(i);
|
||||
end;
|
||||
|
||||
constructor TSynEditMarkList.Create(AOwner: TCustomSynEdit);
|
||||
begin
|
||||
inherited Create;
|
||||
fEdit := AOwner;
|
||||
end;
|
||||
|
||||
destructor TSynEditMarkList.Destroy;
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
for i := 0 to Pred(Count) do
|
||||
Get(i).Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TSynEditMarkList.Delete(Index: Integer);
|
||||
begin
|
||||
inherited Delete(Index);
|
||||
DoChange;
|
||||
end;
|
||||
|
||||
procedure TSynEditMarkList.DoChange;
|
||||
begin
|
||||
if Assigned(FOnChange) then
|
||||
FOnChange(Self);
|
||||
end;
|
||||
|
||||
function TSynEditMarkList.First: TSynEditMark;
|
||||
begin
|
||||
result := TSynEditMark(inherited First);
|
||||
end;
|
||||
|
||||
function TSynEditMarkList.Get(Index: Integer): TSynEditMark;
|
||||
begin
|
||||
result := TSynEditMark(inherited Get(Index));
|
||||
end;
|
||||
|
||||
//Returns up to maxMarks book/gutter marks for a chosen line.
|
||||
|
||||
procedure TSynEditMarkList.GetMarksForLine(line: integer;
|
||||
var marks: TSynEditMarks);
|
||||
var
|
||||
cnt: integer;
|
||||
i: integer;
|
||||
begin
|
||||
FillChar(marks, SizeOf(marks), 0);
|
||||
cnt := 0;
|
||||
for i := 0 to Count - 1 do begin
|
||||
if Items[i].Line = line then begin
|
||||
Inc(cnt);
|
||||
marks[cnt] := Items[i];
|
||||
if cnt = maxMarks then break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynEditMarkList.Insert(Index: Integer; Item: TSynEditMark);
|
||||
begin
|
||||
inherited Insert(Index, Item);
|
||||
DoChange;
|
||||
end;
|
||||
|
||||
function TSynEditMarkList.Last: TSynEditMark;
|
||||
begin
|
||||
result := TSynEditMark(inherited Last);
|
||||
end;
|
||||
|
||||
procedure TSynEditMarkList.Place(mark: TSynEditMark);
|
||||
begin
|
||||
if assigned(fEdit) then
|
||||
if assigned(fEdit.OnPlaceBookmark) then fEdit.OnPlaceBookmark(fEdit, mark);
|
||||
if assigned(mark) then
|
||||
Add(mark);
|
||||
DoChange;
|
||||
end;
|
||||
|
||||
procedure TSynEditMarkList.Put(Index: Integer; Item: TSynEditMark);
|
||||
begin
|
||||
inherited Put(Index, Item);
|
||||
DoChange;
|
||||
end;
|
||||
|
||||
function TSynEditMarkList.Remove(Item: TSynEditMark): Integer;
|
||||
begin
|
||||
Result := inherited Remove(Item);
|
||||
DoChange;
|
||||
end;
|
||||
|
||||
{ TSynEditPlugin }
|
||||
|
||||
constructor TSynEditPlugin.Create(AOwner: TCustomSynEdit);
|
||||
|
@ -51,6 +51,10 @@ uses
|
||||
|
||||
type
|
||||
|
||||
// Empty - For type checking on function-arguments
|
||||
// in places where TCustomSynEdit can not be used due to circular unit refs
|
||||
TSynEditBase = class(TCustomControl);
|
||||
|
||||
{ TSynSelectedColor }
|
||||
|
||||
TSynSelectedColor = class(TPersistent)
|
||||
@ -87,86 +91,6 @@ type
|
||||
property OnChange: TNotifyEvent read fOnChange write fOnChange;
|
||||
end;
|
||||
|
||||
{ TSynGutter }
|
||||
|
||||
TSynGutter = class(TPersistent)
|
||||
private
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
FCodeFoldingWidth: integer;
|
||||
fShowCodeFolding: boolean;
|
||||
FShowOnlyLineNumbersMultiplesOf: integer;
|
||||
FMarkupInfoLineNumber: TSynSelectedColor;
|
||||
{$ENDIF}
|
||||
fColor: TColor;
|
||||
fWidth: integer;
|
||||
fShowLineNumbers: boolean;
|
||||
fDigitCount: integer;
|
||||
fLeadingZeros: boolean;
|
||||
fZeroStart: boolean;
|
||||
fLeftOffset: integer;
|
||||
fRightOffset: integer;
|
||||
fOnChange: TNotifyEvent;
|
||||
fCursor: TCursor;
|
||||
fVisible: boolean;
|
||||
fAutoSize: boolean;
|
||||
fAutoSizeDigitCount: integer;
|
||||
procedure SetAutoSize(const Value: boolean);
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
procedure SetCodeFoldingWidth(const AValue: integer);
|
||||
procedure SetShowCodeFolding(const Value: boolean);
|
||||
procedure SetShowOnlyLineNumbersMultiplesOf(const AValue: integer);
|
||||
{$ENDIF}
|
||||
procedure SetColor(const Value: TColor);
|
||||
procedure SetDigitCount(Value: integer);
|
||||
procedure SetLeadingZeros(const Value: boolean);
|
||||
procedure SetLeftOffset(Value: integer);
|
||||
procedure SetRightOffset(Value: integer);
|
||||
procedure SetShowLineNumbers(const Value: boolean);
|
||||
procedure SetVisible(Value: boolean);
|
||||
procedure SetWidth(Value: integer);
|
||||
procedure SetZeroStart(const Value: boolean);
|
||||
procedure DoChange(Sender: TObject);
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure Assign(Source: TPersistent); override;
|
||||
procedure AutoSizeDigitCount(LinesCount: integer);
|
||||
function FormatLineNumber(Line: integer; IsDot: boolean): string;
|
||||
function RealGutterWidth(CharWidth: integer): integer;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
property OnChange: TNotifyEvent read fOnChange write fOnChange;
|
||||
{$ENDIF}
|
||||
published
|
||||
property AutoSize: boolean read fAutoSize write SetAutoSize default FALSE;
|
||||
property Color: TColor read fColor write SetColor default clBtnFace;
|
||||
property Cursor: TCursor read fCursor write fCursor default crDefault;
|
||||
property DigitCount: integer read fDigitCount write SetDigitCount
|
||||
default 4;
|
||||
property LeadingZeros: boolean read fLeadingZeros write SetLeadingZeros
|
||||
default FALSE;
|
||||
property LeftOffset: integer read fLeftOffset write SetLeftOffset
|
||||
default 16;
|
||||
property RightOffset: integer read fRightOffset write SetRightOffset
|
||||
default 2;
|
||||
property ShowLineNumbers: boolean read fShowLineNumbers
|
||||
write SetShowLineNumbers default FALSE;
|
||||
property Visible: boolean read fVisible write SetVisible default TRUE;
|
||||
property Width: integer read fWidth write SetWidth default 30;
|
||||
property ZeroStart: boolean read fZeroStart write SetZeroStart default FALSE;
|
||||
{$IFNDEF SYN_LAZARUS}
|
||||
property OnChange: TNotifyEvent read fOnChange write fOnChange;
|
||||
{$ENDIF}
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
property ShowCodeFolding: boolean read fShowCodeFolding
|
||||
write SetShowCodeFolding default FALSE;
|
||||
property CodeFoldingWidth: integer read FCodeFoldingWidth write SetCodeFoldingWidth
|
||||
default 14;
|
||||
property ShowOnlyLineNumbersMultiplesOf: integer read FShowOnlyLineNumbersMultiplesOf
|
||||
write SetShowOnlyLineNumbersMultiplesOf default 1;
|
||||
property MarkupInfoLineNumber: TSynSelectedColor read FMarkupInfoLineNumber;
|
||||
{$ENDIF}
|
||||
end;
|
||||
|
||||
{ TSynBookMarkOpt }
|
||||
|
||||
TSynBookMarkOpt = class(TPersistent)
|
||||
@ -373,246 +297,6 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TSynGutter }
|
||||
|
||||
constructor TSynGutter.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
fColor := clBtnFace;
|
||||
fVisible := TRUE;
|
||||
fWidth := 30;
|
||||
fLeftOffset := 16;
|
||||
fDigitCount := 4;
|
||||
fAutoSizeDigitCount := fDigitCount;
|
||||
fRightOffset := 2;
|
||||
fShowOnlyLineNumbersMultiplesOf := 1;
|
||||
fCodeFoldingWidth := 14;
|
||||
FMarkupInfoLineNumber := TSynSelectedColor.Create;
|
||||
FMarkupInfoLineNumber.Background := clNone;
|
||||
FMarkupInfoLineNumber.Foreground := clNone;
|
||||
FMarkupInfoLineNumber.OnChange := @DoChange;
|
||||
end;
|
||||
|
||||
destructor TSynGutter.Destroy;
|
||||
begin
|
||||
FMarkupInfoLineNumber.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.Assign(Source: TPersistent);
|
||||
var
|
||||
Src: TSynGutter;
|
||||
begin
|
||||
if Assigned(Source) and (Source is TSynGutter) then
|
||||
begin
|
||||
Src := TSynGutter(Source);
|
||||
fColor := Src.fColor;
|
||||
fVisible := Src.fVisible;
|
||||
fWidth := Src.fWidth;
|
||||
fShowLineNumbers := Src.fShowLineNumbers;
|
||||
fLeadingZeros := Src.fLeadingZeros;
|
||||
fZeroStart := Src.fZeroStart;
|
||||
fLeftOffset := Src.fLeftOffset;
|
||||
fDigitCount := Src.fDigitCount;
|
||||
fRightOffset := Src.fRightOffset;
|
||||
fAutoSize := Src.fAutoSize;
|
||||
fAutoSizeDigitCount := Src.fAutoSizeDigitCount;
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
FCodeFoldingWidth := Src.FCodeFoldingWidth;
|
||||
fShowCodeFolding := Src.fShowCodeFolding;
|
||||
FShowOnlyLineNumbersMultiplesOf := Src.FShowOnlyLineNumbersMultiplesOf;
|
||||
FMarkupInfoLineNumber.Assign(Src.MarkupInfoLineNumber);
|
||||
{$ENDIF}
|
||||
DoChange(Self);
|
||||
end else
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.AutoSizeDigitCount(LinesCount: integer);
|
||||
var
|
||||
nDigits: integer;
|
||||
begin
|
||||
if fVisible and fAutoSize and fShowLineNumbers then
|
||||
begin
|
||||
if fZeroStart then Dec(LinesCount);
|
||||
nDigits := Max(Length(IntToStr(LinesCount)), fDigitCount);
|
||||
if fAutoSizeDigitCount <> nDigits then
|
||||
begin
|
||||
fAutoSizeDigitCount := nDigits;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end else
|
||||
fAutoSizeDigitCount := fDigitCount;
|
||||
end;
|
||||
|
||||
function TSynGutter.FormatLineNumber(Line: integer; IsDot: boolean): string;
|
||||
var
|
||||
i: integer;
|
||||
begin
|
||||
Result := '';
|
||||
// if a dot must be showed
|
||||
if IsDot then
|
||||
if Line mod 5 = 0 then // every 5 lines show '-' instead of '.'
|
||||
Result := StringOfChar(' ', fAutoSizeDigitCount-1) + '-'
|
||||
else
|
||||
Result := StringOfChar(' ', fAutoSizeDigitCount-1) + '.'
|
||||
// else format the line number
|
||||
else begin
|
||||
if fZeroStart then Dec(Line);
|
||||
Str(Line : fAutoSizeDigitCount, Result);
|
||||
if fLeadingZeros then
|
||||
for i := 1 to fAutoSizeDigitCount - 1 do begin
|
||||
if (Result[i] <> ' ') then break;
|
||||
Result[i] := '0';
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSynGutter.RealGutterWidth(CharWidth: integer): integer;
|
||||
begin
|
||||
if not fVisible then
|
||||
begin
|
||||
Result := 0;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if fShowLineNumbers then
|
||||
Result := fLeftOffset + fRightOffset + fAutoSizeDigitCount * CharWidth + 2
|
||||
else
|
||||
Result := fWidth;
|
||||
|
||||
if fShowCodeFolding then
|
||||
Result := Result + CodeFoldingWidth;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetAutoSize(const Value: boolean);
|
||||
begin
|
||||
if fAutoSize <> Value then
|
||||
begin
|
||||
fAutoSize := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
{$IFDEF SYN_LAZARUS}
|
||||
procedure TSynGutter.SetCodeFoldingWidth(const AValue: integer);
|
||||
begin
|
||||
if FCodeFoldingWidth=AValue then exit;
|
||||
FCodeFoldingWidth:=AValue;
|
||||
DoChange(Self);
|
||||
end;
|
||||
{$ENDIF}
|
||||
|
||||
procedure TSynGutter.SetColor(const Value: TColor);
|
||||
begin
|
||||
if fColor <> Value then
|
||||
begin
|
||||
fColor := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetDigitCount(Value: integer);
|
||||
begin
|
||||
Value := MinMax(Value, 2, 12);
|
||||
if fDigitCount <> Value then
|
||||
begin
|
||||
fDigitCount := Value;
|
||||
fAutoSizeDigitCount := fDigitCount;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetLeadingZeros(const Value: boolean);
|
||||
begin
|
||||
if fLeadingZeros <> Value then
|
||||
begin
|
||||
fLeadingZeros := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetLeftOffset(Value: integer);
|
||||
begin
|
||||
Value := Max(0, Value);
|
||||
if fLeftOffset <> Value then
|
||||
begin
|
||||
fLeftOffset := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetRightOffset(Value: integer);
|
||||
begin
|
||||
Value := Max(0, Value);
|
||||
if fRightOffset <> Value then
|
||||
begin
|
||||
fRightOffset := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetShowOnlyLineNumbersMultiplesOf(const AValue: integer);
|
||||
begin
|
||||
if FShowOnlyLineNumbersMultiplesOf <> AValue then
|
||||
begin
|
||||
FShowOnlyLineNumbersMultiplesOf := AValue;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetShowLineNumbers(const Value: boolean);
|
||||
begin
|
||||
if fShowLineNumbers <> Value then
|
||||
begin
|
||||
fShowLineNumbers := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetShowCodeFolding(const Value: boolean);
|
||||
begin
|
||||
if fShowCodeFolding <> Value then
|
||||
begin
|
||||
fShowCodeFolding := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetVisible(Value: boolean);
|
||||
begin
|
||||
if fVisible <> Value then
|
||||
begin
|
||||
fVisible := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetWidth(Value: integer);
|
||||
begin
|
||||
Value := Max(0, Value);
|
||||
if fWidth <> Value then
|
||||
begin
|
||||
fWidth := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.SetZeroStart(const Value: boolean);
|
||||
begin
|
||||
if fZeroStart <> Value then
|
||||
begin
|
||||
fZeroStart := Value;
|
||||
DoChange(Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSynGutter.DoChange(Sender: TObject);
|
||||
begin
|
||||
if Assigned(fOnChange) then
|
||||
fOnChange(Self);
|
||||
end;
|
||||
|
||||
{ TSynBookMarkOpt }
|
||||
|
||||
constructor TSynBookMarkOpt.Create(AOwner: TComponent);
|
||||
|
@ -211,6 +211,9 @@ implementation
|
||||
uses
|
||||
SynEdit, SynGutterLineNumber, SynGutterCodeFolding, SynGutterMarks;
|
||||
|
||||
type // This is until InvalidateGutterLines, can be moved to an accessible place
|
||||
SynEditAccess = Class(TCustomSynEdit);
|
||||
|
||||
{ TSynEditMark }
|
||||
|
||||
function TSynEditMark.GetEdit: TSynEditBase;
|
||||
@ -238,23 +241,23 @@ procedure TSynEditMark.SetImage(const Value: Integer);
|
||||
begin
|
||||
FImage := Value;
|
||||
if fVisible and Assigned(fEdit) then
|
||||
TCustomSynEdit(FEdit).InvalidateGutterLines(fLine, fLine);
|
||||
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine);
|
||||
end;
|
||||
|
||||
procedure TSynEditMark.SetInternalImage(const Value: boolean);
|
||||
begin
|
||||
fInternalImage := Value;
|
||||
if fVisible and Assigned(fEdit) then
|
||||
TCustomSynEdit(FEdit).InvalidateGutterLines(fLine, fLine);
|
||||
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine);
|
||||
end;
|
||||
|
||||
procedure TSynEditMark.SetLine(const Value: Integer);
|
||||
begin
|
||||
if fVisible and Assigned(fEdit) then begin
|
||||
if fLine > 0 then
|
||||
TCustomSynEdit(FEdit).InvalidateGutterLines(fLine, fLine);
|
||||
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine);
|
||||
fLine := Value;
|
||||
TCustomSynEdit(FEdit).InvalidateGutterLines(fLine, fLine);
|
||||
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine);
|
||||
end else
|
||||
fLine := Value;
|
||||
end;
|
||||
@ -264,7 +267,7 @@ begin
|
||||
if fVisible <> Value then begin
|
||||
fVisible := Value;
|
||||
if Assigned(fEdit) then
|
||||
TCustomSynEdit(FEdit).InvalidateGutterLines(fLine, fLine);
|
||||
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user