diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index ef45c747d..c9062cd8a 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -2458,9 +2458,13 @@ namespace Terminal.Gui { (var from, var to) = edges.First (); if (from != superView?.GetTopSuperView (to, from)) { if (!ReferenceEquals (from, to)) { - throw new InvalidOperationException ($"TopologicalSort (for Pos/Dim) cannot find {from} linked with {to}. Did you forget to add it to {superView}?"); + if (ReferenceEquals (from.SuperView, to)) { + throw new InvalidOperationException ($"ComputedLayout for \"{superView}\": \"{to}\" references a SubView (\"{from}\")."); + } else { + throw new InvalidOperationException ($"ComputedLayout for \"{superView}\": \"{from}\" linked with \"{to}\" was not found. Did you forget to add it to {superView}?"); + } } else { - throw new InvalidOperationException ("TopologicalSort encountered a recursive cycle in the relative Pos/Dim in the views of " + superView); + throw new InvalidOperationException ($"ComputedLayout for \"{superView}\": A recursive cycle was found in the relative Pos/Dim of the SubViews."); } } } diff --git a/UICatalog/Scenarios/MessageBoxes.cs b/UICatalog/Scenarios/MessageBoxes.cs index 807af3a98..dcfd2456f 100644 --- a/UICatalog/Scenarios/MessageBoxes.cs +++ b/UICatalog/Scenarios/MessageBoxes.cs @@ -159,10 +159,37 @@ namespace UICatalog.Scenarios { }; frame.Add (ckbWrapMessage); + frame.ForceValidatePosDim = true; + void Top_Loaded () { - frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + Dim.Height (messageEdit) - + Dim.Height (numButtonsEdit) + Dim.Height (defaultButtonEdit) + Dim.Height (styleRadioGroup) + 2 + Dim.Height (ckbEffect3D) + Dim.Height (ckbWrapMessage); + frame.Height = + widthEdit.Frame.Height + + heightEdit.Frame.Height + + titleEdit.Frame.Height + + messageEdit.Frame.Height + + numButtonsEdit.Frame.Height + + defaultButtonEdit.Frame.Height + + styleRadioGroup.Frame.Height + + 2 + + ckbEffect3D.Frame.Height + + ckbWrapMessage.Frame.Height; + + // BUGBUG: this only worked because the subviews are actually added + // to FrameView.ContentView, not FrameView itself. In v2 this breaks because FrameView + // does not have a ContentView. + // + //Dim.Height (widthEdit) + + //Dim.Height (heightEdit); + //+ + //Dim.Height (titleEdit) + + //Dim.Height (messageEdit) + + //Dim.Height (numButtonsEdit) + + //Dim.Height (defaultButtonEdit) + + //Dim.Height (styleRadioGroup) + + //2 + + //Dim.Height (ckbEffect3D) + + //Dim.Height (ckbWrapMessage); Application.Top.Loaded -= Top_Loaded; } Application.Top.Loaded += Top_Loaded; diff --git a/UnitTests/Core/LayoutTests.cs b/UnitTests/Core/LayoutTests.cs index 71571d720..4bc75ace2 100644 --- a/UnitTests/Core/LayoutTests.cs +++ b/UnitTests/Core/LayoutTests.cs @@ -47,6 +47,56 @@ namespace Terminal.Gui.CoreTests { Assert.Throws (() => root.LayoutSubviews ()); } + [Fact] + public void LayoutSubviews_No_SuperView () + { + var root = new View (); + var first = new View () { Id = "first", X = 1, Y = 2, Height = 3, Width = 4 }; + root.Add (first); + + var second = new View () { Id = "second" }; + root.Add (second); + + second.X = Pos.Right (first) + 1; + + root.LayoutSubviews (); + + Assert.Equal (6, second.Frame.X); + } + + [Fact] + public void LayoutSubviews_RootHas_SuperView () + { + var top = new View (); + var root = new View (); + top.Add (root); + + var first = new View () { Id = "first", X = 1, Y = 2, Height = 3, Width = 4 }; + root.Add (first); + + var second = new View () { Id = "second" }; + root.Add (second); + + second.X = Pos.Right (first) + 1; + + root.LayoutSubviews (); + + Assert.Equal (6, second.Frame.X); + } + + + [Fact] + public void LayoutSubviews_ViewThatRefsSuperView_Throws () + { + var root = new View (); + var super = new View (); + root.Add (super); + var sub = new View (); + super.Add (sub); + super.Width = Dim.Width (sub); + Assert.Throws (() => root.LayoutSubviews ()); + } + [Fact, AutoInitShutdown] public void TrySetWidth_ForceValidatePosDim () {