Skip to content

Commit 8df8d69

Browse files
ElminsterAUSharlikran
authored andcommitted
Attempt at fixing issue #725: TBaseVirtualTree.GetLastVisibleNoInit
The code causes exponential slowdowns when traversing very large trees. I copied the code of GetLastNoInit and replaced the GetLastChildNoInit calls with GetLastVisibleChildNoInit calls. For better performance the 2nd GetLastVisibleChildNoInit call has been replaced with code extracted from GetLastVisibleChildNoInit. This prevents unnecessary calls to FullyVisible while recursing the tree.
1 parent 5d8afe3 commit 8df8d69

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

Source/VirtualTrees.pas

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27832,19 +27832,24 @@ function TBaseVirtualTree.GetLastVisibleNoInit(Node: PVirtualNode = nil;
2783227832

2783327833
// Returns the very last visible node in the tree while optionally considering toChildrenAbove.
2783427834
// No initialization is performed.
27835+
var
27836+
Next: PVirtualNode;
2783527837

2783627838
begin
27837-
Result := GetLastNoInit(Node, ConsiderChildrenAbove);
27838-
while Assigned(Result) and (Result <> Node) do
27839-
begin
27840-
if FullyVisible[Result] and
27841-
(IncludeFiltered or not IsEffectivelyFiltered[Result]) then
27842-
Break;
27843-
Result := GetPreviousNoInit(Result, ConsiderChildrenAbove);
27844-
end;
27845-
27846-
if (Result = Node) then // i.e. there is no visible node
27847-
Result := nil;
27839+
Result := GetLastVisibleChildNoInit(Node, IncludeFiltered);
27840+
if not ConsiderChildrenAbove or not (toChildrenAbove in FOptions.FPaintOptions) then
27841+
while Assigned(Result) and (vsExpanded in Result.States) do
27842+
begin
27843+
// Test if there is a next last child. If not keep the node from the last run.
27844+
// Otherwise use the next last child.
27845+
Next := GetLastChildNoInit(Result);
27846+
if Assigned(Next) and (not (vsVisible in Next.States) or
27847+
(not IncludeFiltered and IsEffectivelyFiltered[Next])) then
27848+
Next := GetPreviousVisibleSiblingNoInit(Next, IncludeFiltered);
27849+
if Next = nil then
27850+
Break;
27851+
Result := Next;
27852+
end;
2784827853
end;
2784927854

2785027855
//----------------------------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)