diff --git a/samples/DockControlPanelsSample/MainView.axaml b/samples/DockControlPanelsSample/MainView.axaml
index 06b74de2d..b256077ad 100644
--- a/samples/DockControlPanelsSample/MainView.axaml
+++ b/samples/DockControlPanelsSample/MainView.axaml
@@ -23,7 +23,7 @@
-
+
@@ -68,7 +68,7 @@
-
+
@@ -107,7 +107,7 @@
-
+
@@ -159,7 +159,7 @@
-
+
@@ -210,7 +210,7 @@
-
+
@@ -261,7 +261,7 @@
-
+
diff --git a/src/Dock.Model/Controls/IGridDockSplitter.cs b/src/Dock.Model/Controls/IGridDockSplitter.cs
index 06d8a791e..b55b249ab 100644
--- a/src/Dock.Model/Controls/IGridDockSplitter.cs
+++ b/src/Dock.Model/Controls/IGridDockSplitter.cs
@@ -8,7 +8,7 @@ namespace Dock.Model.Controls;
/// Grid splitter dock contract.
///
[RequiresDataTemplate]
-public interface IGridDockSplitter : IDockable
+public interface IGridDockSplitter : ISplitter
{
///
/// Gets or sets resize direction.
diff --git a/src/Dock.Model/Controls/IProportionalDockSplitter.cs b/src/Dock.Model/Controls/IProportionalDockSplitter.cs
index 2c65ce7fa..6389d1b28 100644
--- a/src/Dock.Model/Controls/IProportionalDockSplitter.cs
+++ b/src/Dock.Model/Controls/IProportionalDockSplitter.cs
@@ -8,7 +8,7 @@ namespace Dock.Model.Controls;
/// Proportional dock splitter contract.
///
[RequiresDataTemplate]
-public interface IProportionalDockSplitter : IDockable
+public interface IProportionalDockSplitter : ISplitter
{
///
/// Gets or sets whether the splitter allows resizing.
diff --git a/src/Dock.Model/Controls/ISplitter.cs b/src/Dock.Model/Controls/ISplitter.cs
new file mode 100644
index 000000000..01a262e45
--- /dev/null
+++ b/src/Dock.Model/Controls/ISplitter.cs
@@ -0,0 +1,12 @@
+// Copyright (c) Wiesław Šoltés. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for details.
+using Dock.Model.Core;
+
+namespace Dock.Model.Controls;
+
+///
+/// Splitter contract.
+///
+public interface ISplitter : IDockable
+{
+}
\ No newline at end of file
diff --git a/src/Dock.Model/FactoryBase.Dockable.cs b/src/Dock.Model/FactoryBase.Dockable.cs
index b178c7cc9..70f56e88f 100644
--- a/src/Dock.Model/FactoryBase.Dockable.cs
+++ b/src/Dock.Model/FactoryBase.Dockable.cs
@@ -58,7 +58,7 @@ public virtual void RemoveDockable(IDockable dockable, bool collapse)
if (dock.VisibleDockables.Count > 0)
{
var nextActiveDockable = dock.VisibleDockables[indexActiveDockable];
- dock.ActiveDockable = nextActiveDockable is not IProportionalDockSplitter ? nextActiveDockable : null;
+ dock.ActiveDockable = nextActiveDockable is not ISplitter ? nextActiveDockable : null;
}
else
{
@@ -98,21 +98,21 @@ protected void CleanupOrphanedSplitters(IDock dock)
var dockables = dock.VisibleDockables.ToList();
// If we only have splitters, remove all of them
- if (dockables.Count > 0 && dockables.All(d => d is IProportionalDockSplitter))
+ if (dockables.Count > 0 && dockables.All(d => d is ISplitter))
{
toRemove.AddRange(dockables);
}
else
{
// Remove splitters that are at the beginning
- while (dockables.Count > 0 && dockables[0] is IProportionalDockSplitter)
+ while (dockables.Count > 0 && dockables[0] is ISplitter)
{
toRemove.Add(dockables[0]);
dockables.RemoveAt(0);
}
// Remove splitters that are at the end
- while (dockables.Count > 0 && dockables[dockables.Count - 1] is IProportionalDockSplitter)
+ while (dockables.Count > 0 && dockables[dockables.Count - 1] is ISplitter)
{
toRemove.Add(dockables[dockables.Count - 1]);
dockables.RemoveAt(dockables.Count - 1);
@@ -121,11 +121,11 @@ protected void CleanupOrphanedSplitters(IDock dock)
// Remove consecutive splitters - keep only the first one in each sequence
for (int i = 0; i < dockables.Count - 1; i++)
{
- if (dockables[i] is IProportionalDockSplitter)
+ if (dockables[i] is ISplitter)
{
// Remove all consecutive splitters after this one
int j = i + 1;
- while (j < dockables.Count && dockables[j] is IProportionalDockSplitter)
+ while (j < dockables.Count && dockables[j] is ISplitter)
{
toRemove.Add(dockables[j]);
j++;
@@ -147,10 +147,10 @@ protected void CleanupOrphanedSplitters(IDock dock)
}
// Update active dockable if it was a splitter that got removed
- if (dock.ActiveDockable is IProportionalDockSplitter ||
+ if (dock.ActiveDockable is ISplitter ||
(dock.ActiveDockable is not null && !dock.VisibleDockables.Contains(dock.ActiveDockable)))
{
- dock.ActiveDockable = dock.VisibleDockables?.FirstOrDefault(d => d is not IProportionalDockSplitter);
+ dock.ActiveDockable = dock.VisibleDockables?.FirstOrDefault(d => d is not ISplitter);
}
}
@@ -1254,7 +1254,7 @@ private void UpdateIsEmpty(IDock dock)
var newIsEmpty = dock.VisibleDockables == null
|| dock.VisibleDockables?.Count == 0
- || dock.VisibleDockables!.All(x => x is IDock { IsEmpty: true, IsCollapsable: true } or IProportionalDockSplitter);
+ || dock.VisibleDockables!.All(x => x is IDock { IsEmpty: true, IsCollapsable: true } or ISplitter);
if (oldIsEmpty != newIsEmpty)
{
diff --git a/src/Dock.Model/FactoryBase.Init.cs b/src/Dock.Model/FactoryBase.Init.cs
index 84b14e0b4..1a28a82d0 100644
--- a/src/Dock.Model/FactoryBase.Init.cs
+++ b/src/Dock.Model/FactoryBase.Init.cs
@@ -35,8 +35,19 @@ public virtual void InitLayout(IDockable layout)
}
}
+ // Auto-set ActiveDockable for RootDock if not already set
if (layout is IRootDock rootDock)
{
+ if (rootDock.ActiveDockable is null && rootDock.VisibleDockables is not null)
+ {
+ // Find first visible dockable that is not a splitter
+ var firstVisible = FindFirstVisibleDockable(rootDock);
+ if (firstVisible is not null)
+ {
+ rootDock.ActiveDockable = firstVisible;
+ }
+ }
+
if (rootDock.ShowWindows.CanExecute(null))
{
rootDock.ShowWindows.Execute(null);
@@ -108,6 +119,43 @@ public virtual void InitDockable(IDockable dockable, IDockable? owner)
OnDockableInit(dockable);
}
+ ///
+ /// Finds the first visible dockable in the hierarchy that is not a splitter.
+ ///
+ /// The dock to search in.
+ /// The first visible dockable or null if none found.
+ private IDockable? FindFirstVisibleDockable(IDock dock)
+ {
+ if (dock.VisibleDockables is null)
+ {
+ return null;
+ }
+
+ // First look for direct visible dockables that are not splitters
+ foreach (var dockable in dock.VisibleDockables)
+ {
+ if (dockable is not ISplitter)
+ {
+ return dockable;
+ }
+ }
+
+ // If no direct dockables found, recursively search in child docks
+ foreach (var dockable in dock.VisibleDockables)
+ {
+ if (dockable is IDock childDock)
+ {
+ var result = FindFirstVisibleDockable(childDock);
+ if (result is not null)
+ {
+ return result;
+ }
+ }
+ }
+
+ return null;
+ }
+
private void InitDockables(IDockable dockable, IList dockables)
{
foreach (var child in dockables)