mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-07 05:00:43 +02:00
Added SynEdit.FoldAll (bug #12561, modified/ext patch from Brad Campbell)
Added Methods to find Collapsed/Expanded Line for block around cursor git-svn-id: trunk@17279 -
This commit is contained in:
parent
9a0a1e6215
commit
4c1df45cac
@ -754,6 +754,7 @@ type
|
|||||||
procedure CodeFoldAction(iLine: integer);
|
procedure CodeFoldAction(iLine: integer);
|
||||||
function FindNextUnfoldedLine(iLine: integer; Down: boolean): Integer;
|
function FindNextUnfoldedLine(iLine: integer; Down: boolean): Integer;
|
||||||
procedure UnfoldAll;
|
procedure UnfoldAll;
|
||||||
|
procedure FoldAll(StartLevel : Integer = 0; IgnoreNested : Boolean = False);
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
procedure AddKey(Command: TSynEditorCommand; Key1: word; SS1: TShiftState;
|
procedure AddKey(Command: TSynEditorCommand; Key1: word; SS1: TShiftState;
|
||||||
@ -2929,6 +2930,11 @@ begin
|
|||||||
Invalidate;
|
Invalidate;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TCustomSynEdit.FoldAll(StartLevel : Integer = 0; IgnoreNested : Boolean = False);
|
||||||
|
begin
|
||||||
|
fTextView.FoldAll(StartLevel, IgnoreNested);
|
||||||
|
Invalidate;
|
||||||
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
procedure TCustomSynEdit.PaintGutter(AClip: TRect; FirstLine, LastLine: integer);
|
procedure TCustomSynEdit.PaintGutter(AClip: TRect; FirstLine, LastLine: integer);
|
||||||
@ -6078,13 +6084,20 @@ end;
|
|||||||
|
|
||||||
{$IFDEF SYN_LAZARUS}
|
{$IFDEF SYN_LAZARUS}
|
||||||
procedure TCustomSynEdit.FoldChanged(Index : integer);
|
procedure TCustomSynEdit.FoldChanged(Index : integer);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
|
TopLine := TopLine;
|
||||||
|
i := fTextView.CollapsedLineForFoldAtLine(CaretY);
|
||||||
|
if i > 0 then
|
||||||
|
SetCaretXY(Point(1, i))
|
||||||
|
else
|
||||||
|
EnsureCursorPosVisible;
|
||||||
|
UpdateScrollBars;
|
||||||
if Index + 1 > ScreenRowToRow(LinesInWindow + 1) then exit;
|
if Index + 1 > ScreenRowToRow(LinesInWindow + 1) then exit;
|
||||||
if Index + 1 < TopLine then Index := TopLine;
|
if Index + 1 < TopLine then Index := TopLine;
|
||||||
TopLine := TopLine;
|
|
||||||
InvalidateLines(Index + 1, ScreenRowToRow(LinesInWindow + 1));
|
InvalidateLines(Index + 1, ScreenRowToRow(LinesInWindow + 1));
|
||||||
InvalidateGutterLines(Index + 1, ScreenRowToRow(LinesInWindow + 1));
|
InvalidateGutterLines(Index + 1, ScreenRowToRow(LinesInWindow + 1));
|
||||||
UpdateScrollBars;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TCustomSynEdit.SetTopView(const AValue : Integer);
|
procedure TCustomSynEdit.SetTopView(const AValue : Integer);
|
||||||
|
@ -171,7 +171,6 @@ type
|
|||||||
fOnFoldChanged : TFoldChangedEvent;
|
fOnFoldChanged : TFoldChangedEvent;
|
||||||
fCFDividerDrawLevel: Integer;
|
fCFDividerDrawLevel: Integer;
|
||||||
|
|
||||||
procedure debug;
|
|
||||||
function GetCount : integer;
|
function GetCount : integer;
|
||||||
function GetDrawDivider(Index : integer) : Boolean;
|
function GetDrawDivider(Index : integer) : Boolean;
|
||||||
function GetLines(index : Integer) : String;
|
function GetLines(index : Integer) : String;
|
||||||
@ -203,6 +202,7 @@ type
|
|||||||
constructor Create(aTextBuffer : TSynEditStringList);
|
constructor Create(aTextBuffer : TSynEditStringList);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
|
||||||
|
// Converting between Folded and Unfolded Lines/Indexes
|
||||||
function TextIndexToViewPos(aTextIndex : Integer) : Integer; (* Convert TextIndex (0-based) to ViewPos (1-based) *)
|
function TextIndexToViewPos(aTextIndex : Integer) : Integer; (* Convert TextIndex (0-based) to ViewPos (1-based) *)
|
||||||
function TextIndexToScreenLine(aTextIndex : Integer) : Integer; (* Convert TextIndex (0-based) to Screen (0-based) *)
|
function TextIndexToScreenLine(aTextIndex : Integer) : Integer; (* Convert TextIndex (0-based) to Screen (0-based) *)
|
||||||
function ViewPosToTextIndex(aViewPos : Integer) : Integer; (* Convert ViewPos (1-based) to TextIndex (0-based) *)
|
function ViewPosToTextIndex(aViewPos : Integer) : Integer; (* Convert ViewPos (1-based) to TextIndex (0-based) *)
|
||||||
@ -211,6 +211,7 @@ type
|
|||||||
function TextIndexAddLines(aTextIndex, LineOffset : Integer) : Integer; (* Add/Sub to/from TextIndex (0-based) skipping folded *)
|
function TextIndexAddLines(aTextIndex, LineOffset : Integer) : Integer; (* Add/Sub to/from TextIndex (0-based) skipping folded *)
|
||||||
function TextPosAddLines(aTextpos, LineOffset : Integer) : Integer; (* Add/Sub to/from TextPos (1-based) skipping folded *)
|
function TextPosAddLines(aTextpos, LineOffset : Integer) : Integer; (* Add/Sub to/from TextPos (1-based) skipping folded *)
|
||||||
|
|
||||||
|
// Attributes for Visible-Lines-On-screen
|
||||||
property Lines[index : Integer] : String (* Lines on screen / 0 = TopLine *)
|
property Lines[index : Integer] : String (* Lines on screen / 0 = TopLine *)
|
||||||
read GetLines; default;
|
read GetLines; default;
|
||||||
property Ranges[Index: integer]: TSynEditRange
|
property Ranges[Index: integer]: TSynEditRange
|
||||||
@ -224,6 +225,7 @@ type
|
|||||||
property TextIndex[index : Integer] : Integer (* Position in SynTextBuffer / result is 0-based *)
|
property TextIndex[index : Integer] : Integer (* Position in SynTextBuffer / result is 0-based *)
|
||||||
read GetTextIndex; // maybe writable
|
read GetTextIndex; // maybe writable
|
||||||
|
|
||||||
|
// Define Visible Area
|
||||||
property TopLine : integer (* refers to visible (unfolded) lines / 1-based *)
|
property TopLine : integer (* refers to visible (unfolded) lines / 1-based *)
|
||||||
read fTopLine write SetTopLine;
|
read fTopLine write SetTopLine;
|
||||||
property TopTextIndex : integer (* refers to TextIndex (folded + unfolded lines) / 1-based *)
|
property TopTextIndex : integer (* refers to TextIndex (folded + unfolded lines) / 1-based *)
|
||||||
@ -236,6 +238,8 @@ type
|
|||||||
property CFDividerDrawLevel: Integer read fCFDividerDrawLevel write fCFDividerDrawLevel;
|
property CFDividerDrawLevel: Integer read fCFDividerDrawLevel write fCFDividerDrawLevel;
|
||||||
|
|
||||||
public
|
public
|
||||||
|
procedure debug;
|
||||||
|
// Action Fold/Unfold
|
||||||
procedure FoldAtLine(AStartLine: Integer); (* Folds at ScreenLine / 0-based *)
|
procedure FoldAtLine(AStartLine: Integer); (* Folds at ScreenLine / 0-based *)
|
||||||
procedure FoldAtViewPos(AStartPos: Integer); (* Folds at nth visible/unfolded Line / 1-based *)
|
procedure FoldAtViewPos(AStartPos: Integer); (* Folds at nth visible/unfolded Line / 1-based *)
|
||||||
procedure FoldAtTextIndex(AStartIndex: Integer); (* Folds at nth TextIndex (all lines in buffer) / 1-based *)
|
procedure FoldAtTextIndex(AStartIndex: Integer); (* Folds at nth TextIndex (all lines in buffer) / 1-based *)
|
||||||
@ -244,11 +248,17 @@ type
|
|||||||
procedure UnFoldAtTextIndex(AStartIndex: Integer; IgnoreFirst : Boolean = False); (* UnFolds at nth TextIndex (all lines in buffer) / 1-based *)
|
procedure UnFoldAtTextIndex(AStartIndex: Integer; IgnoreFirst : Boolean = False); (* UnFolds at nth TextIndex (all lines in buffer) / 1-based *)
|
||||||
|
|
||||||
procedure UnfoldAll;
|
procedure UnfoldAll;
|
||||||
|
procedure FoldAll(StartLevel : Integer = 0; IgnoreNested : Boolean = False);
|
||||||
procedure FixFoldingAtTextIndex(AStartIndex: Integer; AMinEndLine: Integer = 0); // Real/All lines
|
procedure FixFoldingAtTextIndex(AStartIndex: Integer; AMinEndLine: Integer = 0); // Real/All lines
|
||||||
|
|
||||||
|
// Find the visible first line of the fold at ALine. Returns -1 if Aline is not folded
|
||||||
|
function CollapsedLineForFoldAtLine(ALine : Integer) : Integer;
|
||||||
|
function ExpandedLineForBlockAtLine(ALine : Integer) : Integer;
|
||||||
|
|
||||||
|
property FoldedAtTextIndex [index : integer] : Boolean read IsFolded;
|
||||||
|
|
||||||
property OnFoldChanged: TFoldChangedEvent (* reports 1-based line *) {TODO: synedit expects 0 based }
|
property OnFoldChanged: TFoldChangedEvent (* reports 1-based line *) {TODO: synedit expects 0 based }
|
||||||
read fOnFoldChanged write fOnFoldChanged;
|
read fOnFoldChanged write fOnFoldChanged;
|
||||||
property FoldedAtTextIndex [index : integer] : Boolean read IsFolded;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -902,11 +912,17 @@ begin
|
|||||||
|
|
||||||
rFoldedBefore := rFoldedBefore + current.LeftCount;
|
rFoldedBefore := rFoldedBefore + current.LeftCount;
|
||||||
if ALine = rStartLine then begin
|
if ALine = rStartLine then begin
|
||||||
if ACount < current.LineCount
|
if ACount < current.LineCount then
|
||||||
(* *** New Block will be nested in current *** *)
|
(* *** New Block will be nested in current *** *)
|
||||||
then NestNewBlockIntoCurrent
|
NestNewBlockIntoCurrent
|
||||||
(* *** current will be nested in New Block *** *)
|
else
|
||||||
else NestCurrentIntoNewBlock;
|
if ACount > current.LineCount then
|
||||||
|
(* *** current will be nested in New Block *** *)
|
||||||
|
NestCurrentIntoNewBlock
|
||||||
|
else begin
|
||||||
|
debugln(['Droping Foldnode / Already exists. Startline=', rStartLine,' LineCount=',ACount]);
|
||||||
|
ANode.Free;
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else begin
|
else begin
|
||||||
If ALine <= rStartLine + current.LineCount - 1
|
If ALine <= rStartLine + current.LineCount - 1
|
||||||
@ -1598,6 +1614,31 @@ begin
|
|||||||
fOnFoldChanged(0);
|
fOnFoldChanged(0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TSynEditFoldedView.FoldAll(StartLevel : Integer = 0; IgnoreNested : Boolean = False);
|
||||||
|
var
|
||||||
|
i, l, top: Integer;
|
||||||
|
begin
|
||||||
|
top := TopTextIndex;
|
||||||
|
fFoldTree.Clear;
|
||||||
|
i := 0;
|
||||||
|
while i < fLines.Count do begin
|
||||||
|
if (fLines.FoldEndLevel[i] > fLines.FoldMinLevel[i])
|
||||||
|
and (fLines.FoldEndLevel[i] > StartLevel) then begin
|
||||||
|
l := LengthForFoldAtTextIndex(i);
|
||||||
|
// i is 0-based
|
||||||
|
// FoldTree is 1-based AND first line remains visble
|
||||||
|
fFoldTree.InsertNewFold(i+2, l);
|
||||||
|
if IgnoreNested then
|
||||||
|
i := i + l;
|
||||||
|
end;
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
fTopLine := -1;
|
||||||
|
TopTextIndex := top;
|
||||||
|
if Assigned(fOnFoldChanged) then
|
||||||
|
fOnFoldChanged(0);
|
||||||
|
end;
|
||||||
|
|
||||||
function TSynEditFoldedView.FixFolding(AStart : Integer; AMinEnd : Integer; aFoldTree : TSynTextFoldAVLTree) : Boolean;
|
function TSynEditFoldedView.FixFolding(AStart : Integer; AMinEnd : Integer; aFoldTree : TSynTextFoldAVLTree) : Boolean;
|
||||||
var
|
var
|
||||||
line, a : Integer;
|
line, a : Integer;
|
||||||
@ -1661,6 +1702,52 @@ begin
|
|||||||
FixFolding(AStartIndex + 1, AMinEndLine, fFoldTree);
|
FixFolding(AStartIndex + 1, AMinEndLine, fFoldTree);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSynEditFoldedView.ExpandedLineForBlockAtLine(ALine : Integer) : Integer;
|
||||||
|
var
|
||||||
|
i, l : Integer;
|
||||||
|
node: TSynTextFoldAVLNode;
|
||||||
|
begin
|
||||||
|
Result := -1;
|
||||||
|
i := ALine-1;
|
||||||
|
|
||||||
|
if (i>0) and (fLines.FoldMinLevel[i] < fLines.FoldEndLevel[i-1])then begin
|
||||||
|
if fLines.FoldMinLevel[i] < fLines.FoldEndLevel[i] then begin
|
||||||
|
// this is a combined "end begin" line
|
||||||
|
node := fFoldTree.FindFoldForLine(ALine, true);
|
||||||
|
if node.IsInFold and (node.StartLine = ALine +1) then
|
||||||
|
dec(i);
|
||||||
|
if i < 0 then exit;
|
||||||
|
end else begin
|
||||||
|
// this is a "end" line
|
||||||
|
dec(i);
|
||||||
|
end;
|
||||||
|
l := fLines.FoldEndLevel[i];
|
||||||
|
end else if fLines.FoldEndLevel[i] = 0 then
|
||||||
|
exit
|
||||||
|
else begin
|
||||||
|
// check if current line is cfCollapsed
|
||||||
|
node := fFoldTree.FindFoldForLine(ALine, true);
|
||||||
|
if node.IsInFold and (node.StartLine = ALine +1) then
|
||||||
|
dec(i);
|
||||||
|
if i < 0 then exit;
|
||||||
|
l := fLines.FoldEndLevel[i]
|
||||||
|
end;
|
||||||
|
|
||||||
|
while (i > 0) and (fLines.FoldMinLevel[i] >= l) do
|
||||||
|
dec(i);
|
||||||
|
if (fLines.FoldEndLevel[i] > 0) then // TODO, check for collapsed at index = 0
|
||||||
|
Result := i + 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSynEditFoldedView.CollapsedLineForFoldAtLine(ALine : Integer) : Integer;
|
||||||
|
var
|
||||||
|
node: TSynTextFoldAVLNode;
|
||||||
|
begin
|
||||||
|
Result := -1;
|
||||||
|
node := fFoldTree.FindFoldForLine(ALine, false);
|
||||||
|
if node.IsInFold then Result := node.StartLine-1;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TSynEditFoldedView.debug;
|
procedure TSynEditFoldedView.debug;
|
||||||
procedure debug2(ind, typ : String; ANode, AParent : TSynTextFoldAVLNodeData; offset : integer);
|
procedure debug2(ind, typ : String; ANode, AParent : TSynTextFoldAVLNodeData; offset : integer);
|
||||||
begin
|
begin
|
||||||
|
Loading…
Reference in New Issue
Block a user