fix(dock): improve window lifecycle, size sync performance, and code style
This commit is contained in:
@@ -1,18 +1,5 @@
|
|||||||
namespace Ghost.Editor.Core.Controls.Internal.Docking;
|
namespace Ghost.Editor.Core.Controls.Internal.Docking;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the possible dock positions for a drop operation.
|
|
||||||
/// </summary>
|
|
||||||
internal enum DockPosition
|
|
||||||
{
|
|
||||||
Center,
|
|
||||||
Top,
|
|
||||||
Bottom,
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper class for docking-related calculations.
|
/// Helper class for docking-related calculations.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace Ghost.Editor.Core.Controls.Internal.Docking;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the possible dock positions for a drop operation.
|
||||||
|
/// </summary>
|
||||||
|
internal enum DockPosition
|
||||||
|
{
|
||||||
|
Center,
|
||||||
|
Top,
|
||||||
|
Bottom,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
None
|
||||||
|
}
|
||||||
@@ -122,9 +122,13 @@ public sealed partial class DockLayout
|
|||||||
var newWidth = grid.ColumnDefinitions[i * 2].Width;
|
var newWidth = grid.ColumnDefinitions[i * 2].Width;
|
||||||
if (!groupNode.Sizes[i].Equals(newWidth))
|
if (!groupNode.Sizes[i].Equals(newWidth))
|
||||||
{
|
{
|
||||||
_isSyncingSizes = true;
|
// Only sync if it's a star or pixel value (not Auto)
|
||||||
groupNode.Sizes[i] = newWidth;
|
if (newWidth.IsStar || newWidth.IsAbsolute)
|
||||||
changed = true;
|
{
|
||||||
|
_isSyncingSizes = true;
|
||||||
|
groupNode.Sizes[i] = newWidth;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,9 +142,12 @@ public sealed partial class DockLayout
|
|||||||
var newHeight = grid.RowDefinitions[i * 2].Height;
|
var newHeight = grid.RowDefinitions[i * 2].Height;
|
||||||
if (!groupNode.Sizes[i].Equals(newHeight))
|
if (!groupNode.Sizes[i].Equals(newHeight))
|
||||||
{
|
{
|
||||||
_isSyncingSizes = true;
|
if (newHeight.IsStar || newHeight.IsAbsolute)
|
||||||
groupNode.Sizes[i] = newHeight;
|
{
|
||||||
changed = true;
|
_isSyncingSizes = true;
|
||||||
|
groupNode.Sizes[i] = newHeight;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ namespace Ghost.Editor.View.Windows;
|
|||||||
|
|
||||||
internal sealed partial class DockWindow : WindowEx
|
internal sealed partial class DockWindow : WindowEx
|
||||||
{
|
{
|
||||||
|
private long _rootPropertyToken;
|
||||||
|
private DockGroupNode? _currentRoot;
|
||||||
|
|
||||||
public DockWindow(object initialTabContent)
|
public DockWindow(object initialTabContent)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -21,47 +24,54 @@ internal sealed partial class DockWindow : WindowEx
|
|||||||
PART_DockLayout.TabTornOff += OnTabTornOff;
|
PART_DockLayout.TabTornOff += OnTabTornOff;
|
||||||
|
|
||||||
RegisterCloseHandler();
|
RegisterCloseHandler();
|
||||||
|
|
||||||
|
this.Closed += (s, e) =>
|
||||||
|
{
|
||||||
|
if (_rootPropertyToken != 0)
|
||||||
|
{
|
||||||
|
PART_DockLayout.UnregisterPropertyChangedCallback(DockLayout.RootProperty, _rootPropertyToken);
|
||||||
|
_rootPropertyToken = 0;
|
||||||
|
}
|
||||||
|
UnsubscribeFromRoot(_currentRoot);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterCloseHandler()
|
private void RegisterCloseHandler()
|
||||||
{
|
{
|
||||||
// Subscribe to Root changes to ensure we always track the current tree
|
_rootPropertyToken = PART_DockLayout.RegisterPropertyChangedCallback(DockLayout.RootProperty, (s, dp) =>
|
||||||
var rootProperty = DockLayout.RootProperty;
|
|
||||||
|
|
||||||
void OnRootChildrenChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
|
||||||
{
|
{
|
||||||
if (PART_DockLayout.Root?.Children.Count == 0)
|
UnsubscribeFromRoot(_currentRoot);
|
||||||
{
|
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
|
||||||
SubscribeToRoot(PART_DockLayout.Root);
|
SubscribeToRoot(PART_DockLayout.Root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnRootChildrenChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (PART_DockLayout.Root?.Children.Count == 0)
|
||||||
|
{
|
||||||
|
this.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SubscribeToRoot(DockGroupNode? root)
|
||||||
|
{
|
||||||
|
_currentRoot = root;
|
||||||
|
if (_currentRoot != null)
|
||||||
|
{
|
||||||
|
((System.Collections.Specialized.INotifyCollectionChanged)_currentRoot.Children).CollectionChanged += OnRootChildrenChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UnsubscribeFromRoot(DockGroupNode? root)
|
||||||
|
{
|
||||||
|
if (root != null)
|
||||||
|
{
|
||||||
|
((System.Collections.Specialized.INotifyCollectionChanged)root.Children).CollectionChanged -= OnRootChildrenChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnTabTornOff(object? sender, TabTornOffEventArgs e)
|
private void OnTabTornOff(object? sender, TabTornOffEventArgs e)
|
||||||
{
|
{
|
||||||
App.CreateAndShowDockWindow(e.TabContent);
|
App.CreateAndShowDockWindow(e.TabContent);
|
||||||
|
|||||||
Reference in New Issue
Block a user