fix(dock): ensure persistent sizing capture and improve window close logic
This commit is contained in:
@@ -101,21 +101,31 @@ public sealed partial class DockLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Capture size changes to persist back to model
|
// Capture size changes to persist back to model
|
||||||
grid.SizeChanged += (s, e) => SyncSizesToModel(groupNode, grid);
|
grid.LayoutUpdated += (s, e) => SyncSizesToModel(groupNode, grid);
|
||||||
|
|
||||||
return grid;
|
return grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SyncSizesToModel(DockGroupNode groupNode, Grid grid)
|
private void SyncSizesToModel(DockGroupNode groupNode, Grid grid)
|
||||||
{
|
{
|
||||||
|
if (_isSyncingSizes) return;
|
||||||
|
|
||||||
bool isHorizontal = groupNode.Orientation == Orientation.Horizontal;
|
bool isHorizontal = groupNode.Orientation == Orientation.Horizontal;
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
if (isHorizontal)
|
if (isHorizontal)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < groupNode.Children.Count; i++)
|
for (int i = 0; i < groupNode.Children.Count; i++)
|
||||||
{
|
{
|
||||||
if (i < groupNode.Sizes.Count && i * 2 < grid.ColumnDefinitions.Count)
|
if (i < groupNode.Sizes.Count && i * 2 < grid.ColumnDefinitions.Count)
|
||||||
{
|
{
|
||||||
groupNode.Sizes[i] = grid.ColumnDefinitions[i * 2].Width;
|
var newWidth = grid.ColumnDefinitions[i * 2].Width;
|
||||||
|
if (!groupNode.Sizes[i].Equals(newWidth))
|
||||||
|
{
|
||||||
|
_isSyncingSizes = true;
|
||||||
|
groupNode.Sizes[i] = newWidth;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,10 +135,21 @@ public sealed partial class DockLayout
|
|||||||
{
|
{
|
||||||
if (i < groupNode.Sizes.Count && i * 2 < grid.RowDefinitions.Count)
|
if (i < groupNode.Sizes.Count && i * 2 < grid.RowDefinitions.Count)
|
||||||
{
|
{
|
||||||
groupNode.Sizes[i] = grid.RowDefinitions[i * 2].Height;
|
var newHeight = grid.RowDefinitions[i * 2].Height;
|
||||||
|
if (!groupNode.Sizes[i].Equals(newHeight))
|
||||||
|
{
|
||||||
|
_isSyncingSizes = true;
|
||||||
|
groupNode.Sizes[i] = newHeight;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
{
|
||||||
|
_isSyncingSizes = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private UIElement CreatePanelUI(DockPanelNode panelNode)
|
private UIElement CreatePanelUI(DockPanelNode panelNode)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public sealed partial class DockLayout
|
|||||||
if (node is DockGroupNode groupNode)
|
if (node is DockGroupNode groupNode)
|
||||||
{
|
{
|
||||||
((INotifyCollectionChanged)groupNode.Children).CollectionChanged += OnChildrenCollectionChanged;
|
((INotifyCollectionChanged)groupNode.Children).CollectionChanged += OnChildrenCollectionChanged;
|
||||||
|
groupNode.Sizes.CollectionChanged += OnSizesCollectionChanged;
|
||||||
foreach (var child in groupNode.Children)
|
foreach (var child in groupNode.Children)
|
||||||
{
|
{
|
||||||
SubscribeToNode(child);
|
SubscribeToNode(child);
|
||||||
@@ -38,6 +39,7 @@ public sealed partial class DockLayout
|
|||||||
if (node is DockGroupNode groupNode)
|
if (node is DockGroupNode groupNode)
|
||||||
{
|
{
|
||||||
((INotifyCollectionChanged)groupNode.Children).CollectionChanged -= OnChildrenCollectionChanged;
|
((INotifyCollectionChanged)groupNode.Children).CollectionChanged -= OnChildrenCollectionChanged;
|
||||||
|
groupNode.Sizes.CollectionChanged -= OnSizesCollectionChanged;
|
||||||
foreach (var child in groupNode.Children)
|
foreach (var child in groupNode.Children)
|
||||||
{
|
{
|
||||||
UnsubscribeFromNode(child);
|
UnsubscribeFromNode(child);
|
||||||
@@ -55,11 +57,20 @@ public sealed partial class DockLayout
|
|||||||
if (node is DockGroupNode groupNode)
|
if (node is DockGroupNode groupNode)
|
||||||
{
|
{
|
||||||
((INotifyCollectionChanged)groupNode.Children).CollectionChanged -= OnChildrenCollectionChanged;
|
((INotifyCollectionChanged)groupNode.Children).CollectionChanged -= OnChildrenCollectionChanged;
|
||||||
|
groupNode.Sizes.CollectionChanged -= OnSizesCollectionChanged;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_subscribedNodes.Clear();
|
_subscribedNodes.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnSizesCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_isSyncingSizes)
|
||||||
|
{
|
||||||
|
RenderTree();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnNodePropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
private void OnNodePropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
// Filter to structural property names
|
// Filter to structural property names
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public sealed partial class DockLayout : Control
|
|||||||
private const double DROP_EDGE_THRESHOLD = 0.25;
|
private const double DROP_EDGE_THRESHOLD = 0.25;
|
||||||
|
|
||||||
private FrameworkElement? _dropTargetOverlay;
|
private FrameworkElement? _dropTargetOverlay;
|
||||||
|
private bool _isSyncingSizes;
|
||||||
|
|
||||||
public DockLayout()
|
public DockLayout()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -20,13 +20,46 @@ internal sealed partial class DockWindow : WindowEx
|
|||||||
PART_DockLayout.Root = rootGroup;
|
PART_DockLayout.Root = rootGroup;
|
||||||
PART_DockLayout.TabTornOff += OnTabTornOff;
|
PART_DockLayout.TabTornOff += OnTabTornOff;
|
||||||
|
|
||||||
((System.Collections.Specialized.INotifyCollectionChanged)rootGroup.Children).CollectionChanged += (s, e) =>
|
RegisterCloseHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterCloseHandler()
|
||||||
|
{
|
||||||
|
// Subscribe to Root changes to ensure we always track the current tree
|
||||||
|
var rootProperty = DockLayout.RootProperty;
|
||||||
|
|
||||||
|
void OnRootChildrenChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (rootGroup.Children.Count == 0)
|
if (PART_DockLayout.Root?.Children.Count == 0)
|
||||||
{
|
{
|
||||||
this.Close();
|
this.Close();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
void SubscribeToRoot(DockGroupNode? root)
|
||||||
|
{
|
||||||
|
if (root != null)
|
||||||
|
{
|
||||||
|
((System.Collections.Specialized.INotifyCollectionChanged)root.Children).CollectionChanged += OnRootChildrenChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnsubscribeFromRoot(DockGroupNode? root)
|
||||||
|
{
|
||||||
|
if (root != null)
|
||||||
|
{
|
||||||
|
((System.Collections.Specialized.INotifyCollectionChanged)root.Children).CollectionChanged -= OnRootChildrenChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PART_DockLayout.RegisterPropertyChangedCallback(DockLayout.RootProperty, (s, dp) =>
|
||||||
|
{
|
||||||
|
// This is a bit tricky since we don't have the old value easily here in RegisterPropertyChangedCallback
|
||||||
|
// But for DockWindow, the root is usually set once.
|
||||||
|
SubscribeToRoot(PART_DockLayout.Root);
|
||||||
|
});
|
||||||
|
|
||||||
|
SubscribeToRoot(PART_DockLayout.Root);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTabTornOff(object? sender, TabTornOffEventArgs e)
|
private void OnTabTornOff(object? sender, TabTornOffEventArgs e)
|
||||||
|
|||||||
Reference in New Issue
Block a user