fix(dock): ensure callback side-effect cleanup and improve tear-off diagnostics
This commit is contained in:
@@ -59,9 +59,23 @@ public partial class App : Application
|
|||||||
internal static void CreateAndShowDockWindow(object tabContent)
|
internal static void CreateAndShowDockWindow(object tabContent)
|
||||||
{
|
{
|
||||||
var newWindow = new Ghost.Editor.View.Windows.DockWindow(tabContent);
|
var newWindow = new Ghost.Editor.View.Windows.DockWindow(tabContent);
|
||||||
|
try
|
||||||
|
{
|
||||||
AddSecondaryWindow(newWindow);
|
AddSecondaryWindow(newWindow);
|
||||||
newWindow.Activate();
|
newWindow.Activate();
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Cleanup partially created window
|
||||||
|
if (Current is App app)
|
||||||
|
{
|
||||||
|
app._secondaryWindows.Remove(newWindow);
|
||||||
|
}
|
||||||
|
newWindow.Close();
|
||||||
|
Logger.LogError(ex);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal IHost Host
|
internal IHost Host
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -433,14 +433,15 @@ public sealed partial class DockLayout : Control
|
|||||||
{
|
{
|
||||||
// Validate that the item actually belongs to this source node before attempting tear-off
|
// Validate that the item actually belongs to this source node before attempting tear-off
|
||||||
if (sourceNode.Items.Contains(args.Item))
|
if (sourceNode.Items.Contains(args.Item))
|
||||||
{
|
|
||||||
var result = TabTearOffService.TryTearOffTab(sourceNode.Items, args.Item, (tab) =>
|
|
||||||
{
|
{
|
||||||
if (TabTornOff == null)
|
if (TabTornOff == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException("No tear-off handler attached.");
|
Logger.LogWarning("Tab dropped outside but no TabTornOff subscribers found.");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var result = TabTearOffService.TryTearOffTab(sourceNode.Items, args.Item, (tab) =>
|
||||||
|
{
|
||||||
// Raise event to let the host handle window creation
|
// Raise event to let the host handle window creation
|
||||||
TabTornOff.Invoke(this, new TabTornOffEventArgs(tab, sourceNode));
|
TabTornOff.Invoke(this, new TabTornOffEventArgs(tab, sourceNode));
|
||||||
}, sourceNode);
|
}, sourceNode);
|
||||||
|
|||||||
@@ -42,7 +42,9 @@ internal sealed partial class EngineEditorWindow : WindowEx
|
|||||||
private void OnTabDroppedOutside(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDroppedOutsideEventArgs args)
|
private void OnTabDroppedOutside(Microsoft.UI.Xaml.Controls.TabView sender, Microsoft.UI.Xaml.Controls.TabViewTabDroppedOutsideEventArgs args)
|
||||||
{
|
{
|
||||||
// For static tabs in EngineEditorWindow, we remove the item from TabItems
|
// For static tabs in EngineEditorWindow, we remove the item from TabItems
|
||||||
if (sender.TabItems is System.Collections.IList list && list.Contains(args.Item))
|
if (sender.TabItems is System.Collections.IList list)
|
||||||
|
{
|
||||||
|
if (list.Contains(args.Item))
|
||||||
{
|
{
|
||||||
var result = TabTearOffService.TryTearOffTab(list, args.Item, (tab) =>
|
var result = TabTearOffService.TryTearOffTab(list, args.Item, (tab) =>
|
||||||
{
|
{
|
||||||
@@ -54,6 +56,12 @@ internal sealed partial class EngineEditorWindow : WindowEx
|
|||||||
Logger.LogWarning($"Tab tear-off failed: {result.Message}");
|
Logger.LogWarning($"Tab tear-off failed: {result.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string itemInfo = args.Item is FrameworkElement fe ? fe.GetType().Name : args.Item?.ToString() ?? "unknown";
|
||||||
|
Logger.LogWarning($"OnTabDroppedOutside: Item '{itemInfo}' not found in source TabView (Items count: {list.Count}).");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MainGrid_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
private void MainGrid_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||||
|
|||||||
Reference in New Issue
Block a user