From 4da20ace9ded35ded1f57dab095793a6b42ccf86 Mon Sep 17 00:00:00 2001 From: Tig Kindel Date: Wed, 3 Jan 2024 11:53:51 -0700 Subject: [PATCH] Merged v2_develop; updated API docs --- Terminal.Gui/View/Layout/ViewLayout.cs | 167 +++-- Terminal.Gui/View/View.cs | 2 +- UnitTests/View/Layout/AbsoluteLayoutTests.cs | 682 +++++++++---------- 3 files changed, 459 insertions(+), 392 deletions(-) diff --git a/Terminal.Gui/View/Layout/ViewLayout.cs b/Terminal.Gui/View/Layout/ViewLayout.cs index 0ca320c307..9ff5a363af 100644 --- a/Terminal.Gui/View/Layout/ViewLayout.cs +++ b/Terminal.Gui/View/Layout/ViewLayout.cs @@ -30,22 +30,31 @@ public partial class View { Rect _frame; /// - /// Gets or sets the frame for the view. The frame is relative to the 's . + /// Gets or sets location and size of the view. The frame is relative to the 's . /// - /// The frame. + /// The rectangle describing the location and size of the view, in coordinates relative to the . /// /// - /// Change the Frame when using the layout style to move or resize views. + /// Change the Frame when using the layout style to move or resize views. /// /// - /// Altering the Frame of a view will trigger the redrawing of the - /// view as well as the redrawing of the affected regions of the . + /// Altering the Frame will change to . + /// Additionally, , , , and will be set + /// to the values of the Frame (using and ). + /// + /// + /// Altering the Frame will eventually (when the view is next drawn) cause the + /// and methods to be called. /// /// public virtual Rect Frame { get => _frame; set { _frame = new Rect (value.X, value.Y, Math.Max (value.Width, 0), Math.Max (value.Height, 0)); + //X = _frame.X; + //Y = _frame.Y; + //Width = _frame.Width; + //Height = _frame.Height; if (IsInitialized || LayoutStyle == LayoutStyle.Absolute) { LayoutFrames (); TextFormatter.Size = GetTextFormatterSizeNeededForTextAndHotKey (); @@ -161,7 +170,7 @@ public Thickness GetFramesThickness () /// Helper to get the X and Y offset of the Bounds from the Frame. This is the sum of the Left and Top properties of /// , and . /// - public Point GetBoundsOffset () => new Point (Padding?.Thickness.GetInside (Padding.Frame).X ?? 0, Padding?.Thickness.GetInside (Padding.Frame).Y ?? 0); + public Point GetBoundsOffset () => new (Padding?.Thickness.GetInside (Padding.Frame).X ?? 0, Padding?.Thickness.GetInside (Padding.Frame).Y ?? 0); /// /// Creates the view's objects. This internal method is overridden by Frame to do nothing @@ -171,7 +180,9 @@ internal virtual void CreateFrames () { void ThicknessChangedHandler (object sender, EventArgs e) { - LayoutFrames (); + if (IsInitialized) { + LayoutFrames (); + } SetNeedsLayout (); SetNeedsDisplay (); } @@ -207,41 +218,74 @@ void ThicknessChangedHandler (object sender, EventArgs e) /// /// Controls how the View's is computed during . If the style is set to - /// , - /// LayoutSubviews does not change the . If the style is - /// the is updated using + /// , LayoutSubviews does not change the . + /// If the style is the is updated using /// the , , , and properties. /// + /// + /// + /// Setting this property to will cause to determine the + /// size and position of the view. and will be set to using . + /// + /// + /// Setting this property to will cause the view to use the method to + /// size and position of the view. If either of the and properties are `null` they will be set to using + /// the current value of . + /// If either of the and properties are `null` they will be set to using . + /// + /// /// The layout style. public LayoutStyle LayoutStyle { - get => _layoutStyle; + get { + return _layoutStyle; + //if ((X == null || X is Pos.PosAbsolute) && (Y == null || Y is Pos.PosAbsolute) && + //(Width == null || Width is Dim.DimAbsolute) && (Height == null || Height is Dim.DimAbsolute)) { + // return LayoutStyle.Absolute; + //} else { + // return LayoutStyle.Computed; + //} + } set { _layoutStyle = value; + //switch (_layoutStyle) { + //case LayoutStyle.Absolute: + // X = Frame.X; + // Y = Frame.Y; + // Width = Frame.Width; + // Height = Frame.Height; + // break; + + //case LayoutStyle.Computed: + // X ??= Frame.X; + // Y ??= Frame.Y; + // Width ??= Frame.Width; + // Height ??= Frame.Height; + // break; + //} SetNeedsLayout (); } } /// - /// The view's content area. - /// - /// SubViews are positioned relative to Bounds. - /// + /// The bounds represent the View-relative rectangle used for this view; the area inside of the view where subviews and content are presented. + /// + /// The rectangle describing the location and size of the area where the views' subviews and content are drawn. + /// /// - /// Drawing is clipped to Bounds ( clips drawing to Bounds.Size). + /// If is the value of Bounds is indeterminate until the + /// view has been initialized ( is true) and has been called. /// /// - /// Mouse events are reported relative to Bounds. + /// Updates to the Bounds updates , and has the same side effects as updating the . /// - /// - /// The view's content area. - /// /// - /// The of Bounds is always (0, 0). To obtain the offset of the Bounds from the Frame use - /// . + /// Altering the Bounds will eventually (when the view is next drawn) cause the + /// and methods to be called. /// /// - /// When using , Bounds is not valid until after the view has been initialized (after has been called and - /// has fired). Accessing this property before the view is initialized is considered an error./> + /// Because coordinates are relative to the upper-left corner of the , + /// the coordinates of the upper-left corner of the rectangle returned by this property are (0,0). + /// Use this property to obtain the size of the area of the view for tasks such as drawing the view's contents. /// /// public virtual Rect Bounds { @@ -280,12 +324,21 @@ Rect FrameGetInsideBounds () Pos _x, _y; /// - /// Gets or sets the X position for the view (the column). Only used if the is . + /// Gets or sets the X position for the view (the column). /// - /// The X Position. + /// The object representing the X position. /// /// - /// If is changing this property has no effect and its value is indeterminate. + /// If is the value is indeterminate until the + /// view has been initialized ( is true) and has been called. + /// + /// + /// Changing this property will eventually (when the view is next drawn) cause the and + /// methods to be called. + /// + /// + /// If is changing this property will cause the to be updated. If + /// the new value is not of type the will change to . /// /// /// is the same as Pos.Absolute(0). @@ -306,14 +359,22 @@ public Pos X { } } - /// - /// Gets or sets the Y position for the view (the row). Only used if the is . + /// Gets or sets the Y position for the view (the row). /// - /// The X Position. + /// The object representing the Y position. /// /// - /// If is changing this property has no effect and its value is indeterminate. + /// If is the value is indeterminate until the + /// view has been initialized ( is true) and has been called. + /// + /// + /// Changing this property will eventually (when the view is next drawn) cause the and + /// methods to be called. + /// + /// + /// If is changing this property will cause the to be updated. If + /// the new value is not of type the will change to . /// /// /// is the same as Pos.Absolute(0). @@ -333,19 +394,25 @@ public Pos Y { OnResizeNeeded (); } } + Dim _width, _height; /// - /// Gets or sets the width of the view. Only used when is . + /// Gets or sets the width of the view. /// - /// The width. + /// The object representing the width of the view (the number of columns). /// /// - /// If is changing this property - /// has no effect and its value is indeterminate. + /// If is the value is indeterminate until the + /// view has been initialized ( is true) and has been called. + /// + /// + /// Changing this property will eventually (when the view is next drawn) cause the + /// and methods to be called. /// /// - /// is the same as Dim.Fill (0). + /// If is changing this property will cause the to be updated. If + /// the new value is not of type the will change to . /// /// public Dim Width { @@ -372,16 +439,21 @@ public Dim Width { } /// - /// Gets or sets the height of the view. Only used when is . + /// Gets or sets the height of the view. /// - /// The width. + /// The object representing the height of the view (the number of rows). /// /// - /// If is changing this property - /// has no effect and its value is indeterminate. + /// If is the value is indeterminate until the + /// view has been initialized ( is true) and has been called. + /// + /// + /// Changing this property will eventually (when the view is next drawn) cause the + /// and methods to be called. /// /// - /// is the same as Dim.Fill (0). + /// If is changing this property will cause the to be updated. If + /// the new value is not of type the will change to . /// /// public Dim Height { @@ -658,7 +730,7 @@ int GetNewDimension (Dim d, int location, int dimension, int autosize) newDimension = d.Anchor (dimension); newDimension = AutoSize && autosize > newDimension ? autosize : newDimension; break; - + case Dim.DimFill: default: newDimension = Math.Max (d.Anchor (dimension - location), 0); @@ -803,7 +875,7 @@ internal void CollectAll (View from, ref HashSet nNodes, ref HashSet<(View // BUGBUG: This should really only work on initialized subviews foreach (var v in from.InternalSubviews /*.Where(v => v.IsInitialized)*/) { nNodes.Add (v); - if (v._layoutStyle != LayoutStyle.Computed) { + if (v.LayoutStyle != LayoutStyle.Computed) { continue; } CollectPos (v.X, v, ref nNodes, ref nEdges); @@ -896,7 +968,6 @@ internal virtual void LayoutFrames () Margin.Width = Frame.Size.Width; Margin.Height = Frame.Size.Height; Margin.SetNeedsLayout (); - Margin.LayoutSubviews (); Margin.SetNeedsDisplay (); } @@ -908,7 +979,6 @@ internal virtual void LayoutFrames () Border.Width = border.Size.Width; Border.Height = border.Size.Height; Border.SetNeedsLayout (); - Border.LayoutSubviews (); Border.SetNeedsDisplay (); } @@ -920,7 +990,6 @@ internal virtual void LayoutFrames () Padding.Width = padding.Size.Width; Padding.Height = padding.Size.Height; Padding.SetNeedsLayout (); - Padding.LayoutSubviews (); Padding.SetNeedsDisplay (); } } @@ -930,7 +999,13 @@ internal virtual void LayoutFrames () /// response to the container view or terminal resizing. /// /// + /// + /// The position and dimensions of the view are indeterminate until the view has been initialized. Therefore, + /// the behavior of this method is indeterminate if is . + /// + /// /// Raises the event) before it returns. + /// /// public virtual void LayoutSubviews () { diff --git a/Terminal.Gui/View/View.cs b/Terminal.Gui/View/View.cs index a22e60d948..77a8bca421 100644 --- a/Terminal.Gui/View/View.cs +++ b/Terminal.Gui/View/View.cs @@ -238,7 +238,7 @@ void SetInitialProperties (string text, Rect rect, LayoutStyle layoutStyle = Lay CreateFrames (); - LayoutFrames (); + //LayoutFrames (); } /// diff --git a/UnitTests/View/Layout/AbsoluteLayoutTests.cs b/UnitTests/View/Layout/AbsoluteLayoutTests.cs index d8e31af082..3b730266a9 100644 --- a/UnitTests/View/Layout/AbsoluteLayoutTests.cs +++ b/UnitTests/View/Layout/AbsoluteLayoutTests.cs @@ -1,350 +1,342 @@ -using System.Text; -using System; -using System.Collections.Generic; -using System.Xml.Linq; -using Xunit; +using Xunit; using Xunit.Abstractions; //using GraphViewTests = Terminal.Gui.Views.GraphViewTests; // Alias Console to MockConsole so we don't accidentally use Console -using Console = Terminal.Gui.FakeConsole; - -namespace Terminal.Gui.ViewTests { - public class AbsoluteLayoutTests { - readonly ITestOutputHelper output; - - public AbsoluteLayoutTests (ITestOutputHelper output) - { - this.output = output; - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Constructor () - { - var frame = new Rect (1, 2, 3, 4); - var v = new View (frame); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - Assert.Equal (frame, v.Frame); - Assert.Equal (new Rect(0, 0, frame.Width, frame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout - Assert.Null (v.X); - Assert.Null (v.Y); - Assert.Null (v.Height); - Assert.Null (v.Width); - v.Dispose (); - - v = new View (frame, "v"); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - Assert.Equal (frame, v.Frame); - Assert.Equal (new Rect (0, 0, frame.Width, frame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout - Assert.Null (v.X); - Assert.Null (v.Y); - Assert.Null (v.Height); - Assert.Null (v.Width); - v.Dispose (); - - v = new View (frame.X, frame.Y, "v"); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - // BUGBUG: v2 - I think the default size should be 0,0 - Assert.Equal (new Rect(frame.X, frame.Y, 1, 1), v.Frame); - Assert.Equal (new Rect (0, 0, 1, 1), v.Bounds); // With Absolute Bounds *is* deterministic before Layout - Assert.Null (v.X); - Assert.Null (v.Y); - Assert.Null (v.Height); - Assert.Null (v.Width); - v.Dispose (); - - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Change_Frame () - { - var frame = new Rect (1, 2, 3, 4); - var newFrame = new Rect (1, 2, 30, 40); - - var v = new View (frame); - v.Frame = newFrame; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - Assert.Equal (newFrame, v.Frame); - Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout - Assert.Null (v.X); - Assert.Null (v.Y); - Assert.Null (v.Height); - Assert.Null (v.Width); - v.Dispose (); - - v = new View (frame.X, frame.Y, "v"); - v.Frame = newFrame; - Assert.Equal (newFrame, v.Frame); - Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout - Assert.Null (v.X); - Assert.Null (v.Y); - Assert.Null (v.Height); - Assert.Null (v.Width); - v.Dispose (); - - newFrame = new Rect (10, 20, 30, 40); - v = new View (frame); - v.Frame = newFrame; - Assert.Equal (newFrame, v.Frame); - Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout - Assert.Null (v.X); - Assert.Null (v.Y); - Assert.Null (v.Height); - Assert.Null (v.Width); - v.Dispose (); - - v = new View (frame.X, frame.Y, "v"); - v.Frame = newFrame; - Assert.Equal (newFrame, v.Frame); - Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout - Assert.Null (v.X); - Assert.Null (v.Y); - Assert.Null (v.Height); - Assert.Null (v.Width); - v.Dispose (); - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Change_Height_or_Width_Absolute () - { - var frame = new Rect (1, 2, 3, 4); - var newFrame = new Rect (1, 2, 30, 40); - - var v = new View (frame); - v.Height = newFrame.Height; - v.Width = newFrame.Width; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - Assert.Equal (newFrame, v.Frame); - Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout - Assert.Null (v.X); - Assert.Null (v.Y); - Assert.Equal ($"Absolute({newFrame.Height})", v.Height.ToString()); - Assert.Equal ($"Absolute({newFrame.Width})", v.Width.ToString ()); - v.Dispose (); - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Change_Height_or_Width_NotAbsolute () - { - var v = new View (Rect.Empty); - v.Height = Dim.Fill (); - v.Width = Dim.Fill (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - v.Dispose (); - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Change_Height_or_Width_Null () - { - var v = new View (Rect.Empty); - v.Height = null; - v.Width = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - v.Dispose (); - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Change_X_or_Y_Absolute () - { - var frame = new Rect (1, 2, 3, 4); - var newFrame = new Rect (10, 20, 3, 4); - - var v = new View (frame); - v.X = newFrame.X; - v.Y = newFrame.Y; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - Assert.Equal (newFrame, v.Frame); - Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout - Assert.Equal ($"Absolute({newFrame.X})", v.X.ToString ()); - Assert.Equal ($"Absolute({newFrame.Y})", v.Y.ToString ()); - Assert.Null (v.Height); - Assert.Null (v.Width); - v.Dispose (); - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Change_X_or_Y_NotAbsolute () - { - var v = new View (Rect.Empty); - v.X = Pos.Center (); - v.Y = Pos.Center (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - v.Dispose (); - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Change_X_or_Y_Null () - { - var v = new View (Rect.Empty); - v.X = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - v.Dispose (); - - v = new View (Rect.Empty); - v.X = Pos.Center (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - - v.X = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - v.Dispose (); - - v = new View (Rect.Empty); - v.Y = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - v.Dispose (); - - v = new View (Rect.Empty); - v.Y = Pos.Center (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - - v.Y = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - v.Dispose (); - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Change_X_Y_Height_Width_Absolute () - { - var v = new View (Rect.Empty); - v.X = 1; - v.Y = 2; - v.Height = 3; - v.Width = 4; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - v.Dispose (); - - v = new View (Rect.Empty); - v.X = Pos.Center (); - v.Y = Pos.Center (); - v.Width = Dim.Fill (); - v.Height = Dim.Fill (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - - // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? - v.X = null; - v.Y = null; - v.Height = null; - v.Width = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? - v.Dispose (); - - v = new View (Rect.Empty); - v.X = Pos.Center (); - v.Y = Pos.Center (); - v.Width = Dim.Fill (); - v.Height = Dim.Fill (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - - // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? - v.X = 1; - v.Y = null; - v.Height = null; - v.Width = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? - v.Dispose (); - - v = new View (Rect.Empty); - v.X = Pos.Center (); - v.Y = Pos.Center (); - v.Width = Dim.Fill (); - v.Height = Dim.Fill (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - - // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? - v.X = null; - v.Y = 2; - v.Height = null; - v.Width = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? - v.Dispose (); - - v = new View (Rect.Empty); - v.X = Pos.Center (); - v.Y = Pos.Center (); - v.Width = Dim.Fill (); - v.Height = Dim.Fill (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - - // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? - v.X = null; - v.Y = null; - v.Height = 3; - v.Width = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? - v.Dispose (); - - v = new View (Rect.Empty); - v.X = Pos.Center (); - v.Y = Pos.Center (); - v.Width = Dim.Fill (); - v.Height = Dim.Fill (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - - // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? - v.X = null; - v.Y = null; - v.Height = null; - v.Width = 4; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? - v.Dispose (); - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Change_X_Y_Height_Width_Null () - { - var v = new View (Rect.Empty); - v.X = null; - v.Y = null; - v.Height = null; - v.Width = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); - - v.Dispose (); - v = new View (Rect.Empty); - v.X = Pos.Center (); - v.Y = Pos.Center (); - v.Width = Dim.Fill (); - v.Height = Dim.Fill (); - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle - - // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? - v.X = null; - v.Y = null; - v.Height = null; - v.Width = null; - Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? - v.Dispose (); - } - - [Fact, TestRespondersDisposed] - public void AbsoluteLayout_Layout () - { - var superRect = new Rect (0, 0, 100, 100); - var super = new View (superRect, "super"); - Assert.True (super.LayoutStyle == LayoutStyle.Absolute); - var v1 = new View () { - X = 0, - Y = 0, - Width = 10, - Height = 10 - }; - // BUGBUG: v2 - This should be LayoutStyle.Absolute - Assert.True (v1.LayoutStyle == LayoutStyle.Computed); - - var v2 = new View () { - X = 10, - Y = 10, - Width = 10, - Height = 10 - }; - // BUGBUG: v2 - This should be LayoutStyle.Absolute - Assert.True (v1.LayoutStyle == LayoutStyle.Computed); - - super.Add (v1, v2); - super.LayoutSubviews (); - Assert.Equal (new Rect (0, 0, 10, 10), v1.Frame); - Assert.Equal (new Rect (10, 10, 10, 10), v2.Frame); - super.Dispose (); - } + +namespace Terminal.Gui.ViewTests; + +public class AbsoluteLayoutTests { + readonly ITestOutputHelper _output; + + public AbsoluteLayoutTests (ITestOutputHelper output) => this._output = output; + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Constructor () + { + var frame = new Rect (1, 2, 3, 4); + var v = new View (frame); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + Assert.Equal (frame, v.Frame); + Assert.Equal (new Rect (0, 0, frame.Width, frame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout + Assert.Null (v.X); + Assert.Null (v.Y); + Assert.Null (v.Height); + Assert.Null (v.Width); + v.Dispose (); + + v = new View (frame, "v"); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + Assert.Equal (frame, v.Frame); + Assert.Equal (new Rect (0, 0, frame.Width, frame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout + Assert.Null (v.X); + Assert.Null (v.Y); + Assert.Null (v.Height); + Assert.Null (v.Width); + v.Dispose (); + + v = new View (frame.X, frame.Y, "v"); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + // BUGBUG: v2 - I think the default size should be 0,0 + Assert.Equal (new Rect (frame.X, frame.Y, 1, 1), v.Frame); + Assert.Equal (new Rect (0, 0, 1, 1), v.Bounds); // With Absolute Bounds *is* deterministic before Layout + Assert.Null (v.X); + Assert.Null (v.Y); + Assert.Null (v.Height); + Assert.Null (v.Width); + v.Dispose (); + + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Change_Frame () + { + var frame = new Rect (1, 2, 3, 4); + var newFrame = new Rect (1, 2, 30, 40); + + var v = new View (frame); + v.Frame = newFrame; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + Assert.Equal (newFrame, v.Frame); + Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout + Assert.Null (v.X); + Assert.Null (v.Y); + Assert.Null (v.Height); + Assert.Null (v.Width); + v.Dispose (); + + v = new View (frame.X, frame.Y, "v"); + v.Frame = newFrame; + Assert.Equal (newFrame, v.Frame); + Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout + Assert.Null (v.X); + Assert.Null (v.Y); + Assert.Null (v.Height); + Assert.Null (v.Width); + v.Dispose (); + + newFrame = new Rect (10, 20, 30, 40); + v = new View (frame); + v.Frame = newFrame; + Assert.Equal (newFrame, v.Frame); + Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout + Assert.Null (v.X); + Assert.Null (v.Y); + Assert.Null (v.Height); + Assert.Null (v.Width); + v.Dispose (); + + v = new View (frame.X, frame.Y, "v"); + v.Frame = newFrame; + Assert.Equal (newFrame, v.Frame); + Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout + Assert.Null (v.X); + Assert.Null (v.Y); + Assert.Null (v.Height); + Assert.Null (v.Width); + v.Dispose (); + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Change_Height_or_Width_Absolute () + { + var frame = new Rect (1, 2, 3, 4); + var newFrame = new Rect (1, 2, 30, 40); + + var v = new View (frame); + v.Height = newFrame.Height; + v.Width = newFrame.Width; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + Assert.Equal (newFrame, v.Frame); + Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout + Assert.Null (v.X); + Assert.Null (v.Y); + Assert.Equal ($"Absolute({newFrame.Height})", v.Height.ToString ()); + Assert.Equal ($"Absolute({newFrame.Width})", v.Width.ToString ()); + v.Dispose (); + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Change_Height_or_Width_NotAbsolute () + { + var v = new View (Rect.Empty); + v.Height = Dim.Fill (); + v.Width = Dim.Fill (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + v.Dispose (); + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Change_Height_or_Width_Null () + { + var v = new View (Rect.Empty); + v.Height = null; + v.Width = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + v.Dispose (); + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Change_X_or_Y_Absolute () + { + var frame = new Rect (1, 2, 3, 4); + var newFrame = new Rect (10, 20, 3, 4); + + var v = new View (frame); + v.X = newFrame.X; + v.Y = newFrame.Y; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + Assert.Equal (newFrame, v.Frame); + Assert.Equal (new Rect (0, 0, newFrame.Width, newFrame.Height), v.Bounds); // With Absolute Bounds *is* deterministic before Layout + Assert.Equal ($"Absolute({newFrame.X})", v.X.ToString ()); + Assert.Equal ($"Absolute({newFrame.Y})", v.Y.ToString ()); + Assert.Null (v.Height); + Assert.Null (v.Width); + v.Dispose (); + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Change_X_or_Y_NotAbsolute () + { + var v = new View (Rect.Empty); + v.X = Pos.Center (); + v.Y = Pos.Center (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + v.Dispose (); + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Change_X_or_Y_Null () + { + var v = new View (Rect.Empty); + v.X = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + v.Dispose (); + + v = new View (Rect.Empty); + v.X = Pos.Center (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + + v.X = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + v.Dispose (); + + v = new View (Rect.Empty); + v.Y = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + v.Dispose (); + + v = new View (Rect.Empty); + v.Y = Pos.Center (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + + v.Y = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + v.Dispose (); + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Change_X_Y_Height_Width_Absolute () + { + var v = new View (Rect.Empty); + v.X = 1; + v.Y = 2; + v.Height = 3; + v.Width = 4; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + v.Dispose (); + + v = new View (Rect.Empty); + v.X = Pos.Center (); + v.Y = Pos.Center (); + v.Width = Dim.Fill (); + v.Height = Dim.Fill (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + + // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? + v.X = null; + v.Y = null; + v.Height = null; + v.Width = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? + v.Dispose (); + + v = new View (Rect.Empty); + v.X = Pos.Center (); + v.Y = Pos.Center (); + v.Width = Dim.Fill (); + v.Height = Dim.Fill (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + + // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? + v.X = 1; + v.Y = null; + v.Height = null; + v.Width = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? + v.Dispose (); + + v = new View (Rect.Empty); + v.X = Pos.Center (); + v.Y = Pos.Center (); + v.Width = Dim.Fill (); + v.Height = Dim.Fill (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + + // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? + v.X = null; + v.Y = 2; + v.Height = null; + v.Width = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? + v.Dispose (); + + v = new View (Rect.Empty); + v.X = Pos.Center (); + v.Y = Pos.Center (); + v.Width = Dim.Fill (); + v.Height = Dim.Fill (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + + // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? + v.X = null; + v.Y = null; + v.Height = 3; + v.Width = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? + v.Dispose (); + + v = new View (Rect.Empty); + v.X = Pos.Center (); + v.Y = Pos.Center (); + v.Width = Dim.Fill (); + v.Height = Dim.Fill (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + + // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? + v.X = null; + v.Y = null; + v.Height = null; + v.Width = 4; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? + v.Dispose (); + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Change_X_Y_Height_Width_Null () + { + var v = new View (Rect.Empty); + v.X = null; + v.Y = null; + v.Height = null; + v.Width = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); + + v.Dispose (); + v = new View (Rect.Empty); + v.X = Pos.Center (); + v.Y = Pos.Center (); + v.Width = Dim.Fill (); + v.Height = Dim.Fill (); + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // BUGBUG: v2 - Changing the Height or Width should change the LayoutStyle + + // BUGBUG: v2 - If all of X, Y, Width, and Height are null or Absolute(n), isn't that the same as LayoutStyle.Absoulte? + v.X = null; + v.Y = null; + v.Height = null; + v.Width = null; + Assert.True (v.LayoutStyle == LayoutStyle.Absolute); // We never automatically change to Absolute from Computed?? + v.Dispose (); + } + + [Fact] [TestRespondersDisposed] + public void AbsoluteLayout_Layout () + { + var superRect = new Rect (0, 0, 100, 100); + var super = new View (superRect, "super"); + Assert.True (super.LayoutStyle == LayoutStyle.Absolute); + var v1 = new View () { + X = 0, + Y = 0, + Width = 10, + Height = 10 + }; + // BUGBUG: v2 - This should be LayoutStyle.Absolute + Assert.True (v1.LayoutStyle == LayoutStyle.Computed); + + var v2 = new View () { + X = 10, + Y = 10, + Width = 10, + Height = 10 + }; + // BUGBUG: v2 - This should be LayoutStyle.Absolute + Assert.True (v1.LayoutStyle == LayoutStyle.Computed); + + super.Add (v1, v2); + super.LayoutSubviews (); + Assert.Equal (new Rect (0, 0, 10, 10), v1.Frame); + Assert.Equal (new Rect (10, 10, 10, 10), v2.Frame); + super.Dispose (); } -} +} \ No newline at end of file