Skip to content

Commit f86f7f2

Browse files
Merge pull request #873 from wieslawsoltes/AutoSetActiveDockableForRootDock
Auto set active dockable for root dock
2 parents 8e7b47d + 8f2851f commit f86f7f2

File tree

6 files changed

+77
-17
lines changed

6 files changed

+77
-17
lines changed

samples/DockControlPanelsSample/MainView.axaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
<Factory />
2424
</DockControl.Factory>
2525

26-
<RootDock Id="ProportionalRoot" IsCollapsable="False" ActiveDockable="ProportionalMain">
26+
<RootDock Id="ProportionalRoot" IsCollapsable="False">
2727
<ProportionalDock x:Name="ProportionalMain" Id="ProportionalMain" Orientation="Horizontal">
2828

2929
<!-- Left Tool -->
@@ -68,7 +68,7 @@
6868
<Factory />
6969
</DockControl.Factory>
7070

71-
<RootDock Id="StackRoot" IsCollapsable="False" ActiveDockable="StackMain">
71+
<RootDock Id="StackRoot" IsCollapsable="False">
7272
<StackDock x:Name="StackMain" Id="StackMain" Orientation="Horizontal" Spacing="5">
7373

7474
<ToolDock Id="StackTool1" Alignment="Unset">
@@ -107,7 +107,7 @@
107107
<Factory />
108108
</DockControl.Factory>
109109

110-
<RootDock Id="GridRoot" IsCollapsable="False" ActiveDockable="GridMain">
110+
<RootDock Id="GridRoot" IsCollapsable="False">
111111
<GridDock x:Name="GridMain" Id="GridMain" ColumnDefinitions="*,Auto,2*,Auto,*" RowDefinitions="Auto,*">
112112

113113
<!-- Top row toolbar -->
@@ -159,7 +159,7 @@
159159
<Factory />
160160
</DockControl.Factory>
161161

162-
<RootDock Id="WrapRoot" IsCollapsable="False" ActiveDockable="WrapMain">
162+
<RootDock Id="WrapRoot" IsCollapsable="False">
163163
<WrapDock x:Name="WrapMain" Id="WrapMain" Orientation="Horizontal">
164164

165165
<ToolDock Id="WrapTool1" Alignment="Unset">
@@ -210,7 +210,7 @@
210210
<Factory />
211211
</DockControl.Factory>
212212

213-
<RootDock Id="UniformRoot" IsCollapsable="False" ActiveDockable="UniformMain">
213+
<RootDock Id="UniformRoot" IsCollapsable="False">
214214
<UniformGridDock x:Name="UniformMain" Id="UniformMain" Rows="2" Columns="3">
215215

216216
<ToolDock Id="UniformTool1" Alignment="Unset">
@@ -261,7 +261,7 @@
261261
<Factory />
262262
</DockControl.Factory>
263263

264-
<RootDock Id="DockRoot" IsCollapsable="False" ActiveDockable="DockMain">
264+
<RootDock Id="DockRoot" IsCollapsable="False">
265265
<DockDock x:Name="DockMain" Id="DockMain" LastChildFill="True">
266266

267267
<!-- Top toolbar -->

