fix(dock): improve window lifecycle, size sync performance, and code style

This commit is contained in:
2026-03-28 19:00:09 +09:00
parent 71abd60a75
commit 975c359bf4
4 changed files with 67 additions and 49 deletions

View File

@@ -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>

View File

@@ -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
}

View File

@@ -121,6 +121,9 @@ 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))
{
// Only sync if it's a star or pixel value (not Auto)
if (newWidth.IsStar || newWidth.IsAbsolute)
{ {
_isSyncingSizes = true; _isSyncingSizes = true;
groupNode.Sizes[i] = newWidth; groupNode.Sizes[i] = newWidth;
@@ -129,6 +132,7 @@ public sealed partial class DockLayout
} }
} }
} }
}
else else
{ {
for (int i = 0; i < groupNode.Children.Count; i++) for (int i = 0; i < groupNode.Children.Count; i++)
@@ -137,6 +141,8 @@ 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))
{
if (newHeight.IsStar || newHeight.IsAbsolute)
{ {
_isSyncingSizes = true; _isSyncingSizes = true;
groupNode.Sizes[i] = newHeight; groupNode.Sizes[i] = newHeight;
@@ -145,6 +151,7 @@ public sealed partial class DockLayout
} }
} }
} }
}
if (changed) if (changed)
{ {

View File

@@ -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,14 +24,30 @@ 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; {
UnsubscribeFromRoot(_currentRoot);
SubscribeToRoot(PART_DockLayout.Root);
});
void OnRootChildrenChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) SubscribeToRoot(PART_DockLayout.Root);
}
private void OnRootChildrenChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{ {
if (PART_DockLayout.Root?.Children.Count == 0) if (PART_DockLayout.Root?.Children.Count == 0)
{ {
@@ -36,15 +55,16 @@ internal sealed partial class DockWindow : WindowEx
} }
} }
void SubscribeToRoot(DockGroupNode? root) private void SubscribeToRoot(DockGroupNode? root)
{ {
if (root != null) _currentRoot = root;
if (_currentRoot != null)
{ {
((System.Collections.Specialized.INotifyCollectionChanged)root.Children).CollectionChanged += OnRootChildrenChanged; ((System.Collections.Specialized.INotifyCollectionChanged)_currentRoot.Children).CollectionChanged += OnRootChildrenChanged;
} }
} }
void UnsubscribeFromRoot(DockGroupNode? root) private void UnsubscribeFromRoot(DockGroupNode? root)
{ {
if (root != null) if (root != null)
{ {
@@ -52,16 +72,6 @@ internal sealed partial class DockWindow : WindowEx
} }
} }
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)
{ {
App.CreateAndShowDockWindow(e.TabContent); App.CreateAndShowDockWindow(e.TabContent);