@@ -83,6 +83,20 @@ public void AddItem(DockItem item, ElementPane? pane, DockDirection? direction)
8383
8484 return Walk ( _rootPane ) ;
8585 }
86+
87+ #if DEBUG
88+ internal void RefreshTabViews ( )
89+ {
90+ foreach ( var pane in Hierarchy . Walk < DockPane > ( _rootPane , x => ( x as LayoutPane ) ? . NestedPanes ) . OfType < ElementPane > ( ) )
91+ {
92+ pane . RepairTabView ( ) ;
93+ }
94+ }
95+ internal void ResetPanes ( )
96+ {
97+ _rootPane ? . PopulateNestedPanes ( ) ;
98+ }
99+ #endif
86100}
87101public partial class DockControl // handlers, forwarded handlers
88102{
@@ -108,6 +122,16 @@ internal void OnPaneCloseRequested(ElementPane pane, RoutedEventArgs e)
108122 TryCloseEmptyPane ( pane ) ;
109123 }
110124 }
125+ internal void OnPaneDragStarting ( ElementPane pane , DragStartingEventArgs e )
126+ {
127+ Debug . WriteLine ( $ "@xy DockPanel::OnPaneDragStarting") ;
128+
129+ e . Data . Properties [ PropertyKeys . Container ] = pane ;
130+ }
131+ internal void OnPaneDropCompleted ( ElementPane pane , DropCompletedEventArgs e )
132+ {
133+ Debug . WriteLine ( $ "@xy DockPanel::OnPaneDragStarting") ;
134+ }
111135 internal void OnPaneDropEnter ( ElementPane pane , DragEventArgs e )
112136 {
113137 Debug . WriteLine ( $ "@xy DockControl::OnPaneDropEnter") ;
@@ -120,7 +144,7 @@ internal void OnPaneDropEnter(ElementPane pane, DragEventArgs e)
120144 if ( pane . CanAcceptDrop ( item ) )
121145 {
122146 e . AcceptedOperation = DataPackageOperation . Move ;
123- _dockingDiamond ? . ShowAt ( pane ) ;
147+ _dockingDiamond ? . ShowAt ( pane , item ) ;
124148 }
125149 else
126150 {
@@ -133,7 +157,7 @@ internal void OnPaneDropEnter(ElementPane pane, DragEventArgs e)
133157 if ( container != pane )
134158 {
135159 e . AcceptedOperation = DataPackageOperation . Move ;
136- _dockingDiamond ? . ShowAt ( pane ) ;
160+ _dockingDiamond ? . ShowAt ( pane , null ) ;
137161 }
138162 else
139163 {
@@ -142,10 +166,6 @@ internal void OnPaneDropEnter(ElementPane pane, DragEventArgs e)
142166 }
143167 }
144168 }
145- //internal void OnPaneDropOver(ElementPane pane, DragEventArgs e)
146- //{
147- // //Debug.WriteLine($"@xy DockControl::OnPaneDropOver");
148- //}
149169 internal void OnPaneDropLeave ( ElementPane pane , DragEventArgs e )
150170 {
151171 Debug . WriteLine ( $ "@xy DockControl::OnPaneDropLeave") ;
@@ -170,6 +190,7 @@ internal void OnPaneDrop(ElementPane pane, DragEventArgs e)
170190 if ( ! pane . CanAcceptDrop ( item ) ) return ;
171191
172192 var direction = _dockingDiamond ? . Direction ?? DockDirection . None ;
193+ var dirInfo = direction . Explode ( ) ;
173194 if ( direction is DockDirection . None )
174195 {
175196 if ( container == pane ) return ;
@@ -182,28 +203,79 @@ internal void OnPaneDrop(ElementPane pane, DragEventArgs e)
182203 TryCloseEmptyPane ( container ) ;
183204 }
184205 }
206+ else if ( dirInfo . IsEdge )
207+ {
208+ throw new NotImplementedException ( direction . ToString ( ) ) ;
209+ }
185210 else if ( pane is DocumentPane { ParentPane : EditorPane editorPane } )
186211 {
187- if ( pane . ParentPane is not { } parentPane ) return ;
188- if ( ! ( parentPane . NestedPanes . IndexOf ( pane ) is var index && index != - 1 ) ) return ;
189-
190- // For document pane, if we previously had splited, then only allow split in the same orientation (horizontally/vertically).
191- // If not, any direction is okay. If the document panes were to be reduced back to a single one again, remove the orientation restriction.
192- if ( ! editorPane . IsOrientationLocked && direction . ToOrientation ( ) is { } orientation )
212+ if ( dirInfo . IsInner )
193213 {
194- editorPane . Orientation = orientation ;
195- }
214+ if ( pane . ParentPane is not { } parentPane ) return ;
215+ if ( ! ( parentPane . NestedPanes . IndexOf ( pane ) is var index && index != - 1 ) ) return ;
216+
217+ // For document pane, if we previously had splited, then only allow split in the same orientation (horizontally/vertically).
218+ // If not, any direction is okay. If the document panes were to be reduced back to a single one again, remove the orientation restriction.
219+ if ( ! editorPane . IsOrientationLocked && direction . ToOrientation ( ) is { } orientation )
220+ {
221+ editorPane . Orientation = orientation ;
222+ }
196223
197- if ( editorPane . Orientation == direction . ToOrientation ( ) &&
198- container . Remove ( item ) )
224+ if ( editorPane . Orientation == direction . ToOrientation ( ) &&
225+ container . Remove ( item ) )
226+ {
227+ var newPane = new DocumentPane ( ) ;
228+
229+ parentPane . NestedPanes . Insert ( index + ( direction . IsLeading ( ) ? 0 : 1 ) , newPane ) ;
230+
231+ newPane . Add ( item ) ;
232+
233+ TryCloseEmptyPane ( container ) ;
234+ }
235+ }
236+ else if ( dirInfo . IsOuter && item is ToolItem )
199237 {
200- var newPane = new DocumentPane ( ) ;
238+ // refactor@xy: this block is mostly the same as `else if (item is ToolItem)` extract the logics into: TryInsertParallelPane(refPane, item, orientation)
239+ if ( editorPane . ParentPane is not { } parentPane ) return ;
240+ if ( ! ( parentPane . NestedPanes . IndexOf ( editorPane ) is var index && index != - 1 ) ) return ;
201241
202- parentPane . NestedPanes . Insert ( index + direction is DockDirection . Left or DockDirection . Top ? 0 : 1 , newPane ) ;
242+ if ( container . Remove ( item ) )
243+ {
244+ // if the direction is parallel to the parent layout, just insert the new pane before/after the target pane
245+ if ( parentPane . Orientation == direction . ToOrientation ( ) )
246+ {
247+ var newPane = new ToolPane ( ) ;
203248
204- newPane . Add ( item ) ;
249+ parentPane . NestedPanes . Insert ( index + direction is DockDirection . Left or DockDirection . Top ? 0 : 1 , newPane ) ;
205250
206- TryCloseEmptyPane ( container ) ;
251+ newPane . Add ( item ) ;
252+ }
253+ // if the direction is perpendicular to the parent layout,
254+ // remove the target pane from its parent, insert a new layout pane at its place,
255+ // add the target pane and the new pane.
256+ else
257+ {
258+ var newLayoutPane = new LayoutPane { Orientation = parentPane . Orientation . ToOpposite ( ) } ;
259+ var newPane = new ToolPane ( ) ;
260+
261+ parentPane . NestedPanes . Remove ( editorPane ) ;
262+ if ( direction . IsLeading ( ) )
263+ {
264+ newLayoutPane . NestedPanes . Add ( newPane ) ;
265+ newLayoutPane . NestedPanes . Add ( editorPane ) ;
266+ }
267+ else
268+ {
269+ newLayoutPane . NestedPanes . Add ( editorPane ) ;
270+ newLayoutPane . NestedPanes . Add ( newPane ) ;
271+ }
272+ parentPane . NestedPanes . Insert ( index , newLayoutPane ) ;
273+
274+ newPane . Add ( item ) ;
275+ }
276+
277+ TryCloseEmptyPane ( container ) ;
278+ }
207279 }
208280 else
209281 {
@@ -213,6 +285,8 @@ internal void OnPaneDrop(ElementPane pane, DragEventArgs e)
213285 }
214286 else if ( item is ToolItem )
215287 {
288+ if ( ! dirInfo . IsInner && ! dirInfo . IsEdge ) throw new ArgumentOutOfRangeException ( direction . ToString ( ) ) ;
289+
216290 if ( pane . ParentPane is not { } parentPane ) return ;
217291 if ( ! ( parentPane . NestedPanes . IndexOf ( pane ) is var index && index != - 1 ) ) return ;
218292
@@ -232,11 +306,11 @@ internal void OnPaneDrop(ElementPane pane, DragEventArgs e)
232306 // add the target pane and the new pane.
233307 else
234308 {
235- var newLayoutPane = new LayoutPane { Orientation = pane . ParentPane . Orientation . Opposite ( ) } ;
309+ var newLayoutPane = new LayoutPane { Orientation = pane . ParentPane . Orientation . ToOpposite ( ) } ;
236310 var newPane = new ToolPane ( ) ;
237311
238312 parentPane . NestedPanes . Remove ( pane ) ;
239- if ( direction is DockDirection . Left or DockDirection . Top )
313+ if ( direction . IsLeading ( ) )
240314 {
241315 newLayoutPane . NestedPanes . Add ( newPane ) ;
242316 newLayoutPane . NestedPanes . Add ( pane ) ;
@@ -335,7 +409,7 @@ internal void OnPaneDrop(ElementPane pane, DragEventArgs e)
335409 // add the target pane and the new pane.
336410 else
337411 {
338- var newLayoutPane = new LayoutPane { Orientation = pane . ParentPane . Orientation . Opposite ( ) } ;
412+ var newLayoutPane = new LayoutPane { Orientation = pane . ParentPane . Orientation . ToOpposite ( ) } ;
339413 var newPane = new ToolPane ( ) ;
340414
341415 parentPane . NestedPanes . Remove ( pane ) ;
@@ -352,7 +426,7 @@ internal void OnPaneDrop(ElementPane pane, DragEventArgs e)
352426 parentPane . NestedPanes . Insert ( index , newLayoutPane ) ;
353427
354428 pane . RepairTabView ( ) ;
355-
429+
356430 newPane . AddRange ( items ) ;
357431 }
358432
@@ -365,17 +439,6 @@ internal void OnPaneDrop(ElementPane pane, DragEventArgs e)
365439 }
366440 }
367441
368- internal void OnPaneDragStarting ( ElementPane pane , DragStartingEventArgs e )
369- {
370- Debug . WriteLine ( $ "@xy DockPanel::OnPaneDragStarting") ;
371-
372- e . Data . Properties [ PropertyKeys . Container ] = pane ;
373- }
374- internal void OnPaneDropCompleted ( ElementPane pane , DropCompletedEventArgs e )
375- {
376- Debug . WriteLine ( $ "@xy DockPanel::OnPaneDragStarting") ;
377- }
378-
379442 internal void OnItemCloseRequested ( ElementPane pane , TabViewTabCloseRequestedEventArgs e )
380443 {
381444 Debug . WriteLine ( $ "@xy DockControl::OnItemCloseRequested") ;
@@ -437,6 +500,7 @@ private void ReduceEmptyPaneRecursively(LayoutPane? pane)
437500 ReduceEmptyPaneRecursively ( pane ) ;
438501 }
439502 }
503+
440504 private ( ElementPane ? Container , DockItem ? Item ) ExtractDragInfo ( DataPackageView view )
441505 {
442506 if ( ExtractValue < ElementPane > ( view . Properties , PropertyKeys . Container , out var container ) )
0 commit comments