IdeIntf: Improve recursion in TComponentTreeView.FindAndChange. Call RebuildCollection only once per deleted comp. Issue #39290.

This commit is contained in:
Juha 2021-09-26 14:12:48 +03:00
parent 0ffa296511
commit b7ab9549a6

View File

@ -49,15 +49,18 @@ type
FRoot2CollapasedMap: TPointerToPointerTree; FRoot2CollapasedMap: TPointerToPointerTree;
FCollapsedComps: TAVLTree; // The current list of collapsed components. FCollapsedComps: TAVLTree; // The current list of collapsed components.
FDrawWholeTree: Boolean; FDrawWholeTree: Boolean;
FZOrderDelCommand: TZOrderDelete;
// Events // Events
FOnComponentGetImageIndex: TCTVGetImageIndexEvent; FOnComponentGetImageIndex: TCTVGetImageIndexEvent;
FOnModified: TNotifyEvent; FOnModified: TNotifyEvent;
function AddOrGetPersNode(AParentNode: TTreeNode; APers: TPersistent; function AddOrGetPersNode(AParentNode: TTreeNode; APers: TPersistent;
ACapt: String): TTreeNode; ACapt: String): TTreeNode;
procedure AddChildren(AComponent: TComponent; ARootNode: TTreeNode); procedure AddChildren(AComponent: TComponent; ARootNode: TTreeNode);
function FindAndChange(APers: TPersistent; ZOrderDel: TZOrderDelete): Boolean; procedure ChangeNode(ANode: TTreeNode);
function FindAndChange(APers: TPersistent; AZOrderDel: TZOrderDelete): Boolean;
function GetRootObject: TPersistent; function GetRootObject: TPersistent;
function GetSelection: TPersistentSelectionList; function GetSelection: TPersistentSelectionList;
function IterateTree(ANode: TTreeNode; APers: TPersistent): TTreeNode;
procedure NodeCollapsed(Sender: TObject; Node: TTreeNode); procedure NodeCollapsed(Sender: TObject; Node: TTreeNode);
procedure NodeExpanded(Sender: TObject; Node: TTreeNode); procedure NodeExpanded(Sender: TObject; Node: TTreeNode);
procedure RebuildCollection(ANode: TTreeNode); procedure RebuildCollection(ANode: TTreeNode);
@ -783,18 +786,12 @@ begin
end; end;
end; end;
function TComponentTreeView.FindAndChange(APers: TPersistent; procedure TComponentTreeView.ChangeNode(ANode: TTreeNode);
ZOrderDel: TZOrderDelete): Boolean; // Change ZOrder of the given node or delete it.
// APers is Component to be moved or deleted based on ZOrderDel value.
var var
DoneChange: Boolean;
procedure ChangeNode(ANode: TTreeNode);
// Change ZOrder of the given node or delete it.
var
Neighbor: TTreeNode; Neighbor: TTreeNode;
begin begin
case ZOrderDel of case FZOrderDelCommand of
zoToFront: begin // Front means the last sibling. zoToFront: begin // Front means the last sibling.
Neighbor := ANode.GetLastSibling; Neighbor := ANode.GetLastSibling;
if Assigned(Neighbor) then if Assigned(Neighbor) then
@ -817,39 +814,42 @@ var
end; end;
zoDelete: ANode.Delete; // Delete the node zoDelete: ANode.Delete; // Delete the node
end; end;
end; end;
procedure IterateTree(ANode: TTreeNode); function TComponentTreeView.IterateTree(ANode: TTreeNode; APers: TPersistent): TTreeNode;
begin // Returns the node that was changed.
begin
Result := Nil;
if TObject(ANode.Data)=APers then if TObject(ANode.Data)=APers then
begin begin
ChangeNode(ANode); ChangeNode(ANode);
DoneChange := True; Exit(ANode); // Found and changed.
Exit; // Found and changed.
end; end;
// Iterate subnodes. // Iterate subnodes.
ANode := ANode.GetFirstChild; ANode := ANode.GetFirstChild;
while Assigned(ANode) and not DoneChange do while Assigned(ANode) and (Result=Nil) do
begin begin
IterateTree(ANode); // Recursive call. Result := IterateTree(ANode, APers); // Recursive call.
if DoneChange then
begin
// Search a Collection from siblings of the changed node and rebuild if found.
RebuildCollection(ANode); // Needed for FlowPanel.ControlList at least.
Exit; // Found, don't search more.
end;
ANode := ANode.GetNextSibling; ANode := ANode.GetNextSibling;
end; end;
end; end;
function TComponentTreeView.FindAndChange(APers: TPersistent;
AZOrderDel: TZOrderDelete): Boolean;
// APers is Component to be moved or deleted based on AZOrderDel value.
var
ChangedNode: TTreeNode;
begin begin
// Search for a node to change. // Search for a node to change.
Assert(Assigned(APers), 'TComponentTreeView.FindAndChangeItem: APers=Nil.'); Assert(Assigned(APers), 'TComponentTreeView.FindAndChangeItem: APers=Nil.');
Assert(Items.GetFirstNode.GetNextSibling=Nil, Assert(Items.GetFirstNode.GetNextSibling=Nil,
'TComponentTreeView.FindAndChange: Top node has siblings.'); 'TComponentTreeView.FindAndChange: Top node has siblings.');
DoneChange := False; FZOrderDelCommand := AZOrderDel;
IterateTree(Items.GetFirstNode); ChangedNode := IterateTree(Items.GetFirstNode, APers);
Result := DoneChange; Result := Assigned(ChangedNode);
if Result then
// Search a Collection from siblings of the changed node and rebuild if found.
RebuildCollection(ChangedNode); // Needed for FlowPanel.ControlList at least.
end; end;
procedure TComponentTreeView.ChangeCompZOrder(APersistent: TPersistent; procedure TComponentTreeView.ChangeCompZOrder(APersistent: TPersistent;