diff --git a/Terminal.Gui/Core/Border.cs b/Terminal.Gui/Core/Border.cs index d7ec4e884..97b31cacd 100644 --- a/Terminal.Gui/Core/Border.cs +++ b/Terminal.Gui/Core/Border.cs @@ -16,7 +16,11 @@ namespace Terminal.Gui { /// /// The border is drawn with a double line limits. /// - Double + Double, + /// + /// The border is drawn with a single line and rounded corners limits. + /// + Rounded } /// @@ -75,6 +79,13 @@ namespace Terminal.Gui { Right = right; Bottom = bottom; } + + /// Returns the fully qualified type name of this instance. + /// The fully qualified type name. + public override string ToString () + { + return $"(Left={Left},Top={Top},Right={Right},Bottom={Bottom})"; + } } /// @@ -295,6 +306,8 @@ namespace Terminal.Gui { private bool drawMarginFrame; private Thickness borderThickness; private Thickness padding; + private bool effect3D; + private Point effect3DOffset = new Point (1, 1); /// /// Specifies the for a view. @@ -406,13 +419,24 @@ namespace Terminal.Gui { /// /// Gets or sets the 3D effect around the . /// - public bool Effect3D { get; set; } + public bool Effect3D { + get => effect3D; + set { + effect3D = value; + OnBorderChanged (); + } + } /// /// Get or sets the offset start position for the /// - public Point Effect3DOffset { get; set; } = new Point (1, 1); - + public Point Effect3DOffset { + get => effect3DOffset; + set { + effect3DOffset = value; + OnBorderChanged (); + } + } /// /// Gets or sets the color for the /// @@ -436,8 +460,11 @@ namespace Terminal.Gui { /// Drawn the more the /// more the and the . /// - public void DrawContent () + public void DrawContent (View view = null) { + if (Child == null) { + Child = view; + } if (Parent?.Border != null) { DrawParentBorder (Parent.ViewToScreen (Parent.Bounds)); } else { @@ -644,9 +671,9 @@ namespace Terminal.Gui { // Draw the upper Effect3D for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y; - r < frame.Y - drawMarginFrame - sumThickness.Top; r++) { + r >= 0 && r < frame.Y - drawMarginFrame - sumThickness.Top; r++) { for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X; - c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X, driver.Cols); c++) { + c >= 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X, driver.Cols); c++) { AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]); } @@ -654,9 +681,9 @@ namespace Terminal.Gui { // Draw the left Effect3D for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y; - r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y, driver.Rows); r++) { + r >= 0 && r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y, driver.Rows); r++) { for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X; - c < frame.X - drawMarginFrame - sumThickness.Left; c++) { + c >= 0 && c < frame.X - drawMarginFrame - sumThickness.Left; c++) { AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]); } @@ -664,9 +691,9 @@ namespace Terminal.Gui { // Draw the right Effect3D for (int r = frame.Y - drawMarginFrame - sumThickness.Top + effect3DOffset.Y; - r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y, driver.Rows); r++) { + r >= 0 && r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y, driver.Rows); r++) { for (int c = frame.Right + drawMarginFrame + sumThickness.Right; - c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X, driver.Cols); c++) { + c >= 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X, driver.Cols); c++) { AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]); } @@ -674,14 +701,15 @@ namespace Terminal.Gui { // Draw the lower Effect3D for (int r = frame.Bottom + drawMarginFrame + sumThickness.Bottom; - r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y, driver.Rows); r++) { + r >= 0 && r < Math.Min (frame.Bottom + drawMarginFrame + sumThickness.Bottom + effect3DOffset.Y, driver.Rows); r++) { for (int c = frame.X - drawMarginFrame - sumThickness.Left + effect3DOffset.X; - c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X, driver.Cols); c++) { + c >= 0 && c < Math.Min (frame.Right + drawMarginFrame + sumThickness.Right + effect3DOffset.X, driver.Cols); c++) { AddRuneAt (driver, c, r, (Rune)driver.Contents [r, c, 0]); } } } + driver.SetAttribute (savedAttribute); } private void DrawParentBorder (Rect frame) @@ -833,6 +861,7 @@ namespace Terminal.Gui { } } } + driver.SetAttribute (savedAttribute); } private Attribute GetEffect3DBrush () diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index dd2d1dd58..4ea70ea8b 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -910,12 +910,41 @@ namespace Terminal.Gui { var borderStyle = borderContent == null ? BorderStyle.Single : borderContent.BorderStyle; - Rune hLine = border ? (borderStyle == BorderStyle.Single ? HLine : HDLine) : clearChar; - Rune vLine = border ? (borderStyle == BorderStyle.Single ? VLine : VDLine) : clearChar; - Rune uRCorner = border ? (borderStyle == BorderStyle.Single ? URCorner : URDCorner) : clearChar; - Rune uLCorner = border ? (borderStyle == BorderStyle.Single ? ULCorner : ULDCorner) : clearChar; - Rune lLCorner = border ? (borderStyle == BorderStyle.Single ? LLCorner : LLDCorner) : clearChar; - Rune lRCorner = border ? (borderStyle == BorderStyle.Single ? LRCorner : LRDCorner) : clearChar; + Rune hLine = default, vLine = default, + uRCorner = default, uLCorner = default, lLCorner = default, lRCorner = default; + + if (border) { + switch (borderStyle) { + case BorderStyle.None: + break; + case BorderStyle.Single: + hLine = HLine; + vLine = VLine; + uRCorner = URCorner; + uLCorner = ULCorner; + lLCorner = LLCorner; + lRCorner = LRCorner; + break; + case BorderStyle.Double: + hLine = HDLine; + vLine = VDLine; + uRCorner = URDCorner; + uLCorner = ULDCorner; + lLCorner = LLDCorner; + lRCorner = LRDCorner; + break; + case BorderStyle.Rounded: + hLine = HRLine; + vLine = VRLine; + uRCorner = URRCorner; + uLCorner = ULRCorner; + lLCorner = LLRCorner; + lRCorner = LRRCorner; + break; + } + } else { + hLine = vLine = uRCorner = uLCorner = lLCorner = lRCorner = clearChar; + } // Outside top if (paddingTop > 1) { @@ -1235,6 +1264,36 @@ namespace Terminal.Gui { /// public Rune LRDCorner = '\u255d'; + /// + /// Horizontal line character for rounded corners. + /// + public Rune HRLine = '\u2500'; + + /// + /// Vertical line character for rounded corners. + /// + public Rune VRLine = '\u2502'; + + /// + /// Upper left rounded corner + /// + public Rune ULRCorner = '\u256d'; + + /// + /// Lower left rounded corner + /// + public Rune LLRCorner = '\u2570'; + + /// + /// Upper right rounded corner + /// + public Rune URRCorner = '\u256e'; + + /// + /// Lower right rounded corner + /// + public Rune LRRCorner = '\u256f'; + /// /// Make the attribute for the foreground and background colors. /// diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs index d13f8d38b..883ebe12b 100644 --- a/Terminal.Gui/Core/View.cs +++ b/Terminal.Gui/Core/View.cs @@ -1385,7 +1385,7 @@ namespace Terminal.Gui { } if (Border != null) { - Border.DrawContent (); + Border.DrawContent (this); } if (!ustring.IsNullOrEmpty (Text) || (this is Label && !AutoSize)) { diff --git a/Terminal.Gui/Views/PanelView.cs b/Terminal.Gui/Views/PanelView.cs index edd747cd4..6f513119c 100644 --- a/Terminal.Gui/Views/PanelView.cs +++ b/Terminal.Gui/Views/PanelView.cs @@ -77,20 +77,15 @@ namespace Terminal.Gui { Visible = false; return; } - child.X = 0; - child.Y = 0; - AdjustContainer (); if (child?.Border != null) { - child.Border.BorderChanged += Border_BorderChanged; Border = child.Border; - Border.Child = childContentView; } else { if (Border == null) { Border = new Border (); } - Border.BorderChanged += Border_BorderChanged; - Border.Child = childContentView; + Child.Border = Border; } + Border.Child = childContentView; if (!child.IsInitialized) { child.Initialized += Child_Initialized; } @@ -98,6 +93,29 @@ namespace Terminal.Gui { } } + /// + public override Border Border { + get => base.Border; + set { + if (base.Border?.Child != null && value.Child == null) { + value.Child = base.Border.Child; + } + base.Border = value; + if (value == null) { + return; + } + Border.BorderChanged += Border_BorderChanged; + if (Child != null && (Child?.Border == null || Child?.Border != value)) { + if (Child?.Border == null) { + Child.Border = new Border (); + } + Child.Border = Border; + Child.Border.BorderChanged += Border_BorderChanged; + } + AdjustContainer (); + } + } + private void Child_Initialized (object sender, EventArgs e) { savedPanel = new SavedPosDim () { @@ -118,23 +136,26 @@ namespace Terminal.Gui { private void AdjustContainer () { if (Child?.IsInitialized == true) { - var borderLength = Child.Border != null - ? Child.Border.DrawMarginFrame ? 1 : 0 - : 0; - var sumPadding = Child.Border != null - ? Child.Border.GetSumThickness () - : new Thickness (); + if (Child?.Border != null && Child.Border != Border) { + Border = Child.Border; + } + var borderLength = Child.Border.DrawMarginFrame ? 1 : 0; + var sumPadding = Child.Border.GetSumThickness (); + var effect3DOffset = Child.Border.Effect3D ? Child.Border.Effect3DOffset : new Point (); if (!UsePanelFrame) { - X = savedChild.X; + X = savedPanel.X; childContentView.X = borderLength + sumPadding.Left; - Y = savedChild.Y; + Y = savedPanel.Y; childContentView.Y = borderLength + sumPadding.Top; if (savedChild.Width is Dim.DimFill) { var margin = -savedChild.Width.Anchor (0); Width = Dim.Fill (margin); childContentView.Width = Dim.Fill (margin + borderLength + sumPadding.Right); } else { - Width = savedChild.Width + (2 * borderLength) + sumPadding.Right + sumPadding.Left; + var savedLayout = LayoutStyle; + LayoutStyle = LayoutStyle.Absolute; + Width = savedChild.X.Anchor (0) + savedChild.Width + (2 * borderLength) + sumPadding.Right + sumPadding.Left; + LayoutStyle = savedLayout; childContentView.Width = Dim.Fill (borderLength + sumPadding.Right); } if (savedChild.Height is Dim.DimFill) { @@ -142,25 +163,34 @@ namespace Terminal.Gui { Height = Dim.Fill (margin); childContentView.Height = Dim.Fill (margin + borderLength + sumPadding.Bottom); } else { - Height = savedChild.Height + (2 * borderLength) + sumPadding.Bottom + sumPadding.Top; + var savedLayout = LayoutStyle; + LayoutStyle = LayoutStyle.Absolute; + Height = savedChild.Y.Anchor (0) + savedChild.Height + (2 * borderLength) + sumPadding.Bottom + sumPadding.Top; + LayoutStyle = savedLayout; childContentView.Height = Dim.Fill (borderLength + sumPadding.Bottom); } } else { - X = savedPanel.X; + X = savedPanel.X - (effect3DOffset.X < 0 ? effect3DOffset.X : 0); childContentView.X = borderLength + sumPadding.Left; - Y = savedPanel.Y; + Y = savedPanel.Y - (effect3DOffset.Y < 0 ? effect3DOffset.Y : 0); childContentView.Y = borderLength + sumPadding.Top; Width = savedPanel.Width; Height = savedPanel.Height; if (Width is Dim.DimFill) { - var margin = -savedPanel.Width.Anchor (0); - childContentView.Width = Dim.Fill (margin + borderLength + sumPadding.Right); + var margin = -savedPanel.Width.Anchor (0) + + (effect3DOffset.X > 0 ? effect3DOffset.X : 0); + Width = Dim.Fill (margin); + childContentView.Width = Dim.Fill (margin + borderLength + sumPadding.Right + + (effect3DOffset.X > 0 ? effect3DOffset.X : 0)); } else { childContentView.Width = Dim.Fill (borderLength + sumPadding.Right); } if (Height is Dim.DimFill) { - var margin = -savedPanel.Height.Anchor (0); - childContentView.Height = Dim.Fill (margin + borderLength + sumPadding.Bottom); + var margin = -savedPanel.Height.Anchor (0) + + (effect3DOffset.Y > 0 ? effect3DOffset.Y : 0); + Height = Dim.Fill (margin); + childContentView.Height = Dim.Fill (margin + borderLength + sumPadding.Bottom + + (effect3DOffset.Y > 0 ? effect3DOffset.Y : 0)); } else { childContentView.Height = Dim.Fill (borderLength + sumPadding.Bottom); } @@ -206,7 +236,7 @@ namespace Terminal.Gui { { if (!NeedDisplay.IsEmpty) { Driver.SetAttribute (Child.GetNormalColor ()); - Border.DrawContent (); + Child.Border.DrawContent (Border.Child); } var savedClip = childContentView.ClipToBounds (); childContentView.Redraw (childContentView.Bounds); diff --git a/UICatalog/Scenarios/Borders.cs b/UICatalog/Scenarios/Borders.cs index 30dd8743c..b2c3eea4b 100644 --- a/UICatalog/Scenarios/Borders.cs +++ b/UICatalog/Scenarios/Borders.cs @@ -18,12 +18,6 @@ namespace UICatalog.Scenarios { var effect3D = true; var smartPanel = new PanelView () { - X = Pos.Center () - 38, - Y = Pos.Center () - 3, - Width = 24, - Height = 13 - }; - smartPanel.Add (new Label () { // Or smartPanel.Child = X = Pos.Center () - 38, Y = Pos.Center () - 3, Width = 24, @@ -37,6 +31,12 @@ namespace UICatalog.Scenarios { Background = background, Effect3D = effect3D }, + }; + smartPanel.Add (new Label () { // Or smartPanel.Child = + X = 0, + Y = 0, + Width = 24, + Height = 13, ColorScheme = Colors.TopLevel, Text = "This is a test\nwith a \nPanelView", TextAlignment = TextAlignment.Centered diff --git a/UICatalog/Scenarios/CharacterMap.cs b/UICatalog/Scenarios/CharacterMap.cs index b7e3fa31e..f0fdb814e 100644 --- a/UICatalog/Scenarios/CharacterMap.cs +++ b/UICatalog/Scenarios/CharacterMap.cs @@ -166,5 +166,22 @@ namespace UICatalog.Scenarios { base.OnDrawContent (viewport); } #endif + + public override bool ProcessKey (KeyEvent kb) + { + if (kb.Key == Key.PageDown) { + ContentOffset = new Point (0, ContentOffset.Y - Bounds.Height / 2 + 1); + return true; + } + if (kb.Key == Key.PageUp) { + if (ContentOffset.Y + Bounds.Height / 2 - 1 < 0) { + ContentOffset = new Point (0, ContentOffset.Y + Bounds.Height / 2 - 1); + } else { + ContentOffset = Point.Empty; + } + return true; + } + return base.ProcessKey (kb); + } } } diff --git a/UnitTests/BorderTests.cs b/UnitTests/BorderTests.cs index 4e2d88e15..75d137df4 100644 --- a/UnitTests/BorderTests.cs +++ b/UnitTests/BorderTests.cs @@ -538,5 +538,23 @@ namespace Terminal.Gui.Core { } } } + + [Fact] + [AutoInitShutdown] + public void BorderOnControlWithNoChildren () + { + var label = new TextField ("Loading...") { + Border = new Border () { + BorderStyle = BorderStyle.Single, + DrawMarginFrame = true, + Padding = new Thickness (1), + BorderBrush = Color.White + } + }; + + Application.Top.Add (label); + + Assert.Null (Record.Exception (() => label.Redraw (label.Bounds))); + } } } diff --git a/UnitTests/PanelViewTests.cs b/UnitTests/PanelViewTests.cs index f049a249f..829aca80a 100644 --- a/UnitTests/PanelViewTests.cs +++ b/UnitTests/PanelViewTests.cs @@ -24,7 +24,7 @@ namespace Terminal.Gui.Views { Assert.False (pv.UsePanelFrame); Assert.NotNull (pv.Child); Assert.NotNull (pv.Border); - Assert.Null (pv.Child.Border); + Assert.NotNull (pv.Child.Border); } [Fact] @@ -120,6 +120,19 @@ namespace Terminal.Gui.Views { Application.Begin (top); + Assert.False (pv.Child.Border.Effect3D); + Assert.Equal (new Rect (0, 0, 25, 15), pv.Frame); + Assert.Equal (new Rect (0, 0, 15, 1), pv.Child.Frame); + + pv.Child.Border.Effect3D = true; + + Assert.True (pv.Child.Border.Effect3D); + Assert.Equal (new Rect (0, 0, 25, 15), pv.Frame); + Assert.Equal (new Rect (0, 0, 15, 1), pv.Child.Frame); + + pv.Child.Border.Effect3DOffset = new Point (-1, -1); + + Assert.Equal (new Point (-1, -1), pv.Child.Border.Effect3DOffset); Assert.Equal (new Rect (0, 0, 25, 15), pv.Frame); Assert.Equal (new Rect (0, 0, 15, 1), pv.Child.Frame); } @@ -171,11 +184,31 @@ namespace Terminal.Gui.Views { Assert.Equal (new Rect (0, 0, 65, 6), pv1.Child.Frame); Assert.Equal (new Rect (0, 0, 76, 21), pv2.Frame); Assert.Equal (new Rect (0, 0, 62, 3), pv2.Child.Frame); + + pv.Child.Border.Effect3D = pv1.Child.Border.Effect3D = pv2.Child.Border.Effect3D = true; + + Assert.True (pv.Child.Border.Effect3D); + Assert.Equal (new Rect (0, 0, 78, 23), pv.Frame); + Assert.Equal (new Rect (0, 0, 68, 9), pv.Child.Frame); + Assert.Equal (new Rect (0, 0, 77, 22), pv1.Frame); + Assert.Equal (new Rect (0, 0, 65, 6), pv1.Child.Frame); + Assert.Equal (new Rect (0, 0, 76, 21), pv2.Frame); + Assert.Equal (new Rect (0, 0, 62, 3), pv2.Child.Frame); + + pv.Child.Border.Effect3DOffset = pv1.Child.Border.Effect3DOffset = pv2.Child.Border.Effect3DOffset = new Point (-1, -1); + + Assert.Equal (new Point (-1, -1), pv.Child.Border.Effect3DOffset); + Assert.Equal (new Rect (0, 0, 78, 23), pv.Frame); + Assert.Equal (new Rect (0, 0, 68, 9), pv.Child.Frame); + Assert.Equal (new Rect (0, 0, 77, 22), pv1.Frame); + Assert.Equal (new Rect (0, 0, 65, 6), pv1.Child.Frame); + Assert.Equal (new Rect (0, 0, 76, 21), pv2.Frame); + Assert.Equal (new Rect (0, 0, 62, 3), pv2.Child.Frame); } [Fact] [AutoInitShutdown] - public void UsePanelFrame_False_PanelView_Always_Respect_The_Child_Upper_Left_Corner_Position_And_Size () + public void UsePanelFrame_False_PanelView_Always_Respect_The_PanelView_Upper_Left_Corner_Position_And_The_Child_Size () { var top = Application.Top; var win = new Window (); @@ -208,17 +241,44 @@ namespace Terminal.Gui.Views { Application.Begin (top); - Assert.Equal (new Rect (0, 0, 15, 1), pv.Frame); + Assert.False (pv.UsePanelFrame); + Assert.False (pv.Border.Effect3D); + Assert.Equal (pv.Child.Border, pv.Border); + Assert.False (pv1.UsePanelFrame); + Assert.False (pv1.Border.Effect3D); + Assert.Equal (pv1.Child.Border, pv1.Border); + Assert.False (pv2.UsePanelFrame); + Assert.False (pv2.Border.Effect3D); + Assert.Equal (pv2.Child.Border, pv2.Border); + Assert.Equal (new Rect (2, 4, 15, 1), pv.Frame); Assert.Equal (new Rect (0, 0, 15, 1), pv.Child.Frame); - Assert.Equal (new Rect (3, 4, 15, 1), pv1.Frame); - Assert.Equal (new Rect (0, 0, 15, 1), pv1.Child.Frame); - Assert.Equal (new Rect (5, 6, 73, 17), pv2.Frame); - Assert.Equal (new Rect (0, 0, 73, 17), pv2.Child.Frame); + Assert.Equal (new Rect (2, 4, 18, 5), pv1.Frame); + Assert.Equal (new Rect (3, 4, 15, 1), pv1.Child.Frame); + Assert.Equal (new Rect (2, 4, 76, 19), pv2.Frame); + Assert.Equal (new Rect (5, 6, 71, 13), pv2.Child.Frame); + + pv.Border.Effect3D = pv1.Border.Effect3D = pv2.Border.Effect3D = true; + + Assert.Equal (new Rect (2, 4, 15, 1), pv.Frame); + Assert.Equal (new Rect (0, 0, 15, 1), pv.Child.Frame); + Assert.Equal (new Rect (2, 4, 18, 5), pv1.Frame); + Assert.Equal (new Rect (3, 4, 15, 1), pv1.Child.Frame); + Assert.Equal (new Rect (2, 4, 76, 19), pv2.Frame); + Assert.Equal (new Rect (5, 6, 71, 13), pv2.Child.Frame); + + pv.Border.Effect3DOffset = pv1.Border.Effect3DOffset = pv2.Border.Effect3DOffset = new Point (-1, -1); + + Assert.Equal (new Rect (2, 4, 15, 1), pv.Frame); + Assert.Equal (new Rect (0, 0, 15, 1), pv.Child.Frame); + Assert.Equal (new Rect (2, 4, 18, 5), pv1.Frame); + Assert.Equal (new Rect (3, 4, 15, 1), pv1.Child.Frame); + Assert.Equal (new Rect (2, 4, 76, 19), pv2.Frame); + Assert.Equal (new Rect (5, 6, 71, 13), pv2.Child.Frame); } [Fact] [AutoInitShutdown] - public void UsePanelFrame_True_PanelView_Position_And_Size_Are_Used () + public void UsePanelFrame_True_PanelView_Position_And_Size_Are_Used_Depending_On_Effect3DOffset () { var top = Application.Top; var win = new Window (); @@ -253,9 +313,23 @@ namespace Terminal.Gui.Views { Application.Begin (top); Assert.Equal (new Rect (5, 6, 73, 17), pv.Frame); - Assert.Equal (new Rect (0, 0, 20, 10), pv.Child.Frame); + Assert.Equal (new Rect (2, 4, 20, 10), pv.Child.Frame); Assert.Equal (new Rect (2, 4, 20, 10), pv1.Frame); - Assert.Equal (new Rect (0, 0, 20, 10), pv1.Child.Frame); + Assert.Equal (new Rect (5, 6, 15, 4), pv1.Child.Frame); + + pv.Border.Effect3D = pv1.Border.Effect3D = true; + + Assert.Equal (new Rect (5, 6, 73, 17), pv.Frame); + Assert.Equal (new Rect (2, 4, 20, 10), pv.Child.Frame); + Assert.Equal (new Rect (2, 4, 20, 10), pv1.Frame); + Assert.Equal (new Rect (5, 6, 15, 4), pv1.Child.Frame); + + pv.Border.Effect3DOffset = pv1.Border.Effect3DOffset = new Point (-1, -1); + + Assert.Equal (new Rect (6, 7, 73, 17), pv.Frame); + Assert.Equal (new Rect (2, 4, 20, 10), pv.Child.Frame); + Assert.Equal (new Rect (3, 5, 20, 10), pv1.Frame); + Assert.Equal (new Rect (5, 6, 15, 4), pv1.Child.Frame); } } }