Files
GhostEngine/docs/superpowers/specs/2026-03-28-dock-layout-design.md

3.9 KiB

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)

public abstract class DockNode : INotifyPropertyChanged { }

// Represents a split region (Grid)
public class DockGroupNode : DockNode 
{
    public Orientation Orientation { get; set; } // Horizontal or Vertical
    public ObservableCollection<DockNode> Children { get; }
    public ObservableCollection<GridLength> 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<object> 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 GridSplitters.
    • 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 DockPanelNodes.
  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.