mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-05-01 21:24:24 +02:00
190 lines
5.0 KiB
ObjectPascal
190 lines
5.0 KiB
ObjectPascal
unit SynGutterCodeFolding;
|
|
|
|
{$I synedit.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Graphics, LCLType, LCLIntf, SynGutter,
|
|
SynEditMiscClasses, SynEditMiscProcs, SynEditFoldedView;
|
|
|
|
type
|
|
|
|
{ TSynGutterCodeFolding }
|
|
|
|
TSynGutterCodeFolding = class(TSynGutterPartBase)
|
|
private
|
|
FEdit: TSynEditBase;
|
|
FFoldView: TSynEditFoldedView;
|
|
FMarkupInfoCodeFoldingTree: TSynSelectedColor;
|
|
public
|
|
constructor Create(AOwner : TSynEditBase; AFoldView : TSynEditFoldedView);
|
|
|
|
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer);
|
|
override;
|
|
function RealGutterWidth(CharWidth: integer): integer; override;
|
|
procedure DoOnGutterClick(X, Y: integer); override;
|
|
public
|
|
property MarkupInfoCodeFoldingTree: TSynSelectedColor read FMarkupInfoCodeFoldingTree;
|
|
end;
|
|
|
|
implementation
|
|
uses
|
|
SynEdit;
|
|
|
|
{ TSynGutterCodeFolding }
|
|
|
|
constructor TSynGutterCodeFolding.Create(AOwner : TSynEditBase;
|
|
AFoldView : TSynEditFoldedView);
|
|
begin
|
|
inherited Create;
|
|
FEdit := AOwner;
|
|
FFoldView := AFoldView;
|
|
|
|
FMarkupInfoCodeFoldingTree := TSynSelectedColor.Create;
|
|
FMarkupInfoCodeFoldingTree.Background := clNone;
|
|
FMarkupInfoCodeFoldingTree.Foreground := clDkGray;
|
|
FMarkupInfoCodeFoldingTree.FrameColor := clNone;
|
|
FMarkupInfoCodeFoldingTree.OnChange := @DoChange;
|
|
|
|
Width := 14;
|
|
end;
|
|
|
|
function TSynGutterCodeFolding.RealGutterWidth(CharWidth : integer) : integer;
|
|
begin
|
|
If Visible then
|
|
Result := Width
|
|
else
|
|
Result := 0;
|
|
end;
|
|
|
|
procedure TSynGutterCodeFolding.DoOnGutterClick(X, Y : integer);
|
|
var
|
|
line : integer;
|
|
begin
|
|
line := TSynEdit(FEdit).PixelsToRowColumn(Point(X, Y)).Y;
|
|
if line <= TSynEdit(FEdit).Lines.Count then
|
|
TSynEdit(FEdit).CodeFoldAction(line);
|
|
end;
|
|
|
|
procedure TSynGutterCodeFolding.Paint(Canvas : TCanvas; AClip : TRect; FirstLine, LastLine : integer);
|
|
var
|
|
iLine: integer;
|
|
rcLine: TRect;
|
|
rcCodeFold: TRect;
|
|
tmp: TSynEditCodeFoldType;
|
|
LineHeight, LineOffset: Integer;
|
|
|
|
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;
|
|
LineOffset := 0;
|
|
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 + LineOffset);
|
|
Canvas.LineTo(iCenter, rcCodeFold.Bottom);
|
|
LineOffset := 0;
|
|
end;
|
|
|
|
procedure DrawParagraphEnd(rcCodeFold: TRect);
|
|
var
|
|
X : Integer;
|
|
begin
|
|
//center of the draw area
|
|
X := (rcCodeFold.Left + rcCodeFold.Right) div 2;
|
|
|
|
Canvas.MoveTo(X, rcCodeFold.Top + LineOffset);
|
|
Canvas.LineTo(X, rcCodeFold.Bottom - 1);
|
|
Canvas.LineTo(rcCodeFold.Right, rcCodeFold.Bottom - 1);
|
|
LineOffset := min(2, (rcCodeFold.Top + rcCodeFold.Bottom) div 2);
|
|
end;
|
|
|
|
begin
|
|
if not Visible then exit;
|
|
LineHeight := TSynEdit(FEdit).LineHeight;
|
|
LineOffset := 0;
|
|
|
|
if MarkupInfoCodeFoldingTree.Background <> clNone then
|
|
begin
|
|
Canvas.Brush.Color := MarkupInfoCodeFoldingTree.Background;
|
|
{$IFDEF SYN_LAZARUS}
|
|
LCLIntf.SetBkColor(Canvas.Handle, Canvas.Brush.Color);
|
|
{$ENDIF}
|
|
Canvas.FillRect(AClip);
|
|
end;
|
|
|
|
with Canvas do
|
|
begin
|
|
Pen.Color := MarkupInfoCodeFoldingTree.Foreground;
|
|
Pen.Width := 1;
|
|
|
|
rcLine.Bottom := FirstLine * LineHeight;
|
|
for iLine := FirstLine to LastLine do
|
|
begin
|
|
// next line rect
|
|
rcLine.Top := rcLine.Bottom;
|
|
Inc(rcLine.Bottom, LineHeight);
|
|
|
|
rcCodeFold.Left := AClip.Left;
|
|
rcCodeFold.Right := AClip.Left + self.Width;
|
|
rcCodeFold.Top := rcLine.Top;
|
|
rcCodeFold.Bottom := rcLine.Bottom;
|
|
|
|
tmp := FFoldView.FoldType[iLine];
|
|
|
|
case tmp of
|
|
cfCollapsed: DrawNodeBox(rcCodeFold, True);
|
|
cfExpanded: DrawNodeBox(rcCodeFold, False);
|
|
cfContinue: DrawParagraphContinue(rcCodeFold);
|
|
cfEnd: DrawParagraphEnd(rcCodeFold);
|
|
else LineOffset := 0;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
end.
|
|
|