mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-26 23:03:48 +02:00
SynEdit: Improved TLazSynEditNestedFoldsList, keep filtered node-infos
git-svn-id: trunk@37886 -
This commit is contained in:
parent
09c3e91542
commit
bf59a09199
components/synedit
@ -45,7 +45,7 @@ unit SynEditFoldedView;
|
||||
interface
|
||||
|
||||
uses
|
||||
LCLProc, LazLoggerBase, Graphics,
|
||||
LCLProc, LazLoggerBase, LazClasses, Graphics,
|
||||
Classes, SysUtils, LazSynEditText, SynEditTypes, SynEditMiscClasses,
|
||||
SynEditMiscProcs, SynEditPointClasses,
|
||||
SynEditHighlighter, SynEditHighlighterFoldBase;
|
||||
@ -323,6 +323,9 @@ type
|
||||
FIncludeOpeningOnLine: Boolean;
|
||||
FNestInfo: Array of TLazSynEditNestedFoldsListEntry;
|
||||
FEvaluationIndex: Integer;
|
||||
FFoldNodeInfoList: TLazSynFoldNodeInfoList;
|
||||
FFoldNodeInfoListHoldCnt: integer;
|
||||
|
||||
function GetHLNode(Index: Integer): TSynFoldNodeInfo;
|
||||
function GetNodeFoldGroup(Index: Integer): Integer;
|
||||
function GetNodeFoldType(Index: Integer): Pointer;
|
||||
@ -330,6 +333,9 @@ type
|
||||
procedure InitNestInfoForIndex(AnIndex: Integer);
|
||||
procedure SetFoldFlags(AValue: TSynFoldBlockFilterFlags);
|
||||
procedure SetIncludeOpeningOnLine(AValue: Boolean);
|
||||
function GetOpeningOnLineCount(const AHighlighter: TSynCustomFoldHighlighter; AFoldGroup: Integer): Integer; // ignores FFoldFlags
|
||||
procedure AquireFoldNodeInfoList(const AHighlighter: TSynCustomFoldHighlighter; const ALine: Integer = -1);
|
||||
procedure ReleaseFoldNodeInfoList;
|
||||
public
|
||||
constructor Create(aFoldProvider: TSynEditFoldProvider);
|
||||
procedure Clear;
|
||||
@ -2878,11 +2884,18 @@ begin
|
||||
FGroupCount := hl.FoldTypeCount;
|
||||
// start at 1, so FoldGroup can be used as index
|
||||
SetLength(FGroupEndLevelsAtEval, FGroupCount + 1);
|
||||
for i := 1 to FGroupCount do begin
|
||||
FGroupEndLevelsAtEval[i] := hl.FoldBlockEndLevel(FLine - 1, i, FFoldFlags);
|
||||
// TODO: adjust flags, if include disabled
|
||||
if FIncludeOpeningOnLine then
|
||||
AquireFoldNodeInfoList(hl, FLine);
|
||||
try
|
||||
for i := 1 to FGroupCount do begin
|
||||
FGroupEndLevelsAtEval[i] := hl.FoldBlockEndLevel(FLine - 1, i, FFoldFlags);
|
||||
// TODO: adjust flags, if include disabled
|
||||
if FIncludeOpeningOnLine then
|
||||
FGroupEndLevelsAtEval[i] := FGroupEndLevelsAtEval[i] + GetOpeningOnLineCount(hl, i);
|
||||
end;
|
||||
finally
|
||||
if FIncludeOpeningOnLine then
|
||||
FGroupEndLevelsAtEval[i] := FGroupEndLevelsAtEval[i] + hl.FoldNodeInfo[FLine].CountEx([sfaOpen, sfaFold], i);
|
||||
ReleaseFoldNodeInfoList;
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
@ -2928,72 +2941,82 @@ procedure TLazSynEditNestedFoldsList.InitNestInfoForIndex(AnIndex: Integer);
|
||||
var
|
||||
CurLine: TLineIdx;
|
||||
hl: TSynCustomFoldHighlighter;
|
||||
i, i2, c, t, l: Integer;
|
||||
i, c, t, l: Integer;
|
||||
NFilter: TSynFoldActions;
|
||||
nd: TSynFoldNodeInfo;
|
||||
begin
|
||||
if (AnIndex >= Count) or (AnIndex >= FEvaluationIndex) then exit;
|
||||
hl := FFoldProvider.HighLighterWithLines;
|
||||
if hl = nil then exit;
|
||||
|
||||
InitSubGroupEndLevels;
|
||||
if (FEvaluationIndex = Count) then begin
|
||||
if (OpeningOnLineCount > 0) then
|
||||
CurLine := Line
|
||||
else
|
||||
CurLine := Line - 1
|
||||
end
|
||||
else
|
||||
CurLine := FNestInfo[FEvaluationIndex].LineIdx - 1;
|
||||
AquireFoldNodeInfoList(hl);
|
||||
try
|
||||
if (AnIndex >= Count) or (AnIndex >= FEvaluationIndex) then exit;
|
||||
|
||||
inc(CurLine);
|
||||
while CurLine > 0 do begin
|
||||
dec(CurLine);
|
||||
|
||||
if FFoldGroup = 0 then begin
|
||||
i := FGroupCount;
|
||||
while (i > 0) and
|
||||
(hl.FoldBlockMinLevel(CurLine, i, FFoldFlags) >= FGroupEndLevelsAtEval[i])
|
||||
do
|
||||
dec(i);
|
||||
if i <= 0 then continue;
|
||||
end
|
||||
else begin
|
||||
if hl.FoldBlockMinLevel(CurLine, FFoldGroup, FFoldFlags) >= FGroupEndLevelsAtEval[0] then
|
||||
continue;
|
||||
end;
|
||||
|
||||
// something of interest opened on this line
|
||||
NFilter := [sfaOpen];
|
||||
if not(sfbIncludeDisabled in FFoldFlags) then Include(NFilter, sfaFold);
|
||||
c := hl.FoldNodeInfo[CurLine].CountEx(NFilter, FFoldGroup) - 1;
|
||||
for i := c downto 0 do begin
|
||||
nd := hl.FoldNodeInfo[CurLine].NodeInfoEx(i, NFilter, FFoldGroup);
|
||||
|
||||
if FFoldGroup = 0 then
|
||||
t := nd.FoldGroup
|
||||
InitSubGroupEndLevels;
|
||||
if (FEvaluationIndex = Count) then begin
|
||||
if (OpeningOnLineCount > 0) then
|
||||
CurLine := Line
|
||||
else
|
||||
t := 0;
|
||||
CurLine := Line - 1
|
||||
end
|
||||
else
|
||||
CurLine := FNestInfo[FEvaluationIndex].LineIdx - 1;
|
||||
|
||||
if (sfbIncludeDisabled in FFoldFlags)
|
||||
then l := nd.NestLvlStart
|
||||
else l := nd.FoldLvlStart;
|
||||
if l >= FGroupEndLevelsAtEval[t] then continue;
|
||||
inc(CurLine);
|
||||
while CurLine > 0 do begin
|
||||
dec(CurLine);
|
||||
|
||||
dec(FGroupEndLevelsAtEval[t]);
|
||||
dec(FEvaluationIndex);
|
||||
if FFoldGroup = 0 then begin
|
||||
i := FGroupCount;
|
||||
while (i > 0) and
|
||||
(hl.FoldBlockMinLevel(CurLine, i, FFoldFlags) >= FGroupEndLevelsAtEval[i])
|
||||
do
|
||||
dec(i);
|
||||
if i <= 0 then continue;
|
||||
end
|
||||
else begin
|
||||
if hl.FoldBlockMinLevel(CurLine, FFoldGroup, FFoldFlags) >= FGroupEndLevelsAtEval[0] then
|
||||
continue;
|
||||
end;
|
||||
|
||||
assert(FGroupEndLevelsAtEval[t] >= 0, 'TLazSynEditNestedFoldsList.InitNestInfoForIndex GroupEndLevel < 0');
|
||||
assert(FEvaluationIndex >= 0, 'TLazSynEditNestedFoldsList.InitNestInfoForIndex FEvaluationIndex < 0');
|
||||
// something of interest opened on this line
|
||||
NFilter := [sfaOpen];
|
||||
if not(sfbIncludeDisabled in FFoldFlags) then Include(NFilter, sfaFold);
|
||||
FFoldNodeInfoList.Line := CurLine;
|
||||
FFoldNodeInfoList.ActionFilter := NFilter;
|
||||
FFoldNodeInfoList.GroupFilter := FFoldGroup;
|
||||
c := FFoldNodeInfoList.Count - 1;
|
||||
//c := hl.FoldNodeInfo[CurLine].CountEx(NFilter, FFoldGroup) - 1;
|
||||
for i := c downto 0 do begin
|
||||
nd := FFoldNodeInfoList[i];
|
||||
//nd := hl.FoldNodeInfo[CurLine].NodeInfoEx(i, NFilter, FFoldGroup);
|
||||
|
||||
FNestInfo[FEvaluationIndex].LineIdx := CurLine;
|
||||
FNestInfo[FEvaluationIndex].HNode := nd;
|
||||
if FFoldGroup = 0 then
|
||||
t := nd.FoldGroup
|
||||
else
|
||||
t := 0;
|
||||
|
||||
if (sfbIncludeDisabled in FFoldFlags)
|
||||
then l := nd.NestLvlStart
|
||||
else l := nd.FoldLvlStart;
|
||||
if l >= FGroupEndLevelsAtEval[t] then continue;
|
||||
|
||||
dec(FGroupEndLevelsAtEval[t]);
|
||||
dec(FEvaluationIndex);
|
||||
|
||||
assert(FGroupEndLevelsAtEval[t] >= 0, 'TLazSynEditNestedFoldsList.InitNestInfoForIndex GroupEndLevel < 0');
|
||||
assert(FEvaluationIndex >= 0, 'TLazSynEditNestedFoldsList.InitNestInfoForIndex FEvaluationIndex < 0');
|
||||
|
||||
FNestInfo[FEvaluationIndex].LineIdx := CurLine;
|
||||
FNestInfo[FEvaluationIndex].HNode := nd;
|
||||
end;
|
||||
|
||||
if (AnIndex >= FEvaluationIndex) then Break;
|
||||
end;
|
||||
|
||||
if (AnIndex >= FEvaluationIndex) then Break;
|
||||
finally
|
||||
ReleaseFoldNodeInfoList;
|
||||
end;
|
||||
|
||||
|
||||
assert(AnIndex >= FEvaluationIndex, 'TLazSynEditNestedFoldsList.InitNestInfoForIndex Index not found');
|
||||
end;
|
||||
|
||||
@ -3011,6 +3034,24 @@ begin
|
||||
Clear;
|
||||
end;
|
||||
|
||||
procedure TLazSynEditNestedFoldsList.AquireFoldNodeInfoList(const AHighlighter: TSynCustomFoldHighlighter;
|
||||
const ALine: Integer);
|
||||
begin
|
||||
if FFoldNodeInfoListHoldCnt = 0 then begin
|
||||
FFoldNodeInfoList := AHighlighter.FoldNodeInfo[ALine];
|
||||
FFoldNodeInfoList.AddReference;
|
||||
end else
|
||||
FFoldNodeInfoList.Line := ALine;
|
||||
inc(FFoldNodeInfoListHoldCnt);
|
||||
end;
|
||||
|
||||
procedure TLazSynEditNestedFoldsList.ReleaseFoldNodeInfoList;
|
||||
begin
|
||||
dec(FFoldNodeInfoListHoldCnt);
|
||||
if FFoldNodeInfoListHoldCnt = 0 then
|
||||
ReleaseRefAndNil(FFoldNodeInfoList);
|
||||
end;
|
||||
|
||||
procedure TLazSynEditNestedFoldsList.SetFoldGroup(AValue: Integer);
|
||||
begin
|
||||
if FFoldGroup = AValue then Exit;
|
||||
@ -3024,6 +3065,7 @@ begin
|
||||
FIncludeOpeningOnLine := True;
|
||||
FFoldFlags := [];
|
||||
FFoldGroup := 0;
|
||||
FFoldNodeInfoListHoldCnt := 0;
|
||||
end;
|
||||
|
||||
function TLazSynEditNestedFoldsList.Count: Integer;
|
||||
@ -3041,29 +3083,39 @@ begin
|
||||
Result := FCount;
|
||||
end;
|
||||
|
||||
function TLazSynEditNestedFoldsList.GetOpeningOnLineCount(const AHighlighter: TSynCustomFoldHighlighter;
|
||||
AFoldGroup: Integer): Integer;
|
||||
begin
|
||||
AquireFoldNodeInfoList(AHighlighter, FLine);
|
||||
try
|
||||
// TODO: adjust flags, if include disabled
|
||||
//NFilter := [sfaOpen];
|
||||
//if not(sfbIncludeDisabled in FFoldFlags) then Include(NFilter, sfaFold);
|
||||
FFoldNodeInfoList.ActionFilter := [sfaOpen, sfaFold];
|
||||
FFoldNodeInfoList.GroupFilter := AFoldGroup;
|
||||
|
||||
// Need to check alll nodes with FoldNodeInfoCount
|
||||
// Hide-able nodes can open and close on the same line "(* comment *)"
|
||||
Result := FFoldNodeInfoList.Count;
|
||||
finally
|
||||
ReleaseFoldNodeInfoList;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TLazSynEditNestedFoldsList.OpeningOnLineCount: Integer;
|
||||
var
|
||||
hl: TSynCustomFoldHighlighter;
|
||||
begin
|
||||
if (not FIncludeOpeningOnLine) or (FLine < 0) then
|
||||
exit(0);
|
||||
|
||||
Result := FOpeningOnLineCount;
|
||||
if Result >= 0 then exit;
|
||||
|
||||
FOpeningOnLineCount := 0;
|
||||
hl := FFoldProvider.HighLighterWithLines;
|
||||
if hl = nil then
|
||||
exit(0);
|
||||
|
||||
// TODO: adjust flags, if include disabled
|
||||
//NFilter := [sfaOpen];
|
||||
//if not(sfbIncludeDisabled in FFoldFlags) then Include(NFilter, sfaFold);
|
||||
|
||||
// Need to check alll nodes with FoldNodeInfoCount
|
||||
// Hide-able nodes can open and close on the same line "(* comment *)"
|
||||
FOpeningOnLineCount := hl.FoldNodeInfo[FLine].CountEx([sfaOpen, sfaFold], FFoldGroup);
|
||||
Result := FOpeningOnLineCount;
|
||||
if Result >= 0 then exit;
|
||||
|
||||
FOpeningOnLineCount := GetOpeningOnLineCount(hl, FFoldGroup);
|
||||
Result := FOpeningOnLineCount;
|
||||
end;
|
||||
|
||||
|
@ -150,9 +150,11 @@ type
|
||||
protected
|
||||
procedure Invalidate;
|
||||
procedure Clear;
|
||||
procedure ClearData;
|
||||
procedure ClearFilteredList;
|
||||
procedure DoFilter(MinIndex: Integer = -1);
|
||||
procedure SetLine(ALine: TLineIdx);
|
||||
procedure SetLineClean(ALine: TLineIdx);
|
||||
procedure Add(const AnInfo: TSynFoldNodeInfo);
|
||||
procedure Delete(AnIndex: Integer = -1);
|
||||
function CountAll: Integer;
|
||||
@ -505,8 +507,16 @@ procedure TLazSynFoldNodeInfoList.Clear;
|
||||
var
|
||||
c: Integer;
|
||||
begin
|
||||
FValid := True;
|
||||
ClearFilter;
|
||||
ClearData;
|
||||
end;
|
||||
|
||||
procedure TLazSynFoldNodeInfoList.ClearData;
|
||||
var
|
||||
c: Integer;
|
||||
begin
|
||||
FValid := True;
|
||||
ClearFilteredList;
|
||||
FLine := -1;
|
||||
c := MinCapacity;
|
||||
FNodeCount := 0;
|
||||
@ -556,7 +566,15 @@ end;
|
||||
|
||||
procedure TLazSynFoldNodeInfoList.SetLine(ALine: TLineIdx);
|
||||
begin
|
||||
if FLine = ALine then exit;
|
||||
if (FLine = ALine) or (ALine < 0) then exit;
|
||||
ClearData;
|
||||
FLine := ALine;
|
||||
FHighLighter.InitFoldNodeInfo(Self, FLine);
|
||||
end;
|
||||
|
||||
procedure TLazSynFoldNodeInfoList.SetLineClean(ALine: TLineIdx);
|
||||
begin
|
||||
if (FLine = ALine) or (ALine < 0) then exit;
|
||||
Clear;
|
||||
FLine := ALine;
|
||||
FHighLighter.InitFoldNodeInfo(Self, FLine);
|
||||
@ -1001,7 +1019,7 @@ begin
|
||||
end;
|
||||
|
||||
Result := FFoldNodeInfoList;
|
||||
Result.Line := Line;
|
||||
Result.SetLineClean(Line);
|
||||
end;
|
||||
|
||||
procedure TSynCustomFoldHighlighter.InitFoldNodeInfo(AList: TLazSynFoldNodeInfoList; Line: TLineIdx);
|
||||
|
Loading…
Reference in New Issue
Block a user