mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 16:59:09 +02:00
IdeIntf: Improve recursion in TComponentTreeView.FindAndChange. Call RebuildCollection only once per deleted comp. Issue #39290.
This commit is contained in:
parent
0ffa296511
commit
b7ab9549a6
@ -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,73 +786,70 @@ 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;
|
Neighbor: TTreeNode;
|
||||||
|
begin
|
||||||
procedure ChangeNode(ANode: TTreeNode);
|
case FZOrderDelCommand of
|
||||||
// Change ZOrder of the given node or delete it.
|
zoToFront: begin // Front means the last sibling.
|
||||||
var
|
Neighbor := ANode.GetLastSibling;
|
||||||
Neighbor: TTreeNode;
|
if Assigned(Neighbor) then
|
||||||
begin
|
ANode.MoveTo(Neighbor, naInsertBehind);
|
||||||
case ZOrderDel of
|
|
||||||
zoToFront: begin // Front means the last sibling.
|
|
||||||
Neighbor := ANode.GetLastSibling;
|
|
||||||
if Assigned(Neighbor) then
|
|
||||||
ANode.MoveTo(Neighbor, naInsertBehind);
|
|
||||||
end;
|
|
||||||
zoToBack: begin // Back means the first sibling.
|
|
||||||
Neighbor := ANode.GetFirstSibling;
|
|
||||||
if Assigned(Neighbor) then
|
|
||||||
ANode.MoveTo(Neighbor, naInsert);
|
|
||||||
end;
|
|
||||||
zoForward: begin // Towards the end.
|
|
||||||
Neighbor := ANode.GetNextSibling;
|
|
||||||
if Assigned(Neighbor) then
|
|
||||||
ANode.MoveTo(Neighbor, naInsertBehind);
|
|
||||||
end;
|
|
||||||
zoBackward: begin // Towards the beginning.
|
|
||||||
Neighbor := ANode.GetPrevSibling;
|
|
||||||
if Assigned(Neighbor) then
|
|
||||||
ANode.MoveTo(Neighbor, naInsert);
|
|
||||||
end;
|
|
||||||
zoDelete: ANode.Delete; // Delete the node
|
|
||||||
end;
|
end;
|
||||||
|
zoToBack: begin // Back means the first sibling.
|
||||||
|
Neighbor := ANode.GetFirstSibling;
|
||||||
|
if Assigned(Neighbor) then
|
||||||
|
ANode.MoveTo(Neighbor, naInsert);
|
||||||
|
end;
|
||||||
|
zoForward: begin // Towards the end.
|
||||||
|
Neighbor := ANode.GetNextSibling;
|
||||||
|
if Assigned(Neighbor) then
|
||||||
|
ANode.MoveTo(Neighbor, naInsertBehind);
|
||||||
|
end;
|
||||||
|
zoBackward: begin // Towards the beginning.
|
||||||
|
Neighbor := ANode.GetPrevSibling;
|
||||||
|
if Assigned(Neighbor) then
|
||||||
|
ANode.MoveTo(Neighbor, naInsert);
|
||||||
|
end;
|
||||||
|
zoDelete: ANode.Delete; // Delete the node
|
||||||
end;
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure IterateTree(ANode: TTreeNode);
|
function TComponentTreeView.IterateTree(ANode: TTreeNode; APers: TPersistent): TTreeNode;
|
||||||
|
// Returns the node that was changed.
|
||||||
|
begin
|
||||||
|
Result := Nil;
|
||||||
|
if TObject(ANode.Data)=APers then
|
||||||
begin
|
begin
|
||||||
if TObject(ANode.Data)=APers then
|
ChangeNode(ANode);
|
||||||
begin
|
Exit(ANode); // Found and changed.
|
||||||
ChangeNode(ANode);
|
|
||||||
DoneChange := True;
|
|
||||||
Exit; // Found and changed.
|
|
||||||
end;
|
|
||||||
// Iterate subnodes.
|
|
||||||
ANode := ANode.GetFirstChild;
|
|
||||||
while Assigned(ANode) and not DoneChange do
|
|
||||||
begin
|
|
||||||
IterateTree(ANode); // 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;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
// Iterate subnodes.
|
||||||
|
ANode := ANode.GetFirstChild;
|
||||||
|
while Assigned(ANode) and (Result=Nil) do
|
||||||
|
begin
|
||||||
|
Result := IterateTree(ANode, APers); // Recursive call.
|
||||||
|
ANode := ANode.GetNextSibling;
|
||||||
|
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user