diff --git a/docs/superpowers/specs/2026-03-28-dock-layout-design.md b/docs/superpowers/specs/2026-03-28-dock-layout-design.md new file mode 100644 index 0000000..5846f47 --- /dev/null +++ b/docs/superpowers/specs/2026-03-28-dock-layout-design.md @@ -0,0 +1,75 @@ +# DockLayout System Design + +## Purpose +To create a fully-featured docking layout system for the Ghost Engine Editor using WinUI 3, supporting tab tearing, window popping, and dynamic splitting of regions in a style similar to Unity or Blender. + +## Architecture + +The DockLayout will be entirely driven by a C# data model that represents a tree of nodes. The UI (`DockLayout` control) will observe this tree and recursively generate the corresponding XAML `Grid` and `TabView` elements. + +### Core Data Model (The Node Tree) + +```csharp +public abstract class DockNode : INotifyPropertyChanged { } + +// Represents a split region (Grid) +public class DockGroupNode : DockNode +{ + public Orientation Orientation { get; set; } // Horizontal or Vertical + public ObservableCollection Children { get; } + public ObservableCollection Sizes { get; } // Replaces Ratios for better WinUI 3 Grid binding +} + +// Represents a leaf node containing a TabView +public class DockPanelNode : DockNode +{ + // The items shown in the TabView + public ObservableCollection Items { get; } + public int SelectedIndex { get; set; } +} +``` + +### Visual Components + +1. **`DockLayout` (Control)** + * The root control. + * Takes a `DockNode` (usually a `DockGroupNode`) as its `Root`. + * Listens to Drag/Drop events to render the transparent drop target overlay over the layout. + +2. **Node Renderers** + * A recursive template selector or code-behind builder that converts `DockGroupNode` into a `Grid` with `GridSplitter`s. + * Converts `DockPanelNode` into a `NavigationTabView` (or standard `TabView` with customized drag behaviors). + +3. **`DockDropTarget` (Visual Overlay)** + * A simple XAML structure (e.g., a colored `Border` with opacity) that highlights a portion of a `DockPanelNode` based on mouse position during a drag operation (Left/Right/Top/Bottom 25% for splitting, Center 50% for merging). + +## Interactions & Data Flow + +### 1. Internal Dragging (Within the same window) +* User starts dragging a tab. +* The `DockLayout` tracks the mouse pointer `DragOver` events. +* It determines which `DockPanelNode` the mouse is currently hovering over. +* It calculates relative coordinates to show the Unity-style drop highlight. +* On **Drop**: + * If dropped in the **center**: The tab object is moved from its source `DockPanelNode.Items` to the target `DockPanelNode.Items`. + * If dropped on an **edge** (e.g., Right): The target `DockPanelNode` is removed from its parent `DockGroupNode`. A new `DockGroupNode` (Horizontal) is created to replace it. The target node and a *new* `DockPanelNode` (containing the dragged tab) are added as children to this new group. + +### 2. Window Tear-Off (Full Docking) +* User drags a tab completely outside the main window. +* `TabView.TabDroppedOutside` is triggered. +* The system creates a new WinUI 3 `Window`. +* A new `DockLayout` instance is placed in this window. +* The dragged tab object is removed from its original tree and added to a new `DockPanelNode` inside the new window's tree. +* *Note: Because WinUI 3 supports multiple windows on the same UI thread, we don't have to worry about cross-thread marshaling of UI elements, making this much simpler than UWP.* + +### 3. Empty Node Cleanup +* When a `DockPanelNode`'s `Items` collection reaches 0 (the last tab is dragged away), it is removed from the tree. +* If its parent `DockGroupNode` now only has 1 child remaining, that `DockGroupNode` is removed and replaced by its single child, collapsing the tree. + +## Implementation Phases +1. Define the Data Model (`DockNode` structure). +2. Implement the recursive UI generation (binding the tree to nested Grids and TabViews). +3. Implement basic tab moving (Merge) between existing `DockPanelNode`s. +4. Implement edge dropping (Split) and the drop target highlight overlay. +5. Implement empty node cleanup logic. +6. Implement multi-window tear-off via `TabDroppedOutside`.