From e9f822409dd00ee7e3b2d9ae923ec89d4bfc8ebb Mon Sep 17 00:00:00 2001 From: Misaki Date: Sat, 28 Mar 2026 23:07:28 +0900 Subject: [PATCH] fix(docking): prevent layout tree loss and enforce cross-layout ownership --- .../View/Controls/Docking/DockContainer.cs | 6 ++++++ .../View/Controls/Docking/DockingLayout.cs | 15 +++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Editor/Ghost.Editor/View/Controls/Docking/DockContainer.cs b/src/Editor/Ghost.Editor/View/Controls/Docking/DockContainer.cs index 81b062b..cbaffca 100644 --- a/src/Editor/Ghost.Editor/View/Controls/Docking/DockContainer.cs +++ b/src/Editor/Ghost.Editor/View/Controls/Docking/DockContainer.cs @@ -47,6 +47,9 @@ public abstract class DockContainer : DockModule { ValidateChild(module); + if (module.Owner == null && module.Root != null && module.Root != this.Root) + throw new InvalidOperationException("Cannot insert a module that is the root of another layout. Detach it first."); + if (index < 0 || index > _children.Count) throw new ArgumentOutOfRangeException(nameof(index)); @@ -94,6 +97,9 @@ public abstract class DockContainer : DockModule ArgumentNullException.ThrowIfNull(oldChild); ValidateChild(newChild); + if (newChild.Owner == null && newChild.Root != null && newChild.Root != this.Root) + throw new InvalidOperationException("Cannot insert a module that is the root of another layout. Detach it first."); + if (oldChild == newChild) return; int index = _children.IndexOf(oldChild); diff --git a/src/Editor/Ghost.Editor/View/Controls/Docking/DockingLayout.cs b/src/Editor/Ghost.Editor/View/Controls/Docking/DockingLayout.cs index f049edf..980ef40 100644 --- a/src/Editor/Ghost.Editor/View/Controls/Docking/DockingLayout.cs +++ b/src/Editor/Ghost.Editor/View/Controls/Docking/DockingLayout.cs @@ -104,12 +104,23 @@ public class DockingLayout : Control { // Root is not a container, or contains no groups. Wrap it. var newGroup = new DockGroup(); + newGroup.AddChild(document); + if (RootModule is DockDocument existingDoc) { - RootModule = null; // Detach first + RootModule = null; newGroup.AddChild(existingDoc); + RootModule = newGroup; + } + else + { + var oldRoot = RootModule; + RootModule = null; + var panel = new DockPanel(); + panel.AddChild(oldRoot); + panel.AddChild(newGroup); + RootModule = panel; } - RootModule = newGroup; targetGroup = newGroup; } }