diff --git a/Terminal.Gui/Core/TextFormatter.cs b/Terminal.Gui/Core/TextFormatter.cs index a297d1143..9a20bdaf5 100644 --- a/Terminal.Gui/Core/TextFormatter.cs +++ b/Terminal.Gui/Core/TextFormatter.cs @@ -141,6 +141,14 @@ namespace Terminal.Gui { } } + /// + /// Used by to resize the view's with the . + /// Setting to true only work if the and are null or + /// values and doesn't work with layout, + /// to avoid breaking the and settings. + /// + public bool AutoSize { get; set; } + // TODO: Add Vertical Text Alignment /// /// Controls the horizontal text-alignment property. @@ -306,8 +314,14 @@ namespace Terminal.Gui { if (IsVerticalDirection (textDirection)) { lines = Format (shown_text, Size.Height, textVerticalAlignment == VerticalTextAlignment.Justified, Size.Width > 1); + if (!AutoSize && lines.Count > Size.Width) { + lines.RemoveRange (Size.Width, lines.Count - Size.Width); + } } else { lines = Format (shown_text, Size.Width, textAlignment == TextAlignment.Justified, Size.Height > 1); + if (!AutoSize && lines.Count > Size.Height) { + lines.RemoveRange (Size.Height, lines.Count - Size.Height); + } } NeedsFormat = false; @@ -675,40 +689,77 @@ namespace Terminal.Gui { /// The x location of the rectangle /// The y location of the rectangle /// The text to measure + /// The text direction. /// - public static Rect CalcRect (int x, int y, ustring text) + public static Rect CalcRect (int x, int y, ustring text, TextDirection direction = TextDirection.LeftRight_TopBottom) { if (ustring.IsNullOrEmpty (text)) { return new Rect (new Point (x, y), Size.Empty); } - int mw = 0; - int ml = 1; + int w, h; - int cols = 0; - foreach (var rune in text) { - if (rune == '\n') { - ml++; - if (cols > mw) { - mw = cols; - } - cols = 0; - } else { - if (rune != '\r') { - cols++; - var rw = Rune.ColumnWidth (rune); - if (rw > 0) { - rw--; + if (IsHorizontalDirection (direction)) { + int mw = 0; + int ml = 1; + + int cols = 0; + foreach (var rune in text) { + if (rune == '\n') { + ml++; + if (cols > mw) { + mw = cols; + } + cols = 0; + } else { + if (rune != '\r') { + cols++; + var rw = Rune.ColumnWidth (rune); + if (rw > 0) { + rw--; + } + cols += rw; } - cols += rw; } } - } - if (cols > mw) { - mw = cols; + if (cols > mw) { + mw = cols; + } + w = mw; + h = ml; + } else { + int vw = 0; + int vh = 0; + + int rows = 0; + foreach (var rune in text) { + if (rune == '\n') { + vw++; + if (rows > vh) { + vh = rows; + } + rows = 0; + } else { + if (rune != '\r') { + rows++; + var rw = Rune.ColumnWidth (rune); + if (rw < 0) { + rw++; + } + if (rw > vw) { + vw = rw; + } + } + } + } + if (rows > vh) { + vh = rows; + } + w = vw; + h = vh; } - return new Rect (x, y, mw, ml); + return new Rect (x, y, w, h); } /// @@ -932,6 +983,7 @@ namespace Terminal.Gui { var current = start; for (var idx = start; idx < start + size; idx++) { if (idx < 0) { + current++; continue; } var rune = (Rune)' '; diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index 338431dd8..0d466bbde 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -478,6 +478,10 @@ namespace Terminal.Gui { x = value; SetNeedsLayout (); + if (x is Pos.PosAbsolute) { + frame = new Rect (x.Anchor (0), frame.Y, frame.Width, frame.Height); + } + textFormatter.Size = frame.Size; SetNeedsDisplay (frame); } } @@ -498,6 +502,10 @@ namespace Terminal.Gui { y = value; SetNeedsLayout (); + if (y is Pos.PosAbsolute) { + frame = new Rect (frame.X, y.Anchor (0), frame.Width, frame.Height); + } + textFormatter.Size = frame.Size; SetNeedsDisplay (frame); } } @@ -520,6 +528,10 @@ namespace Terminal.Gui { width = value; SetNeedsLayout (); + if (width is Dim.DimAbsolute) { + frame = new Rect (frame.X, frame.Y, width.Anchor (0), frame.Height); + } + textFormatter.Size = frame.Size; SetNeedsDisplay (frame); } } @@ -538,6 +550,10 @@ namespace Terminal.Gui { height = value; SetNeedsLayout (); + if (height is Dim.DimAbsolute) { + frame = new Rect (frame.X, frame.Y, frame.Width, height.Anchor (0)); + } + textFormatter.Size = frame.Size; SetNeedsDisplay (frame); } } @@ -572,7 +588,7 @@ namespace Terminal.Gui { /// public View (Rect frame) { - Initialize (ustring.Empty, frame, LayoutStyle.Absolute); + Initialize (ustring.Empty, frame, LayoutStyle.Absolute, TextDirection.LeftRight_TopBottom); } /// @@ -593,7 +609,7 @@ namespace Terminal.Gui { /// Use , , , and properties to dynamically control the size and location of the view. /// /// - public View () : this (text: string.Empty) { } + public View () : this (text: string.Empty, direction: TextDirection.LeftRight_TopBottom) { } /// /// Initializes a new instance of using layout. @@ -647,15 +663,17 @@ namespace Terminal.Gui { /// /// /// text to initialize the property with. - public View (ustring text) + /// The text direction. + public View (ustring text, TextDirection direction = TextDirection.LeftRight_TopBottom) { - Initialize (text, Rect.Empty); + Initialize (text, Rect.Empty, LayoutStyle.Computed, direction); } - void Initialize (ustring text, Rect rect, LayoutStyle layoutStyle = LayoutStyle.Computed) + void Initialize (ustring text, Rect rect, LayoutStyle layoutStyle = LayoutStyle.Computed, + TextDirection direction = TextDirection.LeftRight_TopBottom) { textFormatter = new TextFormatter (); - Text = text; + TextDirection = direction; shortcutHelper = new ShortcutHelper (); @@ -666,7 +684,7 @@ namespace Terminal.Gui { // BUGBUG: CalcRect doesn't account for line wrapping Rect r; if (rect.IsEmpty) { - r = TextFormatter.CalcRect (0, 0, text); + r = TextFormatter.CalcRect (0, 0, text, direction); } else { r = rect; } @@ -676,6 +694,8 @@ namespace Terminal.Gui { Height = r.Height; Frame = r; + + Text = text; } /// @@ -1969,6 +1989,9 @@ namespace Terminal.Gui { set { textFormatter.Text = value; ResizeView (autoSize); + if (textFormatter.Size != Bounds.Size) { + textFormatter.Size = Bounds.Size; + } SetNeedsLayout (); SetNeedsDisplay (); } @@ -1984,8 +2007,10 @@ namespace Terminal.Gui { get => autoSize; set { var v = ResizeView (value); + textFormatter.AutoSize = v; if (autoSize != v) { autoSize = v; + textFormatter.NeedsFormat = true; SetNeedsLayout (); SetNeedsDisplay (); } @@ -2023,8 +2048,17 @@ namespace Terminal.Gui { public virtual TextDirection TextDirection { get => textFormatter.Direction; set { - textFormatter.Direction = value; - SetNeedsDisplay (); + if (textFormatter.Direction != value) { + textFormatter.Direction = value; + if (IsInitialized && AutoSize) { + ResizeView (true); + } else if (IsInitialized) { + var b = new Rect (Bounds.X, Bounds.Y, Bounds.Height, Bounds.Width); + SetWidthHeight (b); + } + textFormatter.Size = Bounds.Size; + SetNeedsDisplay (); + } } } @@ -2045,27 +2079,38 @@ namespace Terminal.Gui { bool ResizeView (bool autoSize) { - var aSize = autoSize; - if (textFormatter.Size != Bounds.Size && (((width == null || width is Dim.DimAbsolute) && (Bounds.Width == 0 - || autoSize && Bounds.Width != textFormatter.Size.Width)) - || ((height == null || height is Dim.DimAbsolute) && (Bounds.Height == 0 - || autoSize && Bounds.Height != textFormatter.Size.Height)))) { - Bounds = new Rect (Bounds.X, Bounds.Y, textFormatter.Size.Width, textFormatter.Size.Height); - if (width == null) { - width = Bounds.Width; - } else if (width is Dim.DimAbsolute) { - width = Math.Max (Bounds.Width, height.Anchor (Bounds.Width)); - } else { - aSize = false; - } - if (height == null) { - height = Bounds.Height; - } else if (height is Dim.DimAbsolute) { - height = Math.Max (Bounds.Height, height.Anchor (Bounds.Height)); - } else { - aSize = false; - } + if (!autoSize) { + return false; } + + var aSize = autoSize; + Rect nBounds = TextFormatter.CalcRect (Bounds.X, Bounds.Y, Text, textFormatter.Direction); + + if ((textFormatter.Size != Bounds.Size || textFormatter.Size != nBounds.Size) + && (((width == null || width is Dim.DimAbsolute) && (Bounds.Width == 0 + || autoSize && Bounds.Width != nBounds.Width)) + || ((height == null || height is Dim.DimAbsolute) && (Bounds.Height == 0 + || autoSize && Bounds.Height != nBounds.Height)))) { + aSize = SetWidthHeight (nBounds); + } + return aSize; + } + + bool SetWidthHeight (Rect nBounds) + { + bool aSize; + var canSizeW = SetWidth (nBounds.Width, out int rW); + var canSizeH = SetHeight (nBounds.Height, out int rH); + if (canSizeW && canSizeH) { + aSize = true; + Bounds = nBounds; + width = rW; + height = rH; + textFormatter.Size = Bounds.Size; + } else { + aSize = false; + } + return aSize; } diff --git a/Terminal.Gui/Views/Label.cs b/Terminal.Gui/Views/Label.cs index 39863fccb..69f7e825e 100644 --- a/Terminal.Gui/Views/Label.cs +++ b/Terminal.Gui/Views/Label.cs @@ -13,7 +13,8 @@ using NStack; namespace Terminal.Gui { /// - /// The Label displays a string at a given position and supports multiple lines separted by newline characters. Multi-line Labels support word wrap. + /// The Label displays a string at a given position and supports multiple lines separated by newline characters. + /// Multi-line Labels support word wrap. /// /// /// The view is functionality identical to and is included for API backwards compatibility. @@ -44,6 +45,12 @@ namespace Terminal.Gui { { } + /// + public Label (ustring text, TextDirection direction) + : base (text, direction) + { + } + /// /// Clicked , raised when the user clicks the primary mouse button within the Bounds of this /// or if the user presses the action key while this view is focused. (TODO: IsDefault) @@ -84,7 +91,6 @@ namespace Terminal.Gui { if (MouseEvent (mouseEvent)) return true; - if (mouseEvent.Flags == MouseFlags.Button1Clicked) { if (!HasFocus && SuperView != null) { SetFocus (); diff --git a/UICatalog/Scenarios/AutoSizeAndDirectionText.cs b/UICatalog/Scenarios/AutoSizeAndDirectionText.cs new file mode 100644 index 000000000..50e0ba077 --- /dev/null +++ b/UICatalog/Scenarios/AutoSizeAndDirectionText.cs @@ -0,0 +1,65 @@ +using Terminal.Gui; + +namespace UICatalog { + [ScenarioMetadata (Name: "AutoSize and Direction Text", Description: "Demonstrates the text auto-size and direction manipulation.")] + [ScenarioCategory ("Text")] + class AutoSizeAndDirectionText : Scenario { + public override void Setup () + { + var text = "Hello World"; + var color = Colors.Dialog; + + var labelH = new Label (text, TextDirection.LeftRight_TopBottom) { + X = 1, + Y = 1, + ColorScheme = color + }; + Win.Add (labelH); + + var labelV = new Label (text, TextDirection.TopBottom_LeftRight) { + X = 70, + Y = 1, + ColorScheme = color + }; + Win.Add (labelV); + + var editText = new TextView () { + X = Pos.Center (), + Y = Pos.Center (), + Width = 20, + Height = 5, + ColorScheme = color, + Text = text + }; + + editText.SetFocus (); + + Win.Add (editText); + + var ckbDirection = new CheckBox ("Toggle Direction") { + X = Pos.Center (), + Y = Pos.Center () + 3 + }; + ckbDirection.Toggled += (_) => { + if (labelH.TextDirection == TextDirection.LeftRight_TopBottom) { + labelH.TextDirection = TextDirection.TopBottom_LeftRight; + labelV.TextDirection = TextDirection.LeftRight_TopBottom; + } else { + labelH.TextDirection = TextDirection.LeftRight_TopBottom; + labelV.TextDirection = TextDirection.TopBottom_LeftRight; + } + }; + Win.Add (ckbDirection); + + var ckbAutoSize = new CheckBox ("Auto Size") { + X = Pos.Center (), + Y = Pos.Center () + 5 + }; + ckbAutoSize.Toggled += (_) => labelH.AutoSize = labelV.AutoSize = ckbAutoSize.Checked; + Win.Add (ckbAutoSize); + + Win.KeyUp += (_) => + labelH.Text = labelV.Text = text = editText.Text.ToString (); + } + } +} \ No newline at end of file diff --git a/UICatalog/Scenarios/Dialogs.cs b/UICatalog/Scenarios/Dialogs.cs index 31907cbac..8dcdeb693 100644 --- a/UICatalog/Scenarios/Dialogs.cs +++ b/UICatalog/Scenarios/Dialogs.cs @@ -13,9 +13,9 @@ namespace UICatalog { public override void Setup () { var frame = new FrameView ("Dialog Options") { - X = Pos.Center(), + X = Pos.Center (), Y = 1, - Width = Dim.Percent(75), + Width = Dim.Percent (75), Height = 10 }; Win.Add (frame); @@ -72,7 +72,7 @@ namespace UICatalog { var titleEdit = new TextField ("Title") { X = Pos.Right (label) + 1, Y = Pos.Top (label), - Width = Dim.Fill(), + Width = Dim.Fill (), Height = 1 }; frame.Add (titleEdit); @@ -93,8 +93,13 @@ namespace UICatalog { }; frame.Add (numButtonsEdit); - frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) - + Dim.Height (numButtonsEdit) + 2; + void Top_Loaded () + { + frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + + Dim.Height (numButtonsEdit) + 2; + Top.Loaded -= Top_Loaded; + } + Top.Loaded += Top_Loaded; label = new Label ("Button Pressed:") { X = Pos.Center (), @@ -113,7 +118,7 @@ namespace UICatalog { //var btnText = new [] { "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine" }; var showDialogButton = new Button ("Show Dialog") { - X = Pos.Center(), + X = Pos.Center (), Y = Pos.Bottom (frame) + 2, IsDefault = true, }; @@ -129,7 +134,7 @@ namespace UICatalog { var buttonId = i; //var button = new Button (btnText [buttonId % 10], // is_default: buttonId == 0); - var button = new Button (NumberToWords.Convert(buttonId), + var button = new Button (NumberToWords.Convert (buttonId), is_default: buttonId == 0); button.Clicked += () => { clicked = buttonId; diff --git a/UICatalog/Scenarios/Keys.cs b/UICatalog/Scenarios/Keys.cs index e6ec5a98b..debc27c3e 100644 --- a/UICatalog/Scenarios/Keys.cs +++ b/UICatalog/Scenarios/Keys.cs @@ -87,9 +87,9 @@ namespace UICatalog { var labelKeypress = new Label ("") { X = Pos.Left (edit), Y = Pos.Top (keyPressedLabel), - Width = 20, TextAlignment = Terminal.Gui.TextAlignment.Centered, ColorScheme = Colors.Error, + AutoSize = true }; Win.Add (labelKeypress); diff --git a/UICatalog/Scenarios/MessageBoxes.cs b/UICatalog/Scenarios/MessageBoxes.cs index a157e6d1b..38036ec82 100644 --- a/UICatalog/Scenarios/MessageBoxes.cs +++ b/UICatalog/Scenarios/MessageBoxes.cs @@ -140,8 +140,13 @@ namespace UICatalog { }; frame.Add (styleRadioGroup); - frame.Height = Dim.Height (widthEdit) + Dim.Height (heightEdit) + Dim.Height (titleEdit) + Dim.Height (messageEdit) + 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; + Top.Loaded -= Top_Loaded; + } + Top.Loaded += Top_Loaded; label = new Label ("Button Pressed:") { X = Pos.Center (), diff --git a/UICatalog/Scenarios/Scrolling.cs b/UICatalog/Scenarios/Scrolling.cs index 79ee89ad5..f334eed53 100644 --- a/UICatalog/Scenarios/Scrolling.cs +++ b/UICatalog/Scenarios/Scrolling.cs @@ -129,6 +129,7 @@ namespace UICatalog { X = 0, Y = 0, Width = Dim.Fill (), // FIXED: I don't think this should be needed; DimFill() should respect container's frame. X does. + Height = 2, ColorScheme = Colors.Error }; scrollView.Add (horizontalRuler); @@ -143,12 +144,13 @@ namespace UICatalog { }; scrollView.Add (verticalRuler); - void Top_Loaded() { + void Top_Loaded () + { horizontalRuler.Text = rule.Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)] + "\n" + "| ".Repeat ((int)Math.Ceiling ((double)(horizontalRuler.Bounds.Width) / (double)rule.Length)) [0..(horizontalRuler.Bounds.Width)]; verticalRuler.Text = vrule.Repeat ((int)Math.Ceiling ((double)(verticalRuler.Bounds.Height * 2) / (double)rule.Length)) [0..(verticalRuler.Bounds.Height * 2)]; Top.Loaded -= Top_Loaded; - }; + } Top.Loaded += Top_Loaded; var pressMeButton = new Button ("Press me!") { @@ -204,8 +206,8 @@ namespace UICatalog { scrollView.Add (anchorButton); var hCheckBox = new CheckBox ("Horizontal Scrollbar", scrollView.ShowHorizontalScrollIndicator) { - X = Pos.X(scrollView), - Y = Pos.Bottom(scrollView) + 1, + X = Pos.X (scrollView), + Y = Pos.Bottom (scrollView) + 1, }; Win.Add (hCheckBox); @@ -273,7 +275,7 @@ namespace UICatalog { int count = 0; var mousePos = new Label ("Mouse: "); - mousePos.X = Pos.Right(scrollView) + 1; + mousePos.X = Pos.Right (scrollView) + 1; mousePos.Y = Pos.AnchorEnd (1); mousePos.Width = 50; Application.RootMouseEvent += delegate (MouseEvent me) { diff --git a/UnitTests/RectTests.cs b/UnitTests/RectTests.cs index 6a61085ac..3b18cd3d7 100644 --- a/UnitTests/RectTests.cs +++ b/UnitTests/RectTests.cs @@ -29,7 +29,6 @@ namespace Terminal.Gui.Types { action = () => new Rect (1, 2, -3, -4); ex = Assert.Throws (action); Assert.Equal ("Width must be greater or equal to 0.", ex.Message); - } [Fact] @@ -110,5 +109,43 @@ namespace Terminal.Gui.Types { rect2 = new Rect (-1, 2, 3, 4); Assert.NotEqual (rect1, rect2); } + + [Fact] + public void Positive_X_Y_Positions () + { + var rect = new Rect (10, 5, 100, 50); + int yCount = 0, xCount = 0, yxCount = 0; + + for (int line = rect.Y; line < rect.Y + rect.Height; line++) { + yCount++; + xCount = 0; + for (int col = rect.X; col < rect.X + rect.Width; col++) { + xCount++; + yxCount++; + } + } + Assert.Equal (yCount, rect.Height); + Assert.Equal (xCount, rect.Width); + Assert.Equal (yxCount, rect.Height * rect.Width); + } + + [Fact] + public void Negative_X_Y_Positions () + { + var rect = new Rect (-10, -5, 100, 50); + int yCount = 0, xCount = 0, yxCount = 0; + + for (int line = rect.Y; line < rect.Y + rect.Height; line++) { + yCount++; + xCount = 0; + for (int col = rect.X; col < rect.X + rect.Width; col++) { + xCount++; + yxCount++; + } + } + Assert.Equal (yCount, rect.Height); + Assert.Equal (xCount, rect.Width); + Assert.Equal (yxCount, rect.Height * rect.Width); + } } } diff --git a/UnitTests/ViewTests.cs b/UnitTests/ViewTests.cs index 0a895e8e8..4d7bc05a1 100644 --- a/UnitTests/ViewTests.cs +++ b/UnitTests/ViewTests.cs @@ -37,6 +37,7 @@ namespace Terminal.Gui.Views { Assert.False (r.WantMousePositionReports); Assert.Null (r.SuperView); Assert.Null (r.MostFocused); + Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection); // Empty Rect r = new View (Rect.Empty); @@ -60,6 +61,7 @@ namespace Terminal.Gui.Views { Assert.False (r.WantMousePositionReports); Assert.Null (r.SuperView); Assert.Null (r.MostFocused); + Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection); // Rect with values r = new View (new Rect (1, 2, 3, 4)); @@ -83,6 +85,32 @@ namespace Terminal.Gui.Views { Assert.False (r.WantMousePositionReports); Assert.Null (r.SuperView); Assert.Null (r.MostFocused); + Assert.Equal (TextDirection.LeftRight_TopBottom, r.TextDirection); + + // Initializes a view with a vertical direction + r = new View ("Vertical View", TextDirection.TopBottom_LeftRight); + Assert.NotNull (r); + Assert.Equal (LayoutStyle.Computed, r.LayoutStyle); + Assert.Equal ("View()({X=0,Y=0,Width=1,Height=13})", r.ToString ()); + Assert.False (r.CanFocus); + Assert.False (r.HasFocus); + Assert.Equal (new Rect (0, 0, 1, 13), r.Bounds); + Assert.Equal (new Rect (0, 0, 1, 13), r.Frame); + Assert.Null (r.Focused); + Assert.Null (r.ColorScheme); + Assert.NotNull (r.Width); // All view Dim are initialized now, + Assert.NotNull (r.Height); // avoiding Dim errors. + Assert.NotNull (r.X); // All view Pos are initialized now, + Assert.NotNull (r.Y); // avoiding Pos errors. + Assert.False (r.IsCurrentTop); + Assert.Empty (r.Id); + Assert.Empty (r.Subviews); + Assert.False (r.WantContinuousButtonPressed); + Assert.False (r.WantMousePositionReports); + Assert.Null (r.SuperView); + Assert.Null (r.MostFocused); + Assert.Equal (TextDirection.TopBottom_LeftRight, r.TextDirection); + } [Fact] @@ -1020,7 +1048,7 @@ namespace Terminal.Gui.Views { } [Fact] - public void View_Difference_Between_An_Object_Initializer_And_A_Constructor () + public void View_With_No_Difference_Between_An_Object_Initializer_And_A_Constructor () { // Object Initializer var view = new View () { @@ -1033,8 +1061,10 @@ namespace Terminal.Gui.Views { Assert.Equal (2, view.Y); Assert.Equal (3, view.Width); Assert.Equal (4, view.Height); - Assert.True (view.Frame.IsEmpty); - Assert.True (view.Bounds.IsEmpty); + Assert.False (view.Frame.IsEmpty); + Assert.Equal (new Rect (1, 2, 3, 4), view.Frame); + Assert.False (view.Bounds.IsEmpty); + Assert.Equal (new Rect (0, 0, 3, 4), view.Bounds); view.LayoutSubviews (); @@ -1073,8 +1103,10 @@ namespace Terminal.Gui.Views { Assert.Equal (2, view.Y); Assert.Equal (3, view.Width); Assert.Equal (4, view.Height); - Assert.True (view.Frame.IsEmpty); - Assert.True (view.Bounds.IsEmpty); + Assert.False (view.Frame.IsEmpty); + Assert.Equal (new Rect (1, 2, 3, 4), view.Frame); + Assert.False (view.Bounds.IsEmpty); + Assert.Equal (new Rect (0, 0, 3, 4), view.Bounds); } [Fact]