fix(dock): enforce tree invariants, sync selection, and fix AOT warnings
This commit is contained in:
@@ -7,12 +7,45 @@ namespace Ghost.Editor.Core.Controls.Internal.Docking;
|
||||
public partial class DockGroupNode : DockNode
|
||||
{
|
||||
[ObservableProperty]
|
||||
private Orientation _orientation = Orientation.Horizontal;
|
||||
public partial Orientation Orientation { get; set; }
|
||||
|
||||
public DockGroupNode()
|
||||
{
|
||||
Orientation = Orientation.Horizontal;
|
||||
}
|
||||
|
||||
public ObservableCollection<DockNode> Children { get; } = new();
|
||||
|
||||
public void AddChild(DockNode node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
|
||||
if (node == this)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot add a node to itself.");
|
||||
}
|
||||
|
||||
if (Children.Contains(node))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for cycles
|
||||
var current = this.Parent;
|
||||
while (current != null)
|
||||
{
|
||||
if (current == node)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot add an ancestor as a child (cycle detected).");
|
||||
}
|
||||
current = current.Parent;
|
||||
}
|
||||
|
||||
if (node.Parent != null && node.Parent != this)
|
||||
{
|
||||
node.Parent.RemoveChild(node);
|
||||
}
|
||||
|
||||
node.Parent = this;
|
||||
Children.Add(node);
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ namespace Ghost.Editor.Core.Controls.Internal.Docking;
|
||||
public abstract partial class DockNode : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private DockGroupNode? _parent;
|
||||
public partial DockGroupNode? Parent { get; set; }
|
||||
}
|
||||
|
||||
@@ -8,8 +8,64 @@ public partial class DockPanelNode : DockNode
|
||||
public ObservableCollection<object> Items { get; } = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private int _selectedIndex = -1;
|
||||
public partial int SelectedIndex { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
private object? _selectedItem;
|
||||
public partial object? SelectedItem { get; set; }
|
||||
|
||||
public DockPanelNode()
|
||||
{
|
||||
SelectedIndex = -1;
|
||||
Items.CollectionChanged += OnItemsCollectionChanged;
|
||||
}
|
||||
|
||||
private void OnItemsCollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (Items.Count == 0)
|
||||
{
|
||||
SelectedIndex = -1;
|
||||
SelectedItem = null;
|
||||
}
|
||||
else if (SelectedIndex >= Items.Count)
|
||||
{
|
||||
SelectedIndex = Items.Count - 1;
|
||||
}
|
||||
else if (SelectedIndex == -1 && Items.Count > 0)
|
||||
{
|
||||
SelectedIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnSelectedIndexChanged(int value)
|
||||
{
|
||||
if (value >= 0 && value < Items.Count)
|
||||
{
|
||||
SelectedItem = Items[value];
|
||||
}
|
||||
else if (value == -1)
|
||||
{
|
||||
SelectedItem = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clamp or reset if out of bounds
|
||||
SelectedIndex = Items.Count > 0 ? 0 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnSelectedItemChanged(object? value)
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
SelectedIndex = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int index = Items.IndexOf(value);
|
||||
if (index != -1)
|
||||
{
|
||||
SelectedIndex = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user