Skip to content

Commit 9f7b0bf

Browse files
committed
fix removing too many splitters.
1 parent e35e228 commit 9f7b0bf

File tree

1 file changed

+83
-19
lines changed

1 file changed

+83
-19
lines changed

src/Dock.Model/FactoryBase.cs

Lines changed: 83 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -111,36 +111,40 @@ public virtual void CollapseDock(IDock dock)
111111
}
112112
}
113113

114+
// Adjust adjacent splitters prior to removing dock so that exactly one splitter remains between neighbors.
114115
if (dock.Owner is IDock ownerDock && ownerDock.VisibleDockables is { })
115116
{
116-
var toRemove = new List<IDockable>();
117117
var dockIndex = ownerDock.VisibleDockables.IndexOf(dock);
118-
119118
if (dockIndex >= 0)
120119
{
121-
var indexSplitterPrevious = dockIndex - 1;
122-
if (dockIndex > 0 && indexSplitterPrevious >= 0)
120+
IProportionalDockSplitter? previousSplitter = null;
121+
IProportionalDockSplitter? nextSplitter = null;
122+
123+
var prevIndex = dockIndex - 1;
124+
if (prevIndex >= 0 && ownerDock.VisibleDockables[prevIndex] is IProportionalDockSplitter ps)
123125
{
124-
var previousVisible = ownerDock.VisibleDockables[indexSplitterPrevious];
125-
if (previousVisible is IProportionalDockSplitter splitterPrevious)
126-
{
127-
toRemove.Add(splitterPrevious);
128-
}
126+
previousSplitter = ps;
129127
}
130-
131-
var indexSplitterNext = dockIndex + 1;
132-
if (dockIndex < ownerDock.VisibleDockables.Count - 1 && indexSplitterNext >= 0)
128+
var nextIndex = dockIndex + 1;
129+
if (nextIndex < ownerDock.VisibleDockables.Count && ownerDock.VisibleDockables[nextIndex] is IProportionalDockSplitter ns)
133130
{
134-
var nextVisible = ownerDock.VisibleDockables[indexSplitterNext];
135-
if (nextVisible is IProportionalDockSplitter splitterNext)
136-
{
137-
toRemove.Add(splitterNext);
138-
}
131+
nextSplitter = ns;
139132
}
140133

141-
foreach (var removeVisible in toRemove)
134+
// If both sides have splitters remove only one (deterministically remove the previous one)
135+
if (previousSplitter is not null && nextSplitter is not null)
136+
{
137+
RemoveDockable(previousSplitter, true);
138+
}
139+
else if (previousSplitter is not null)
142140
{
143-
RemoveDockable(removeVisible, true);
141+
// Edge (first after a splitter) – remove lone previous splitter
142+
RemoveDockable(previousSplitter, true);
143+
}
144+
else if (nextSplitter is not null)
145+
{
146+
// Edge (last before a splitter) – remove lone next splitter
147+
RemoveDockable(nextSplitter, true);
144148
}
145149
}
146150
}
@@ -158,6 +162,66 @@ public virtual void CollapseDock(IDock dock)
158162
if (dock.Owner is IProportionalDock proportionalOwner)
159163
{
160164
CleanupProportionalDockTree(proportionalOwner);
165+
// Ensure splitter pattern correctness after structural change.
166+
CleanupOrphanedSplitters(proportionalOwner);
167+
}
168+
}
169+
170+
// Ensures there are no duplicate or orphaned splitters and that a splitter exists between two adjacent non-splitter dockables inside a proportional dock.
171+
private void CleanupOrphanedSplitters(IProportionalDock dock)
172+
{
173+
var list = dock.VisibleDockables;
174+
if (list is null || list.Count == 0)
175+
return;
176+
177+
int i = 0;
178+
while (i < list.Count)
179+
{
180+
if (i >= list.Count) break; // safety
181+
var current = list[i];
182+
183+
if (current is IProportionalDockSplitter)
184+
{
185+
bool remove = false;
186+
if (i == 0 || i == list.Count - 1)
187+
{
188+
// Leading or trailing splitter is invalid.
189+
remove = true;
190+
}
191+
else
192+
{
193+
var prev = list[i - 1];
194+
var next = list[i + 1];
195+
if (prev is IProportionalDockSplitter || next is IProportionalDockSplitter)
196+
{
197+
// Duplicate or consecutive splitters.
198+
remove = true;
199+
}
200+
}
201+
202+
if (remove)
203+
{
204+
RemoveDockable(current, true);
205+
continue; // Stay at same index after removal.
206+
}
207+
208+
i++; // Keep valid splitter
209+
}
210+
else
211+
{
212+
// If next exists and is not a splitter, insert one between.
213+
if (i < list.Count - 1 && list[i + 1] is not IProportionalDockSplitter)
214+
{
215+
var splitter = CreateProportionalDockSplitter();
216+
splitter.Title = nameof(IProportionalDockSplitter);
217+
InsertVisibleDockable(dock, i + 1, splitter);
218+
OnDockableAdded(splitter);
219+
InitDockable(splitter, dock);
220+
i += 2; // Skip over inserted splitter and next item.
221+
continue;
222+
}
223+
i++;
224+
}
161225
}
162226
}
163227

0 commit comments

Comments
 (0)