src/Dock.Model/Controls/IGridDockSplitter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Dock.Model.Controls;
88
/// Grid splitter dock contract.
99
/// </summary>
1010
[RequiresDataTemplate]
11-
public interface IGridDockSplitter : IDockable
11+
public interface IGridDockSplitter : ISplitter
1212
{
1313
/// <summary>
1414
/// Gets or sets resize direction.

src/Dock.Model/Controls/IProportionalDockSplitter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Dock.Model.Controls;
88
/// Proportional dock splitter contract.
99
/// </summary>
1010
[RequiresDataTemplate]
11-
public interface IProportionalDockSplitter : IDockable
11+
public interface IProportionalDockSplitter : ISplitter
1212
{
1313
/// <summary>
1414
/// Gets or sets whether the splitter allows resizing.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) Wiesław Šoltés. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for details.
3+
using Dock.Model.Core;
4+
5+
namespace Dock.Model.Controls;
6+
7+
/// <summary>
8+
/// Splitter contract.
9+
/// </summary>
10+
public interface ISplitter : IDockable
11+
{
12+
}

src/Dock.Model/FactoryBase.Dockable.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public virtual void RemoveDockable(IDockable dockable, bool collapse)
5858
if (dock.VisibleDockables.Count > 0)
5959
{
6060
var nextActiveDockable = dock.VisibleDockables[indexActiveDockable];
61-
dock.ActiveDockable = nextActiveDockable is not IProportionalDockSplitter ? nextActiveDockable : null;
61+
dock.ActiveDockable = nextActiveDockable is not ISplitter ? nextActiveDockable : null;
6262
}
6363
else
6464
{
@@ -98,21 +98,21 @@ protected void CleanupOrphanedSplitters(IDock dock)
9898
var dockables = dock.VisibleDockables.ToList();
9999

100100
// If we only have splitters, remove all of them
101-
if (dockables.Count > 0 && dockables.All(d => d is IProportionalDockSplitter))
101+
if (dockables.Count > 0 && dockables.All(d => d is ISplitter))
102102
{
103103
toRemove.AddRange(dockables);
104104
}
105105
else
106106
{
107107
// Remove splitters that are at the beginning
108-
while (dockables.Count > 0 && dockables[0] is IProportionalDockSplitter)
108+
while (dockables.Count > 0 && dockables[0] is ISplitter)
109109
{
110110
toRemove.Add(dockables[0]);
111111
dockables.RemoveAt(0);
112112
}
113113

114114
// Remove splitters that are at the end
115-
while (dockables.Count > 0 && dockables[dockables.Count - 1] is IProportionalDockSplitter)
115+
while (dockables.Count > 0 && dockables[dockables.Count - 1] is ISplitter)
116116
{
117117
toRemove.Add(dockables[dockables.Count - 1]);
118118
dockables.RemoveAt(dockables.Count - 1);
@@ -121,11 +121,11 @@ protected void CleanupOrphanedSplitters(IDock dock)
121121
// Remove consecutive splitters - keep only the first one in each sequence
122122
for (int i = 0; i < dockables.Count - 1; i++)
123123
{
124-
if (dockables[i] is IProportionalDockSplitter)
124+
if (dockables[i] is ISplitter)
125125
{
126126
// Remove all consecutive splitters after this one
127127
int j = i + 1;
128-
while (j < dockables.Count && dockables[j] is IProportionalDockSplitter)
128+
while (j < dockables.Count && dockables[j] is ISplitter)
129129
{
130130
toRemove.Add(dockables[j]);
131131
j++;
@@ -147,10 +147,10 @@ protected void CleanupOrphanedSplitters(IDock dock)
147147
}
148148

149149
// Update active dockable if it was a splitter that got removed
150-
if (dock.ActiveDockable is IProportionalDockSplitter ||
150+
if (dock.ActiveDockable is ISplitter ||
151151
(dock.ActiveDockable is not null && !dock.VisibleDockables.Contains(dock.ActiveDockable)))
152152
{
153-
dock.ActiveDockable = dock.VisibleDockables?.FirstOrDefault(d => d is not IProportionalDockSplitter);
153+
dock.ActiveDockable = dock.VisibleDockables?.FirstOrDefault(d => d is not ISplitter);
154154
}
155155
}
156156

@@ -1254,7 +1254,7 @@ private void UpdateIsEmpty(IDock dock)
12541254

12551255
var newIsEmpty = dock.VisibleDockables == null
12561256
|| dock.VisibleDockables?.Count == 0
1257-
|| dock.VisibleDockables!.All(x => x is IDock { IsEmpty: true, IsCollapsable: true } or IProportionalDockSplitter);
1257+
|| dock.VisibleDockables!.All(x => x is IDock { IsEmpty: true, IsCollapsable: true } or ISplitter);
12581258

12591259
if (oldIsEmpty != newIsEmpty)
12601260
{

src/Dock.Model/FactoryBase.Init.cs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,19 @@ public virtual void InitLayout(IDockable layout)
3535
}
3636
}
3737

38+
// Auto-set ActiveDockable for RootDock if not already set
3839
if (layout is IRootDock rootDock)
3940
{
41+
if (rootDock.ActiveDockable is null && rootDock.VisibleDockables is not null)
42+
{
43+
// Find first visible dockable that is not a splitter
44+
var firstVisible = FindFirstVisibleDockable(rootDock);
45+
if (firstVisible is not null)
46+
{
47+
rootDock.ActiveDockable = firstVisible;
48+
}
49+
}
50+
4051
if (rootDock.ShowWindows.CanExecute(null))
4152
{
4253
rootDock.ShowWindows.Execute(null);
@@ -108,6 +119,43 @@ public virtual void InitDockable(IDockable dockable, IDockable? owner)
108119
OnDockableInit(dockable);
109120
}
110121

122+
/// <summary>
123+
/// Finds the first visible dockable in the hierarchy that is not a splitter.
124+
/// </summary>
125+
/// <param name="dock">The dock to search in.</param>
126+
/// <returns>The first visible dockable or null if none found.</returns>
127+
private IDockable? FindFirstVisibleDockable(IDock dock)
128+
{
129+
if (dock.VisibleDockables is null)
130+
{
131+
return null;
132+
}
133+
134+
// First look for direct visible dockables that are not splitters
135+
foreach (var dockable in dock.VisibleDockables)
136+
{
137+
if (dockable is not ISplitter)
138+
{
139+
return dockable;
140+
}
141+
}
142+
143+
// If no direct dockables found, recursively search in child docks
144+
foreach (var dockable in dock.VisibleDockables)
145+
{
146+
if (dockable is IDock childDock)
147+
{
148+
var result = FindFirstVisibleDockable(childDock);
149+
if (result is not null)
150+
{
151+
return result;
152+
}
153+
}
154+
}
155+
156+
return null;
157+
}
158+
111159
private void InitDockables(IDockable dockable, IList<IDockable> dockables)
112160
{
113161
foreach (var child in dockables)

0 commit comments

Comments
 (0)