@@ -111,36 +111,40 @@ public virtual void CollapseDock(IDock dock)
111
111
}
112
112
}
113
113
114
+ // Adjust adjacent splitters prior to removing dock so that exactly one splitter remains between neighbors.
114
115
if ( dock . Owner is IDock ownerDock && ownerDock . VisibleDockables is { } )
115
116
{
116
- var toRemove = new List < IDockable > ( ) ;
117
117
var dockIndex = ownerDock . VisibleDockables . IndexOf ( dock ) ;
118
-
119
118
if ( dockIndex >= 0 )
120
119
{
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 )
123
125
{
124
- var previousVisible = ownerDock . VisibleDockables [ indexSplitterPrevious ] ;
125
- if ( previousVisible is IProportionalDockSplitter splitterPrevious )
126
- {
127
- toRemove . Add ( splitterPrevious ) ;
128
- }
126
+ previousSplitter = ps ;
129
127
}
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 )
133
130
{
134
- var nextVisible = ownerDock . VisibleDockables [ indexSplitterNext ] ;
135
- if ( nextVisible is IProportionalDockSplitter splitterNext )
136
- {
137
- toRemove . Add ( splitterNext ) ;
138
- }
131
+ nextSplitter = ns ;
139
132
}
140
133
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 )
142
140
{
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 ) ;
144
148
}
145
149
}
146
150
}
@@ -158,6 +162,66 @@ public virtual void CollapseDock(IDock dock)
158
162
if ( dock . Owner is IProportionalDock proportionalOwner )
159
163
{
160
164
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
+ }
161
225
}
162
226
}
163
227
0 commit comments