mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-05 07:17:50 +01:00
IdeIntf, Designer: Improve deleting components from OI's tree. Make a special case for PairSplitterSide. Issue #38235.
git-svn-id: trunk@64254 -
This commit is contained in:
parent
da1542668b
commit
deba76613b
@ -47,16 +47,13 @@ type
|
||||
FPropertyEditorHook: TPropertyEditorHook;
|
||||
FRootNode: TTreeNode;
|
||||
FDrawWholeTree: Boolean;
|
||||
// A Component (Persistent) to be moved or deleted based on FZOrderDelete value.
|
||||
FPersToChange: TPersistent;
|
||||
FZOrderDelete: TZOrderDelete;
|
||||
// Events
|
||||
FOnComponentGetImageIndex: TCTVGetImageIndexEvent;
|
||||
FOnModified: TNotifyEvent;
|
||||
function AddOrGetPersNode(AParentNode: TTreeNode; APers: TPersistent;
|
||||
ACapt: String): TTreeNode;
|
||||
procedure AddChildren(AComponent: TComponent);
|
||||
procedure ChangeNode(ANode: TTreeNode);
|
||||
function FindAndChange(APers: TPersistent; ZOrderDel: TZOrderDelete): Boolean;
|
||||
function GetSelection: TPersistentSelectionList;
|
||||
procedure SetPropertyEditorHook(AValue: TPropertyEditorHook);
|
||||
procedure SetSelection(NewSelection: TPersistentSelectionList);
|
||||
@ -212,15 +209,18 @@ var
|
||||
TVNode: TTreeNode;
|
||||
TheRoot: TPersistent;
|
||||
begin
|
||||
if (APers is TComponent)
|
||||
and (csDestroying in TComponent(APers).ComponentState) then Exit;
|
||||
if (APers is TComponent) then
|
||||
Assert(not (csDestroying in TComponent(APers).ComponentState), 'TComponentWalker: Comp is Destroying.');
|
||||
TheRoot := GetLookupRootForComponent(APers);
|
||||
{$IFDEF VerboseComponentTVWalker}
|
||||
DebugLn(['TComponentWalker.AddOwnedPersistent'+
|
||||
' PropName=',APropName,' Persistent=',DbgSName(APers),
|
||||
' its root=',DbgSName(TheRoot),' FLookupRoot=',DbgSName(FLookupRoot)]);
|
||||
{$ENDIF}
|
||||
if TheRoot <> FLookupRoot then Exit;
|
||||
if TheRoot <> FLookupRoot then begin
|
||||
DebugLn(['TComponentWalker.AddOwnedPersistent: TheRoot "', TheRoot, '" <> FLookupRoot "', FLookupRoot, '"']);
|
||||
Exit;
|
||||
end;
|
||||
TVNode := FCompTV.AddOrGetPersNode(AParentNode, APers, CreateNodeCaption(APers, APropName));
|
||||
if APers is TCollection then
|
||||
AddCollection(TCollection(APers), TVNode);
|
||||
@ -261,8 +261,14 @@ var
|
||||
OldNode: TTreeNode;
|
||||
Root: TComponent;
|
||||
begin
|
||||
if csDestroying in AComponent.ComponentState then exit;
|
||||
if GetLookupRootForComponent(AComponent) <> FLookupRoot then Exit;
|
||||
if csDestroying in AComponent.ComponentState then begin
|
||||
DebugLn(['TComponentWalker.Walk: ', AComponent, ' is Destroying.']);
|
||||
Exit;
|
||||
end;
|
||||
if GetLookupRootForComponent(AComponent) <> FLookupRoot then begin
|
||||
DebugLn(['TComponentWalker.Walk: "', AComponent, '" LookupRoot <> FLookupRoot "', FLookupRoot, '"']);
|
||||
Exit;
|
||||
end;
|
||||
OldNode := FNode;
|
||||
FNode := FCompTV.AddOrGetPersNode(FNode, AComponent, ComponentCaption(AComponent));
|
||||
GetOwnedPersistents(AComponent, FNode);
|
||||
@ -631,37 +637,6 @@ begin
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TComponentTreeView.ChangeNode(ANode: TTreeNode);
|
||||
// A node matching FPersToChange was found. Change its ZOrder or delete it.
|
||||
var
|
||||
Neighbor: TTreeNode;
|
||||
begin
|
||||
case FZOrderDelete 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;
|
||||
FPersToChange := nil; // No need to search again in the next round.
|
||||
end;
|
||||
|
||||
function TComponentTreeView.AddOrGetPersNode(AParentNode: TTreeNode;
|
||||
APers: TPersistent; ACapt: String): TTreeNode;
|
||||
var
|
||||
@ -671,15 +646,6 @@ begin
|
||||
begin
|
||||
if AParentNode = nil then
|
||||
Exit(Items.GetFirstNode); // Return existing root node.
|
||||
// Search for a node to change.
|
||||
if Assigned(FPersToChange) then
|
||||
begin
|
||||
xNode := AParentNode.GetFirstChild;
|
||||
while (xNode<>nil) and (TObject(xNode.Data)<>FPersToChange) do
|
||||
xNode := xNode.GetNextSibling;
|
||||
if Assigned(xNode) then
|
||||
ChangeNode(xNode);
|
||||
end;
|
||||
// Search for an existing valid node.
|
||||
xNode := AParentNode.GetFirstChild;
|
||||
while (xNode<>nil) and (TObject(xNode.Data)<>APers) do
|
||||
@ -741,19 +707,76 @@ begin
|
||||
EndUpdate;
|
||||
end;
|
||||
|
||||
function TComponentTreeView.FindAndChange(APers: TPersistent;
|
||||
ZOrderDel: TZOrderDelete): Boolean;
|
||||
// APers is Component to be moved or deleted based on ZOrderDel value.
|
||||
|
||||
procedure ChangeNode(ANode: TTreeNode);
|
||||
// Change ZOrder of the given node or delete it.
|
||||
var
|
||||
Neighbor: TTreeNode;
|
||||
begin
|
||||
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;
|
||||
|
||||
function IterateTree(ANode: TTreeNode): Boolean;
|
||||
begin
|
||||
if TObject(ANode.Data)=APers then
|
||||
begin
|
||||
ChangeNode(ANode);
|
||||
Exit(True); // Found and changed.
|
||||
end;
|
||||
ANode := ANode.GetFirstChild;
|
||||
while ANode<>nil do
|
||||
begin
|
||||
Result := IterateTree(ANode); // Recursive call.
|
||||
if Result then Exit; // Found in a child item. Don't search more.
|
||||
ANode := ANode.GetNextSibling;
|
||||
end;
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
begin
|
||||
// Search for a node to change.
|
||||
Assert(Assigned(APers), 'TComponentTreeView.FindAndChangeItem: APers=Nil.');
|
||||
Assert(Items.GetFirstNode.GetNextSibling=Nil,
|
||||
'TComponentTreeView.FindAndChange: Top node has siblings.');
|
||||
Result := IterateTree(Items.GetFirstNode);
|
||||
end;
|
||||
|
||||
procedure TComponentTreeView.ChangeCompZOrder(APersistent: TPersistent;
|
||||
AZOrder: TZOrderDelete);
|
||||
begin
|
||||
FPersToChange := APersistent;
|
||||
FZOrderDelete := AZOrder;
|
||||
BuildComponentNodes(False);
|
||||
if not FindAndChange(APersistent, AZOrder) then
|
||||
DebugLn(['TComponentTreeView.ChangeCompZOrder failed.']);
|
||||
end;
|
||||
|
||||
procedure TComponentTreeView.DeleteComponentNode(APersistent: TPersistent);
|
||||
begin
|
||||
FPersToChange := APersistent;
|
||||
FZOrderDelete := zoDelete;
|
||||
BuildComponentNodes(False);
|
||||
if not FindAndChange(APersistent, zoDelete) then
|
||||
DebugLn(['TComponentTreeView.DeleteComponentNode failed.']);
|
||||
end;
|
||||
|
||||
procedure TComponentTreeView.UpdateCompNode(ANode: TTreeNode);
|
||||
|
||||
@ -4623,8 +4623,12 @@ end;
|
||||
|
||||
procedure TObjectInspectorDlg.DeleteCompFromList(APersistent: TPersistent);
|
||||
begin
|
||||
if FShowComponentTree then
|
||||
ComponentTree.DeleteComponentNode(APersistent)
|
||||
if FShowComponentTree then begin
|
||||
if APersistent=nil then
|
||||
ComponentTree.BuildComponentNodes(True)
|
||||
else
|
||||
ComponentTree.DeleteComponentNode(APersistent);
|
||||
end
|
||||
else
|
||||
FillPersistentComboBox;
|
||||
end;
|
||||
@ -4652,7 +4656,6 @@ var
|
||||
OldText: AnsiString;
|
||||
NewList: TStringList;
|
||||
begin
|
||||
DebugLn('TObjectInspectorDlg.FillPersistentComboBox: Updating ComboBox with components');
|
||||
Assert(not FUpdatingAvailComboBox,
|
||||
'TObjectInspectorDlg.FillPersistentComboBox: Updating Avail ComboBox');
|
||||
//if FUpdatingAvailComboBox then exit;
|
||||
|
||||
@ -2989,6 +2989,7 @@ end;
|
||||
procedure TDesigner.DoDeletePersistent(APersistent: TPersistent; FreeIt: boolean);
|
||||
var
|
||||
Hook: TPropertyEditorHook;
|
||||
Special: Boolean;
|
||||
begin
|
||||
if APersistent=nil then exit;
|
||||
Include(FFlags, dfDuringDeletePers);
|
||||
@ -3012,17 +3013,22 @@ begin
|
||||
end;
|
||||
// call component deleting handlers
|
||||
Hook:=GetPropertyEditorHook;
|
||||
if Hook<>nil then
|
||||
if Assigned(Hook) then
|
||||
Hook.PersistentDeleting(APersistent);
|
||||
Special:=(APersistent is TWinControl) and TWinControl(APersistent).IsSpecialSubControl;
|
||||
// delete component
|
||||
if APersistent is TComponent then
|
||||
TheFormEditor.DeleteComponent(TComponent(APersistent),FreeIt)
|
||||
else if FreeIt then
|
||||
APersistent.Free;
|
||||
// call ComponentDeleted handler
|
||||
if Assigned(FOnPersistentDeleted) then
|
||||
FOnPersistentDeleted(Self,APersistent);
|
||||
if Hook<>nil then
|
||||
if Assigned(FOnPersistentDeleted) then begin
|
||||
if Special then // Special treatment is now needed only for TPairSplitterSide.
|
||||
FOnPersistentDeleted(Self,nil) // Will rebuild whole OI Tree.
|
||||
else
|
||||
FOnPersistentDeleted(Self,APersistent);
|
||||
end;
|
||||
if Assigned(Hook) then
|
||||
Hook.PersistentDeleted;
|
||||
finally
|
||||
// unmark component
|
||||
|
||||
@ -1946,7 +1946,9 @@ type
|
||||
wcfUpdateShowing,
|
||||
wcfHandleVisible,
|
||||
wcfAdjustedLogicalClientRectValid,
|
||||
wcfKillIntfSetBounds
|
||||
wcfKillIntfSetBounds,
|
||||
wcfDesignerDeleting, // Only used for PairSplitter which should be redesigned
|
||||
wcfSpecialSubControl // Only set by PairSplitterSide
|
||||
);
|
||||
TWinControlFlags = set of TWinControlFlag;
|
||||
|
||||
@ -2032,7 +2034,6 @@ type
|
||||
FShowing: Boolean;
|
||||
FDockSite: Boolean;
|
||||
FUseDockManager: Boolean;
|
||||
FDesignerDeleting: Boolean;
|
||||
procedure AlignControl(AControl: TControl);
|
||||
function DoubleBufferedIsStored: Boolean;
|
||||
function GetBrush: TBrush;
|
||||
@ -2042,9 +2043,11 @@ type
|
||||
function GetDockClients(Index: Integer): TControl;
|
||||
function GetHandle: HWND;
|
||||
function GetIsResizing: boolean;
|
||||
function GetIsSpecialSubControl: Boolean;
|
||||
function GetTabOrder: TTabOrder;
|
||||
function GetVisibleDockClientCount: Integer;
|
||||
procedure SetChildSizing(const AValue: TControlChildSizing);
|
||||
procedure SetDesignerDeleting(AValue: Boolean);
|
||||
procedure SetDockSite(const NewDockSite: Boolean);
|
||||
procedure SetDoubleBuffered(Value: Boolean);
|
||||
procedure SetHandle(NewHandle: HWND);
|
||||
@ -2274,7 +2277,8 @@ type
|
||||
property Showing: Boolean read FShowing; // handle visible
|
||||
property UseDockManager: Boolean read FUseDockManager
|
||||
write SetUseDockManager default False;
|
||||
property DesignerDeleting: Boolean read FDesignerDeleting write FDesignerDeleting;
|
||||
property DesignerDeleting: Boolean write SetDesignerDeleting;
|
||||
property IsSpecialSubControl: Boolean read GetIsSpecialSubControl;
|
||||
property VisibleDockClientCount: Integer read GetVisibleDockClientCount;
|
||||
public
|
||||
// size, position, bounds
|
||||
|
||||
@ -6470,17 +6470,11 @@ begin
|
||||
Result := Control = Self;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
TWinControl GetBorderStyle
|
||||
------------------------------------------------------------------------------}
|
||||
function TWinControl.GetBorderStyle: TBorderStyle;
|
||||
begin
|
||||
Result := TBorderStyle(FBorderStyle);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
TWinControl GetBrush
|
||||
------------------------------------------------------------------------------}
|
||||
function TWinControl.GetBrush: TBrush;
|
||||
begin
|
||||
if not BrushCreated then
|
||||
@ -6488,17 +6482,11 @@ begin
|
||||
Result := FBrush;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
TWinControl GetControl
|
||||
------------------------------------------------------------------------------}
|
||||
function TWinControl.GetControl(const Index: Integer): TControl;
|
||||
begin
|
||||
Result := TControl(FControls[Index]);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
TWinControl GetControlCount
|
||||
------------------------------------------------------------------------------}
|
||||
function TWinControl.GetControlCount: Integer;
|
||||
begin
|
||||
if FControls <> nil then
|
||||
@ -6523,9 +6511,6 @@ begin
|
||||
Result := nil;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
TWinControl GetHandle
|
||||
------------------------------------------------------------------------------}
|
||||
function TWinControl.GetHandle: HWND;
|
||||
begin
|
||||
//if not HandleAllocated then DebugLn('TWinControl.GetHandle Creating handle on the fly: ',DbgSName(Self));
|
||||
@ -8004,9 +7989,11 @@ begin
|
||||
Result:=BoundsLockCount>0;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
function TWinControl.GetTabOrder: TTabOrder;
|
||||
------------------------------------------------------------------------------}
|
||||
function TWinControl.GetIsSpecialSubControl: Boolean;
|
||||
begin
|
||||
Result := wcfSpecialSubControl in FWinControlFlags;
|
||||
end;
|
||||
|
||||
function TWinControl.GetTabOrder: TTabOrder;
|
||||
begin
|
||||
if FParent <> nil then
|
||||
@ -8015,9 +8002,6 @@ begin
|
||||
Result := FTabOrder;
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
function TWinControl.GetVisibleDockClientCount: Integer;
|
||||
------------------------------------------------------------------------------}
|
||||
function TWinControl.GetVisibleDockClientCount: Integer;
|
||||
var
|
||||
i: integer;
|
||||
@ -8028,15 +8012,20 @@ begin
|
||||
if TControl(FDockClients[I]).Visible then inc(Result);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
procedure TWinControl.SetChildSizing(const AValue: TControlChildSizing);
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TWinControl.SetChildSizing(const AValue: TControlChildSizing);
|
||||
begin
|
||||
if (FChildSizing=AValue) then exit;
|
||||
FChildSizing.Assign(AValue);
|
||||
end;
|
||||
|
||||
procedure TWinControl.SetDesignerDeleting(AValue: Boolean);
|
||||
begin
|
||||
if AValue then
|
||||
Include(FWinControlFlags, wcfDesignerDeleting)
|
||||
else
|
||||
Exclude(FWinControlFlags, wcfDesignerDeleting);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
procedure TWinControl.SetDockSite(const NewDockSite: Boolean);
|
||||
|
||||
|
||||
@ -191,7 +191,8 @@ begin
|
||||
ASplitter := Splitter;
|
||||
if ASplitter <> nil then begin
|
||||
ASplitter.RemoveSide(Self);
|
||||
DeletingSplitter := (csDestroying in ASplitter.ComponentState) or DesignerDeleting;
|
||||
DeletingSplitter := (csDestroying in ASplitter.ComponentState)
|
||||
or (wcfDesignerDeleting in FWinControlFlags);
|
||||
end
|
||||
else
|
||||
DeletingSplitter := False;
|
||||
@ -238,6 +239,8 @@ begin
|
||||
inherited Create(TheOwner);
|
||||
FCompStyle := csPairSplitterSide;
|
||||
ControlStyle := ControlStyle + [csAcceptsControls];
|
||||
// A flag custom made for TPairSplitterSide.
|
||||
Include(FWinControlFlags, wcfSpecialSubControl);
|
||||
end;
|
||||
|
||||
destructor TPairSplitterSide.Destroy;
|
||||
@ -334,7 +337,7 @@ begin
|
||||
end;
|
||||
// if the user deletes a side at designtime, autocreate a new one
|
||||
if (ComponentState * [csDesigning,csDestroying] = [csDesigning])
|
||||
and not DesignerDeleting then
|
||||
and not (wcfDesignerDeleting in FWinControlFlags) then
|
||||
CreateSides;
|
||||
end;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user