@@ -322,4 +322,161 @@ public void TestSimpleDrag_IntoTabView()
322322
323323 } , out _ ) ;
324324 }
325+
326+ [ Test ]
327+ public void TestDropInto_SelfIgnored ( )
328+ {
329+ var d = Get10By10View ( ) ;
330+ var lbl = new Label { X = 1 , Y = 1 , Text = "Hello" } ;
331+ var lblDesign = new Design ( d . SourceCode , "lbl" , lbl ) ;
332+ lbl . Data = lblDesign ;
333+ d . View . Add ( lbl ) ;
334+
335+ var drag = new DragOperation ( lblDesign , 1 , 1 , null ) ;
336+
337+ // Try to set DropInto to itself
338+ drag . DropInto = lbl ;
339+
340+ ClassicAssert . IsNull ( drag . DropInto , "Should ignore attempts to drop a view into itself" ) ;
341+ }
342+
343+ [ Test ]
344+ public void TestDropInto_NonContainerIgnored ( )
345+ {
346+ var d = Get10By10View ( ) ;
347+
348+ var lbl = new Label { X = 1 , Y = 1 , Text = "Hello" } ;
349+ var lblDesign = new Design ( d . SourceCode , "lbl" , lbl ) ;
350+ lbl . Data = lblDesign ;
351+ d . View . Add ( lbl ) ;
352+
353+ var btn = new Button { Text = "Not a container" } ;
354+ d . View . Add ( btn ) ;
355+
356+ var drag = new DragOperation ( lblDesign , 1 , 1 , null ) ;
357+
358+ // Try to drop into a non-container view
359+ drag . DropInto = btn ;
360+
361+ ClassicAssert . IsNull ( drag . DropInto , "Should ignore attempts to drop into non-container views" ) ;
362+ }
363+
364+ [ Test ]
365+ public void TestDropInto_DependentViews_MakesImpossible ( )
366+ {
367+ var d = Get10By10View ( ) ;
368+
369+ // Parent container
370+ var container1 = new View { Width = 10 , Height = 10 } ;
371+ container1 . Data = new Design ( d . SourceCode , "c1" , container1 ) ;
372+ d . View . Add ( container1 ) ;
373+
374+ // Another container to drop into
375+ var container2 = new View { Width = 10 , Height = 10 } ;
376+ container2 . Data = new Design ( d . SourceCode , "c2" , container2 ) ;
377+ d . View . Add ( container2 ) ;
378+
379+ // Label inside container1
380+ var lbl = new Label { X = 1 , Y = 1 , Text = "Hello" } ;
381+ var lblDesign = new Design ( d . SourceCode , "lbl" , lbl ) ;
382+ lbl . Data = lblDesign ;
383+ container1 . Add ( lbl ) ;
384+
385+ // Another label that depends on lbl for positioning
386+ var lbl2 = new Label { X = Pos . Right ( lbl ) + 1 , Y = 1 , Text = "World" } ;
387+ var lblDesign2 = new Design ( d . SourceCode , "lbl2" , lbl2 ) ;
388+ lbl2 . Data = lblDesign2 ;
389+ container1 . Add ( lbl2 ) ;
390+
391+ var drag = new DragOperation ( lblDesign , 1 , 1 , null ) ;
392+
393+ // Try to move lbl into container2
394+ drag . DropInto = container2 ;
395+
396+ ClassicAssert . IsTrue ( drag . IsImpossible , "Should be impossible to drop when dependent views exist that are not part of the drag" ) ;
397+ ClassicAssert . Contains ( lbl2 , container1 . SubViews . ToArray ( ) , "Dependent view should remain in original container" ) ;
398+ }
399+
400+ [ Test ]
401+ public void TestDropInto_AllDependantsDragged_Allowed ( )
402+ {
403+ var d = Get10By10View ( ) ;
404+
405+ var container1 = new View { Width = 10 , Height = 10 } ;
406+ container1 . Data = new Design ( d . SourceCode , "c1" , container1 ) ;
407+ d . View . Add ( container1 ) ;
408+
409+ var container2 = new View { Width = 10 , Height = 10 } ;
410+ container2 . Data = new Design ( d . SourceCode , "c2" , container2 ) ;
411+ d . View . Add ( container2 ) ;
412+
413+ // First label
414+ var lbl1 = new Label { X = 1 , Y = 1 , Text = "One" } ;
415+ var lblDesign1 = new Design ( d . SourceCode , "lbl1" , lbl1 ) ;
416+ lbl1 . Data = lblDesign1 ;
417+ container1 . Add ( lbl1 ) ;
418+
419+ // Second label depends on lbl1
420+ var lbl2 = new Label { X = Pos . Right ( lbl1 ) + 1 , Y = 1 , Text = "Two" } ;
421+ var lblDesign2 = new Design ( d . SourceCode , "lbl2" , lbl2 ) ;
422+ lbl2 . Data = lblDesign2 ;
423+ container1 . Add ( lbl2 ) ;
424+
425+ // Drag lbl1 and lbl2 together
426+ var drag = new DragOperation ( lblDesign1 , 1 , 1 , new [ ] { lblDesign2 } ) ;
427+
428+ // Try to drop into container2
429+ drag . DropInto = container2 ;
430+
431+ ClassicAssert . IsFalse ( drag . IsImpossible , "Dragging both dependants together should be allowed" ) ;
432+ drag . Do ( ) ;
433+
434+ ClassicAssert . Contains ( lbl1 , container2 . SubViews . ToArray ( ) ) ;
435+ ClassicAssert . Contains ( lbl2 , container2 . SubViews . ToArray ( ) ) ;
436+ }
437+ [ Test ]
438+ public void TestAbandon_RestoresOriginalPosition ( )
439+ {
440+ var d = Get10By10View ( ) ;
441+
442+ var container1 = new View { Width = 10 , Height = 10 } ;
443+ container1 . Data = new Design ( d . SourceCode , "c1" , container1 ) ;
444+ d . View . Add ( container1 ) ;
445+
446+ var container2 = new View { Width = 10 , Height = 10 } ;
447+ container2 . Data = new Design ( d . SourceCode , "c2" , container2 ) ;
448+ d . View . Add ( container2 ) ;
449+
450+ // Label in container1
451+ var lbl = new Label { X = 1 , Y = 2 , Text = "Hello" } ;
452+ var lblDesign = new Design ( d . SourceCode , "lbl" , lbl ) ;
453+ lbl . Data = lblDesign ;
454+ container1 . Add ( lbl ) ;
455+
456+ // Another label depending on the first
457+ var lbl2 = new Label { X = Pos . Right ( lbl ) + 1 , Y = 2 , Text = "World" } ;
458+ var lblDesign2 = new Design ( d . SourceCode , "lbl2" , lbl2 ) ;
459+ lbl2 . Data = lblDesign2 ;
460+ container1 . Add ( lbl2 ) ;
461+
462+ var drag = new DragOperation ( lblDesign , 1 , 2 , null ) ;
463+
464+ // Move to a legal new position
465+ drag . ContinueDrag ( new Point ( 3 , 4 ) ) ;
466+ ClassicAssert . AreEqual ( Pos . Absolute ( 3 ) , lbl . X ) ;
467+ ClassicAssert . AreEqual ( Pos . Absolute ( 4 ) , lbl . Y ) ;
468+
469+ // Now try to drop into container2 (impossible, because lbl2 depends on lbl)
470+ drag . DropInto = container2 ;
471+ ClassicAssert . IsTrue ( drag . IsImpossible ) ;
472+
473+ // Call Abandon should snap lbl back to original
474+ drag . Abandon ( ) ;
475+
476+ ClassicAssert . AreEqual ( Pos . Absolute ( 1 ) , lbl . X ) ;
477+ ClassicAssert . AreEqual ( Pos . Absolute ( 2 ) , lbl . Y ) ;
478+ ClassicAssert . Contains ( lbl , container1 . SubViews . ToArray ( ) , "Expected abandon to restore original container" ) ;
479+ }
480+
481+
325482}
0 commit comments