From 319d2a66e8b6b2dbbb823481901d1509e4ed0047 Mon Sep 17 00:00:00 2001 From: Tig Date: Sat, 14 Dec 2024 10:56:22 -0700 Subject: [PATCH 1/7] Added ViewportSettigs Editor --- Terminal.Gui/Drawing/Region.cs | 79 ++-- Terminal.Gui/Drawing/Thickness.cs | 13 + Terminal.Gui/View/View.Drawing.Clipping.cs | 4 +- Terminal.Gui/View/View.Drawing.Primitives.cs | 4 +- Terminal.Gui/View/View.Drawing.cs | 85 +++- Terminal.Gui/View/ViewportSettings.cs | 24 +- Terminal.Gui/Views/CharMap/CharMap.cs | 4 +- UICatalog/Scenarios/AllViewsTester.cs | 27 +- .../Editors/ViewportSettingsEditor.cs | 371 ++++++++++++++++++ UnitTests/View/Draw/DrawTests.cs | 4 +- UnitTests/View/ViewTests.cs | 4 +- 11 files changed, 543 insertions(+), 76 deletions(-) create mode 100644 UICatalog/Scenarios/Editors/ViewportSettingsEditor.cs diff --git a/Terminal.Gui/Drawing/Region.cs b/Terminal.Gui/Drawing/Region.cs index c3ef1d61b2..abd06dcbae 100644 --- a/Terminal.Gui/Drawing/Region.cs +++ b/Terminal.Gui/Drawing/Region.cs @@ -1,21 +1,25 @@ -/// +#nullable enable + +namespace Terminal.Gui; + +/// /// Represents a region composed of one or more rectangles, providing methods for union, intersection, exclusion, and /// complement operations. /// public class Region : IDisposable { - private List _rectangles; + private List? _rectangles; /// /// Initializes a new instance of the class. /// - public Region () { _rectangles = new (); } + public Region () { _rectangles = []; } /// /// Initializes a new instance of the class with the specified rectangle. /// /// The initial rectangle for the region. - public Region (Rectangle rectangle) { _rectangles = new () { rectangle }; } + public Region (Rectangle rectangle) { _rectangles = [rectangle]; } /// /// Adds the specified rectangle to the region. @@ -23,7 +27,7 @@ public class Region : IDisposable /// The rectangle to add to the region. public void Union (Rectangle rectangle) { - _rectangles.Add (rectangle); + _rectangles!.Add (rectangle); _rectangles = MergeRectangles (_rectangles); } @@ -31,10 +35,13 @@ public void Union (Rectangle rectangle) /// Adds the specified region to this region. /// /// The region to add to this region. - public void Union (Region region) + public void Union (Region? region) { - _rectangles.AddRange (region._rectangles); - _rectangles = MergeRectangles (_rectangles); + if (region is { }) + { + _rectangles!.AddRange (region._rectangles!); + _rectangles = MergeRectangles (_rectangles); + } } /// @@ -43,20 +50,23 @@ public void Union (Region region) /// The rectangle to intersect with the region. public void Intersect (Rectangle rectangle) { - _rectangles = _rectangles.Select (r => Rectangle.Intersect (r, rectangle)).Where (r => !r.IsEmpty).ToList (); + _rectangles = _rectangles!.Select (r => Rectangle.Intersect (r, rectangle)).Where (r => !r.IsEmpty).ToList (); } /// /// Updates the region to be the intersection of itself with the specified region. /// /// The region to intersect with this region. - public void Intersect (Region region) + public void Intersect (Region? region) { - List intersections = new List (); + List intersections = []; + + // Null is same as empty region + region ??= new (); - foreach (Rectangle rect1 in _rectangles) + foreach (Rectangle rect1 in _rectangles!) { - foreach (Rectangle rect2 in region._rectangles) + foreach (Rectangle rect2 in region!._rectangles!) { Rectangle intersected = Rectangle.Intersect (rect1, rect2); @@ -74,17 +84,20 @@ public void Intersect (Region region) /// Removes the specified rectangle from the region. /// /// The rectangle to exclude from the region. - public void Exclude (Rectangle rectangle) { _rectangles = _rectangles.SelectMany (r => SubtractRectangle (r, rectangle)).ToList (); } + public void Exclude (Rectangle rectangle) { _rectangles = _rectangles!.SelectMany (r => SubtractRectangle (r, rectangle)).ToList (); } /// /// Removes the portion of the specified region from this region. /// /// The region to exclude from this region. - public void Exclude (Region region) + public void Exclude (Region? region) { - foreach (Rectangle rect in region._rectangles) + // Null is same as empty region + region ??= new (); + + foreach (Rectangle rect in region._rectangles!) { - _rectangles = _rectangles.SelectMany (r => SubtractRectangle (r, rect)).ToList (); + _rectangles = _rectangles!.SelectMany (r => SubtractRectangle (r, rect)).ToList (); } } @@ -94,14 +107,14 @@ public void Exclude (Region region) /// The bounding rectangle to use for complementing the region. public void Complement (Rectangle bounds) { - if (bounds.IsEmpty || _rectangles.Count == 0) + if (bounds.IsEmpty || _rectangles!.Count == 0) { - _rectangles.Clear (); + _rectangles!.Clear (); return; } - List complementRectangles = new List { bounds }; + List complementRectangles = [bounds]; foreach (Rectangle rect in _rectangles) { @@ -118,7 +131,7 @@ public void Complement (Rectangle bounds) public Region Clone () { var clone = new Region (); - clone._rectangles = new (_rectangles); + clone._rectangles = [.. _rectangles!]; return clone; } @@ -129,7 +142,7 @@ public Region Clone () /// A that bounds the region. public Rectangle GetBounds () { - if (_rectangles.Count == 0) + if (_rectangles!.Count == 0) { return Rectangle.Empty; } @@ -146,7 +159,7 @@ public Rectangle GetBounds () /// Determines whether the region is empty. /// /// true if the region is empty; otherwise, false. - public bool IsEmpty () { return !_rectangles.Any (); } + public bool IsEmpty () { return !_rectangles!.Any (); } /// /// Determines whether the specified point is contained within the region. @@ -154,20 +167,20 @@ public Rectangle GetBounds () /// The x-coordinate of the point. /// The y-coordinate of the point. /// true if the point is contained within the region; otherwise, false. - public bool Contains (int x, int y) { return _rectangles.Any (r => r.Contains (x, y)); } + public bool Contains (int x, int y) { return _rectangles!.Any (r => r.Contains (x, y)); } /// /// Determines whether the specified rectangle is contained within the region. /// /// The rectangle to check for containment. /// true if the rectangle is contained within the region; otherwise, false. - public bool Contains (Rectangle rectangle) { return _rectangles.Any (r => r.Contains (rectangle)); } + public bool Contains (Rectangle rectangle) { return _rectangles!.Any (r => r.Contains (rectangle)); } /// /// Returns an array of rectangles that represent the region. /// /// An array of objects that make up the region. - public Rectangle [] GetRegionScans () { return _rectangles.ToArray (); } + public Rectangle [] GetRegionScans () { return _rectangles!.ToArray (); } /// /// Offsets all rectangles in the region by the specified amounts. @@ -176,10 +189,10 @@ public Rectangle GetBounds () /// The amount to offset along the y-axis. public void Offset (int offsetX, int offsetY) { - for (int i = 0; i < _rectangles.Count; i++) + for (var i = 0; i < _rectangles!.Count; i++) { - var rect = _rectangles [i]; - _rectangles [i] = new Rectangle (rect.Left + offsetX, rect.Top + offsetY, rect.Width, rect.Height); + Rectangle rect = _rectangles [i]; + _rectangles [i] = new (rect.Left + offsetX, rect.Top + offsetY, rect.Width, rect.Height); } } @@ -188,11 +201,11 @@ public void Offset (int offsetX, int offsetY) /// /// The list of rectangles to merge. /// A list of merged rectangles. - private List MergeRectangles (List rectangles) + private static List MergeRectangles (List rectangles) { // Simplified merging logic: this does not handle all edge cases for merging overlapping rectangles. // For a full implementation, a plane sweep algorithm or similar would be needed. - List merged = new List (rectangles); + List merged = [.. rectangles]; bool mergedAny; do @@ -230,7 +243,7 @@ private List MergeRectangles (List rectangles) /// The original rectangle. /// The rectangle to subtract from the original. /// An enumerable collection of resulting rectangles after subtraction. - private IEnumerable SubtractRectangle (Rectangle original, Rectangle subtract) + private static IEnumerable SubtractRectangle (Rectangle original, Rectangle subtract) { if (!original.IntersectsWith (subtract)) { @@ -279,5 +292,5 @@ private IEnumerable SubtractRectangle (Rectangle original, Rectangle /// /// Releases all resources used by the . /// - public void Dispose () { _rectangles.Clear (); } + public void Dispose () { _rectangles!.Clear (); } } diff --git a/Terminal.Gui/Drawing/Thickness.cs b/Terminal.Gui/Drawing/Thickness.cs index 6aa2088e5a..ed73b3913c 100644 --- a/Terminal.Gui/Drawing/Thickness.cs +++ b/Terminal.Gui/Drawing/Thickness.cs @@ -235,6 +235,19 @@ public Rectangle GetInside (Rectangle rect) return new (x, y, width, height); } + /// + /// Returns a region describing the thickness. + /// + /// The source rectangle + /// + public Region AsRegion (Rectangle rect) + { + Region region = new Region (rect); + region.Exclude (GetInside (rect)); + + return region; + } + /// /// Gets the total width of the left and right sides of the rectangle. Sets the width of the left and right sides /// of the rectangle to half the specified value. diff --git a/Terminal.Gui/View/View.Drawing.Clipping.cs b/Terminal.Gui/View/View.Drawing.Clipping.cs index 30f8b703c6..509854f99a 100644 --- a/Terminal.Gui/View/View.Drawing.Clipping.cs +++ b/Terminal.Gui/View/View.Drawing.Clipping.cs @@ -86,7 +86,7 @@ public static void SetClip (Region? region) /// /// The current Clip, which can be then re-applied /// - internal Region? ClipFrame () + internal Region? AddFrameToClip () { if (Driver is null) { @@ -133,7 +133,7 @@ public static void SetClip (Region? region) /// /// The current Clip, which can be then re-applied /// - public Region? ClipViewport () + public Region? AddViewportToClip () { if (Driver is null) { diff --git a/Terminal.Gui/View/View.Drawing.Primitives.cs b/Terminal.Gui/View/View.Drawing.Primitives.cs index a7f1c8522d..153f12e644 100644 --- a/Terminal.Gui/View/View.Drawing.Primitives.cs +++ b/Terminal.Gui/View/View.Drawing.Primitives.cs @@ -137,7 +137,7 @@ public void FillRect (Rectangle rect, Color? color = null) return; } - Region prevClip = ClipViewport (); + Region prevClip = AddViewportToClip (); Rectangle toClear = ViewportToScreen (rect); Attribute prev = SetAttribute (new (color ?? GetNormalColor ().Background)); Driver.FillRect (toClear); @@ -155,7 +155,7 @@ public void FillRect (Rectangle rect, Rune rune) return; } - Region prevClip = ClipViewport (); + Region prevClip = AddViewportToClip (); Rectangle toClear = ViewportToScreen (rect); Driver.FillRect (toClear, rune); SetClip (prevClip); diff --git a/Terminal.Gui/View/View.Drawing.cs b/Terminal.Gui/View/View.Drawing.cs index adea35c36a..ee7dccd871 100644 --- a/Terminal.Gui/View/View.Drawing.cs +++ b/Terminal.Gui/View/View.Drawing.cs @@ -1,5 +1,6 @@ #nullable enable using System.ComponentModel; +using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Terminal.Gui; @@ -47,27 +48,38 @@ public void Draw () return; } - Region? saved = GetClip (); + Region? originalClip = GetClip (); + + Region? contentClip = null; // TODO: This can be further optimized by checking NeedsDraw below and only clearing, drawing text, drawing content, etc. if it is true. if (NeedsDraw || SubViewNeedsDraw) { // Draw the Border and Padding. - // We clip to the frame to prevent drawing outside the frame. - saved = ClipFrame (); - + if (this is Adornment) + { + AddFrameToClip (); + } + else + { + // Set the clip to be just the thicknesses of the adornments + // TODO: Put this union logic in a method on View? + Region? clipAdornments = Margin!.Thickness.AsRegion (Margin!.FrameToScreen ()); + clipAdornments?.Union (Border!.Thickness.AsRegion (Border!.FrameToScreen ())); + clipAdornments?.Union (Padding!.Thickness.AsRegion (Padding!.FrameToScreen ())); + clipAdornments?.Intersect (originalClip); + SetClip (clipAdornments); + } DoDrawBorderAndPadding (); - SetClip (saved); + SetClip (originalClip); - // Draw the content within the Viewport + // Clear the Viewport // By default, we clip to the viewport preventing drawing outside the viewport // We also clip to the content, but if a developer wants to draw outside the viewport, they can do // so via settings. SetClip honors the ViewportSettings.DisableVisibleContentClipping flag. // Get our Viewport in screen coordinates + originalClip = AddViewportToClip (); - saved = ClipViewport (); - - // Clear the viewport // TODO: Simplify/optimize SetAttribute system. DoSetAttribute (); DoClearViewport (); @@ -87,11 +99,28 @@ public void Draw () DoSetAttribute (); DoDrawContent (); + // TODO: This flag may not be needed. Just returning true from OnClearViewport may be sufficient. + if (ViewportSettings.HasFlag (ViewportSettings.Transparent) && _subviews is { Count: > 0 }) + { + contentClip = new Region (); + + contentClip.Union(ViewportToScreen (new Rectangle(Viewport.Location, TextFormatter.FormatAndGetSize()))); + // TODO: Move this into DrawSubviews somehow + foreach (View view in _subviews?.Where (view => view.Visible).Reverse ()) + { + contentClip.Union (view.FrameToScreen ()); + } + } + else + { + contentClip = new (ViewportToScreen (new Rectangle (Point.Empty, Viewport.Size))); + } + // Restore the clip before rendering the line canvas and adornment subviews // because they may draw outside the viewport. - SetClip (saved); + SetClip (originalClip); - saved = ClipFrame (); + originalClip = AddFrameToClip (); // Draw the line canvas DoRenderLineCanvas (); @@ -113,9 +142,6 @@ public void Draw () // We're done drawing DoDrawComplete (); - // QUESTION: Should this go before DoDrawComplete? What is more correct? - SetClip (saved); - // Exclude this view (not including Margin) from the Clip if (this is not Adornment) { @@ -126,7 +152,24 @@ public void Draw () borderFrame = Border.FrameToScreen (); } - ExcludeFromClip (borderFrame); + if (ViewportSettings.HasFlag (ViewportSettings.Transparent) && contentClip is { }) + { + Region? saved = originalClip!.Clone (); + + saved.Exclude (Border!.Thickness.AsRegion (Border!.FrameToScreen ())); + saved.Exclude (Padding!.Thickness.AsRegion (Padding!.FrameToScreen ())); + saved.Exclude (contentClip); + SetClip (saved); + } + else + { + SetClip (originalClip); + ExcludeFromClip (borderFrame); + } + } + else + { + SetClip (originalClip); } } @@ -144,10 +187,10 @@ private void DoDrawBorderAndPaddingSubViews () subview.SetNeedsDraw (); } - LineCanvas.Exclude (new (subview.FrameToScreen())); + LineCanvas.Exclude (new (subview.FrameToScreen ())); } - Region? saved = Border?.ClipFrame (); + Region? saved = Border?.AddFrameToClip (); Border?.DoDrawSubviews (); SetClip (saved); } @@ -159,7 +202,7 @@ private void DoDrawBorderAndPaddingSubViews () subview.SetNeedsDraw (); } - Region? saved = Padding?.ClipFrame (); + Region? saved = Padding?.AddFrameToClip (); Padding?.DoDrawSubviews (); SetClip (saved); } @@ -170,6 +213,7 @@ private void DoDrawBorderAndPadding () if (Margin?.NeedsLayout == true) { Margin.NeedsLayout = false; + // BUGBUG: This should not use ClearFrame as that clears the insides too Margin?.ClearFrame (); Margin?.Parent?.SetSubViewNeedsDraw (); } @@ -293,6 +337,11 @@ public void SetNormalAttribute () private void DoClearViewport () { + if (ViewportSettings.HasFlag (ViewportSettings.Transparent)) + { + return; + } + if (OnClearingViewport ()) { return; diff --git a/Terminal.Gui/View/ViewportSettings.cs b/Terminal.Gui/View/ViewportSettings.cs index db2c23f4fe..c687da7513 100644 --- a/Terminal.Gui/View/ViewportSettings.cs +++ b/Terminal.Gui/View/ViewportSettings.cs @@ -13,7 +13,7 @@ public enum ViewportSettings /// /// No settings. /// - None = 0, + None = 0b_0000, /// /// If set, .X can be set to negative values enabling scrolling beyond the left of @@ -23,7 +23,7 @@ public enum ViewportSettings /// When not set, .X is constrained to positive values. /// /// - AllowNegativeX = 1, + AllowNegativeX = 0b_0001, /// /// If set, .Y can be set to negative values enabling scrolling beyond the top of the @@ -32,7 +32,7 @@ public enum ViewportSettings /// When not set, .Y is constrained to positive values. /// /// - AllowNegativeY = 2, + AllowNegativeY = 0b_0010, /// /// If set, .Size can be set to negative coordinates enabling scrolling beyond the @@ -58,7 +58,7 @@ public enum ViewportSettings /// The practical effect of this is that the last column of the content will always be visible. /// /// - AllowXGreaterThanContentWidth = 4, + AllowXGreaterThanContentWidth = 0b_0100, /// /// If set, .Y can be set values greater than @@ -74,7 +74,7 @@ public enum ViewportSettings /// The practical effect of this is that the last row of the content will always be visible. /// /// - AllowYGreaterThanContentHeight = 8, + AllowYGreaterThanContentHeight = 0b_1000, /// /// If set, .Location can be set values greater than @@ -102,7 +102,7 @@ public enum ViewportSettings /// This can be useful in infinite scrolling scenarios. /// /// - AllowNegativeXWhenWidthGreaterThanContentWidth = 16, + AllowNegativeXWhenWidthGreaterThanContentWidth = 0b_0001_0000, /// /// If set and .Height is greater than @@ -117,7 +117,7 @@ public enum ViewportSettings /// This can be useful in infinite scrolling scenarios. /// /// - AllowNegativeYWhenHeightGreaterThanContentHeight = 32, + AllowNegativeYWhenHeightGreaterThanContentHeight = 0b_0010_0000, /// /// The combination of and @@ -129,7 +129,7 @@ public enum ViewportSettings /// By default, clipping is applied to the . Setting this flag will cause clipping to be /// applied to the visible content area. /// - ClipContentOnly = 64, + ClipContentOnly = 0b_0100_0000, /// /// If set will clear only the portion of the content @@ -138,5 +138,11 @@ public enum ViewportSettings /// must be set for this setting to work (clipping beyond the visible area must be /// disabled). /// - ClearContentOnly = 128 + ClearContentOnly = 0b_1000_0000, + + /// + /// If set, any will not be cleared when the View is drawn and the clip region + /// will be set to clip the View's and . + /// + Transparent = 0b_0001_0000_0000, } diff --git a/Terminal.Gui/Views/CharMap/CharMap.cs b/Terminal.Gui/Views/CharMap/CharMap.cs index b49c8c4e6f..a42d39c69e 100644 --- a/Terminal.Gui/Views/CharMap/CharMap.cs +++ b/Terminal.Gui/Views/CharMap/CharMap.cs @@ -97,8 +97,8 @@ public CharMap () }; // Set up the vertical scrollbar. Turn off AutoShow since it's always visible. - VerticalScrollBar.AutoShow = false; - VerticalScrollBar.Visible = true; // Force always visible + VerticalScrollBar.AutoShow = true; + VerticalScrollBar.Visible = false; // Force always visible VerticalScrollBar.X = Pos.AnchorEnd (); VerticalScrollBar.Y = HEADER_HEIGHT; // Header } diff --git a/UICatalog/Scenarios/AllViewsTester.cs b/UICatalog/Scenarios/AllViewsTester.cs index d982b2b899..c6f9136796 100644 --- a/UICatalog/Scenarios/AllViewsTester.cs +++ b/UICatalog/Scenarios/AllViewsTester.cs @@ -18,10 +18,9 @@ public class AllViewsTester : Scenario private Dictionary? _viewClasses; private ListView? _classListView; private AdornmentsEditor? _adornmentsEditor; - private ArrangementEditor? _arrangementEditor; - private LayoutEditor? _layoutEditor; + private ViewportSettingsEditor? _viewportSettingsEditor; private FrameView? _settingsPane; private RadioGroup? _orientation; private string _demoText = "This, that, and the other thing."; @@ -133,13 +132,27 @@ public override void Main () AutoSelectAdornments = false, SuperViewRendersLineCanvas = true }; - _layoutEditor.Border!.Thickness = new (1); + _layoutEditor.Border!.Thickness = new (1, 1, 1, 0); + + _viewportSettingsEditor = new () + { + Title = "ViewportSettings [_5]", + X = Pos.Right (_arrangementEditor) - 1, + Y = Pos.Bottom (_layoutEditor) - Pos.Func (() => _layoutEditor.Frame.Height == 1 ? 0 : 1), + Width = Dim.Width (_layoutEditor), + Height = Dim.Auto (), + CanFocus = true, + AutoSelectViewToEdit = false, + AutoSelectAdornments = false, + SuperViewRendersLineCanvas = true + }; + _viewportSettingsEditor.Border!.Thickness = new (1, 1, 1, 1); _settingsPane = new () { - Title = "Settings [_5]", + Title = "Misc Settings [_6]", X = Pos.Right (_adornmentsEditor) - 1, - Y = Pos.Bottom (_layoutEditor) - Pos.Func (() => _layoutEditor.Frame.Height == 1 ? 0 : 1), + Y = Pos.Bottom (_viewportSettingsEditor) - Pos.Func (() => _viewportSettingsEditor.Frame.Height == 1 ? 0 : 1), Width = Dim.Width (_layoutEditor), Height = Dim.Auto (), CanFocus = true, @@ -237,7 +250,7 @@ public override void Main () _hostPane.Padding.Diagnostics = ViewDiagnosticFlags.Ruler; _hostPane.Padding.ColorScheme = app.ColorScheme; - app.Add (_classListView, _adornmentsEditor, _arrangementEditor, _layoutEditor, _settingsPane, _eventLog, _hostPane); + app.Add (_classListView, _adornmentsEditor, _arrangementEditor, _layoutEditor, _viewportSettingsEditor, _settingsPane, _eventLog, _hostPane); app.Initialized += App_Initialized; @@ -306,6 +319,7 @@ private void CreateCurrentView (Type type) _hostPane!.Add (_curView); _layoutEditor!.ViewToEdit = _curView; + _viewportSettingsEditor!.ViewToEdit = _curView; _arrangementEditor!.ViewToEdit = _curView; _curView.SetNeedsLayout (); } @@ -318,6 +332,7 @@ private void DisposeCurrentView () _curView.SubviewsLaidOut -= CurrentView_LayoutComplete; _hostPane!.Remove (_curView); _layoutEditor!.ViewToEdit = null; + _viewportSettingsEditor!.ViewToEdit = null; _arrangementEditor!.ViewToEdit = null; _curView.Dispose (); diff --git a/UICatalog/Scenarios/Editors/ViewportSettingsEditor.cs b/UICatalog/Scenarios/Editors/ViewportSettingsEditor.cs new file mode 100644 index 0000000000..ab77fe4a26 --- /dev/null +++ b/UICatalog/Scenarios/Editors/ViewportSettingsEditor.cs @@ -0,0 +1,371 @@ +#nullable enable +using System; +using Terminal.Gui; + +namespace UICatalog.Scenarios; + +/// +/// Provides an editor UI for View.ViewportSettings. +/// +public sealed class ViewportSettingsEditor : EditorBase +{ + public ViewportSettingsEditor () + { + Title = "ViewportSettingsEditor"; + TabStop = TabBehavior.TabGroup; + + Initialized += ViewportSettingsEditor_Initialized; + } + + protected override void OnUpdateSettings () + { + foreach (View subview in Subviews) + { + subview.Enabled = ViewToEdit is not Adornment; + } + + if (ViewToEdit is null) + { } + } + + protected override void OnViewToEditChanged () + { + if (ViewToEdit is { } and not Adornment) + { + //ViewToEdit.VerticalScrollBar.AutoShow = true; + //ViewToEdit.HorizontalScrollBar.AutoShow = true; + + _contentSizeWidth!.Value = ViewToEdit.GetContentSize ().Width; + _contentSizeHeight!.Value = ViewToEdit.GetContentSize ().Height; + + _cbAllowNegativeX!.CheckedState = ViewToEdit.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.AllowNegativeX) + ? CheckState.Checked + : CheckState.UnChecked; + + _cbAllowNegativeY!.CheckedState = ViewToEdit.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.AllowNegativeY) + ? CheckState.Checked + : CheckState.UnChecked; + + _cbAllowXGreaterThanContentWidth!.CheckedState = ViewToEdit.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.AllowXGreaterThanContentWidth) + ? CheckState.Checked + : CheckState.UnChecked; + + _cbAllowYGreaterThanContentHeight!.CheckedState = ViewToEdit.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.AllowYGreaterThanContentHeight) + ? CheckState.Checked + : CheckState.UnChecked; + + _cbClearContentOnly!.CheckedState = ViewToEdit.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.ClearContentOnly) + ? CheckState.Checked + : CheckState.UnChecked; + + _cbClipContentOnly!.CheckedState = ViewToEdit.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.ClipContentOnly) + ? CheckState.Checked + : CheckState.UnChecked; + + _cbTransparent!.CheckedState = ViewToEdit.ViewportSettings.HasFlag(Terminal.Gui.ViewportSettings.Transparent) + ? CheckState.Checked + : CheckState.UnChecked; + + _cbVerticalScrollBar!.CheckedState = ViewToEdit.VerticalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked; + _cbAutoShowVerticalScrollBar!.CheckedState = ViewToEdit.VerticalScrollBar.AutoShow ? CheckState.Checked : CheckState.UnChecked; + _cbHorizontalScrollBar!.CheckedState = ViewToEdit.HorizontalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked; + _cbAutoShowHorizontalScrollBar!.CheckedState = ViewToEdit.HorizontalScrollBar.AutoShow ? CheckState.Checked : CheckState.UnChecked; + } + } + + private CheckBox? _cbAllowNegativeX; + private CheckBox? _cbAllowNegativeY; + private CheckBox? _cbAllowXGreaterThanContentWidth; + private CheckBox? _cbAllowYGreaterThanContentHeight; + private NumericUpDown? _contentSizeWidth; + private NumericUpDown? _contentSizeHeight; + private CheckBox? _cbClearContentOnly; + private CheckBox? _cbClipContentOnly; + private CheckBox? _cbTransparent; + private CheckBox? _cbVerticalScrollBar; + private CheckBox? _cbAutoShowVerticalScrollBar; + private CheckBox? _cbHorizontalScrollBar; + private CheckBox? _cbAutoShowHorizontalScrollBar; + + private void ViewportSettingsEditor_Initialized (object? s, EventArgs e) + { + _cbAllowNegativeX = new() + { + Title = "Allow X < 0", + CanFocus = true + }; + + Add (_cbAllowNegativeX); + + _cbAllowNegativeY = new() + { + Title = "Allow Y < 0", + CanFocus = true + }; + + Add (_cbAllowNegativeY); + + _cbAllowXGreaterThanContentWidth = new() + { + Title = "Allow X > Content Width", + Y = Pos.Bottom (_cbAllowNegativeX), + CanFocus = true + }; + + _cbAllowNegativeX.CheckedStateChanging += AllowNegativeXToggle; + _cbAllowXGreaterThanContentWidth.CheckedStateChanging += AllowXGreaterThanContentWidthToggle; + + Add (_cbAllowXGreaterThanContentWidth); + + void AllowNegativeXToggle (object? sender, CancelEventArgs e) + { + if (e.NewValue == CheckState.Checked) + { + ViewToEdit!.ViewportSettings |= Terminal.Gui.ViewportSettings.AllowNegativeX; + } + else + { + ViewToEdit!.ViewportSettings &= ~Terminal.Gui.ViewportSettings.AllowNegativeX; + } + } + + void AllowXGreaterThanContentWidthToggle (object? sender, CancelEventArgs e) + { + if (e.NewValue == CheckState.Checked) + { + ViewToEdit!.ViewportSettings |= Terminal.Gui.ViewportSettings.AllowXGreaterThanContentWidth; + } + else + { + ViewToEdit!.ViewportSettings &= ~Terminal.Gui.ViewportSettings.AllowXGreaterThanContentWidth; + } + } + + _cbAllowYGreaterThanContentHeight = new() + { + Title = "Allow Y > Content Height", + X = Pos.Right (_cbAllowXGreaterThanContentWidth) + 1, + Y = Pos.Bottom (_cbAllowNegativeX), + CanFocus = true + }; + + _cbAllowNegativeY.CheckedStateChanging += AllowNegativeYToggle; + + _cbAllowYGreaterThanContentHeight.CheckedStateChanging += AllowYGreaterThanContentHeightToggle; + + Add (_cbAllowYGreaterThanContentHeight); + + void AllowNegativeYToggle (object? sender, CancelEventArgs e) + { + if (e.NewValue == CheckState.Checked) + { + ViewToEdit!.ViewportSettings |= Terminal.Gui.ViewportSettings.AllowNegativeY; + } + else + { + ViewToEdit!.ViewportSettings &= ~Terminal.Gui.ViewportSettings.AllowNegativeY; + } + } + + void AllowYGreaterThanContentHeightToggle (object? sender, CancelEventArgs e) + { + if (e.NewValue == CheckState.Checked) + { + ViewToEdit!.ViewportSettings |= Terminal.Gui.ViewportSettings.AllowYGreaterThanContentHeight; + } + else + { + ViewToEdit!.ViewportSettings &= ~Terminal.Gui.ViewportSettings.AllowYGreaterThanContentHeight; + } + } + + _cbAllowNegativeX.X = Pos.Left (_cbAllowYGreaterThanContentHeight); + + var labelContentSize = new Label + { + Title = "ContentSize:", + Y = Pos.Bottom (_cbAllowYGreaterThanContentHeight) + }; + + _contentSizeWidth = new() + { + X = Pos.Right (labelContentSize) + 1, + Y = Pos.Top (labelContentSize), + CanFocus = true + }; + _contentSizeWidth.ValueChanging += ContentSizeWidthValueChanged; + + void ContentSizeWidthValueChanged (object? sender, CancelEventArgs e) + { + if (e.NewValue < 0) + { + e.Cancel = true; + + return; + } + + // BUGBUG: set_ContentSize is supposed to be `protected`. + ViewToEdit!.SetContentSize (ViewToEdit.GetContentSize () with { Width = e.NewValue }); + } + + var labelComma = new Label + { + Title = ",", + X = Pos.Right (_contentSizeWidth), + Y = Pos.Top (labelContentSize) + }; + + _contentSizeHeight = new() + { + X = Pos.Right (labelComma) + 1, + Y = Pos.Top (labelContentSize), + CanFocus = true + }; + _contentSizeHeight.ValueChanging += ContentSizeHeightValueChanged; + + void ContentSizeHeightValueChanged (object? sender, CancelEventArgs e) + { + if (e.NewValue < 0) + { + e.Cancel = true; + + return; + } + + // BUGBUG: set_ContentSize is supposed to be `protected`. + ViewToEdit?.SetContentSize (ViewToEdit.GetContentSize () with { Height = e.NewValue }); + } + + _cbClearContentOnly = new() + { + Title = "ClearContentOnly", + X = Pos.Right (_contentSizeHeight) + 1, + Y = Pos.Top (labelContentSize), + CanFocus = true + }; + _cbClearContentOnly.CheckedStateChanging += ClearContentOnlyToggle; + + void ClearContentOnlyToggle (object? sender, CancelEventArgs e) + { + if (e.NewValue == CheckState.Checked) + { + ViewToEdit!.ViewportSettings |= Terminal.Gui.ViewportSettings.ClearContentOnly; + } + else + { + ViewToEdit!.ViewportSettings &= ~Terminal.Gui.ViewportSettings.ClearContentOnly; + } + } + + _cbClipContentOnly = new() + { + Title = "ClipContentOnly", + X = Pos.Right (_cbClearContentOnly) + 1, + Y = Pos.Top (labelContentSize), + CanFocus = true + }; + _cbClipContentOnly.CheckedStateChanging += ClipContentOnlyToggle; + + void ClipContentOnlyToggle (object? sender, CancelEventArgs e) + { + if (e.NewValue == CheckState.Checked) + { + ViewToEdit!.ViewportSettings |= Terminal.Gui.ViewportSettings.ClipContentOnly; + } + else + { + ViewToEdit!.ViewportSettings &= ~Terminal.Gui.ViewportSettings.ClipContentOnly; + } + } + + _cbTransparent = new () + { + Title = "Transparent", + X = Pos.Right (_cbClipContentOnly) + 1, + Y = Pos.Top (labelContentSize), + CanFocus = true + }; + _cbTransparent.CheckedStateChanging += TransparentToggle; + + void TransparentToggle (object? sender, CancelEventArgs e) + { + if (e.NewValue == CheckState.Checked) + { + ViewToEdit!.ViewportSettings |= Terminal.Gui.ViewportSettings.Transparent; + } + else + { + ViewToEdit!.ViewportSettings &= ~Terminal.Gui.ViewportSettings.Transparent; + } + } + + _cbVerticalScrollBar = new() + { + Title = "VerticalScrollBar.Visible", + X = 0, + Y = Pos.Bottom (labelContentSize), + CanFocus = false + }; + _cbVerticalScrollBar.CheckedStateChanging += VerticalScrollBarToggle; + + void VerticalScrollBarToggle (object? sender, CancelEventArgs e) + { + ViewToEdit!.VerticalScrollBar.Visible = e.NewValue == CheckState.Checked; + } + + _cbAutoShowVerticalScrollBar = new() + { + Title = "VerticalScrollBar.AutoShow", + X = Pos.Right (_cbVerticalScrollBar) + 1, + Y = Pos.Top (_cbVerticalScrollBar), + CanFocus = false + }; + _cbAutoShowVerticalScrollBar.CheckedStateChanging += AutoShowVerticalScrollBarToggle; + + void AutoShowVerticalScrollBarToggle (object? sender, CancelEventArgs e) + { + ViewToEdit!.VerticalScrollBar.AutoShow = e.NewValue == CheckState.Checked; + } + + _cbHorizontalScrollBar = new() + { + Title = "HorizontalScrollBar.Visible", + X = 0, + Y = Pos.Bottom (_cbVerticalScrollBar), + CanFocus = false + }; + _cbHorizontalScrollBar.CheckedStateChanging += HorizontalScrollBarToggle; + + void HorizontalScrollBarToggle (object? sender, CancelEventArgs e) + { + ViewToEdit!.HorizontalScrollBar.Visible = e.NewValue == CheckState.Checked; + } + + _cbAutoShowHorizontalScrollBar = new() + { + Title = "HorizontalScrollBar.AutoShow ", + X = Pos.Right (_cbHorizontalScrollBar) + 1, + Y = Pos.Top (_cbHorizontalScrollBar), + CanFocus = false + }; + _cbAutoShowHorizontalScrollBar.CheckedStateChanging += AutoShowHorizontalScrollBarToggle; + + void AutoShowHorizontalScrollBarToggle (object? sender, CancelEventArgs e) + { + ViewToEdit!.HorizontalScrollBar.AutoShow = e.NewValue == CheckState.Checked; + } + + Add ( + labelContentSize, + _contentSizeWidth, + labelComma, + _contentSizeHeight, + _cbClearContentOnly, + _cbClipContentOnly, + _cbTransparent, + _cbVerticalScrollBar, + _cbHorizontalScrollBar, + _cbAutoShowVerticalScrollBar, + _cbAutoShowHorizontalScrollBar); + } +} diff --git a/UnitTests/View/Draw/DrawTests.cs b/UnitTests/View/Draw/DrawTests.cs index 90d2ecb520..666e5b8adc 100644 --- a/UnitTests/View/Draw/DrawTests.cs +++ b/UnitTests/View/Draw/DrawTests.cs @@ -968,7 +968,7 @@ public void SetClip_ClipVisibleContentOnly_VisibleContentIsClipped () Assert.Equal (view.Frame, View.GetClip ()!.GetBounds ()); // Act - view.ClipViewport (); + view.AddViewportToClip (); // Assert Assert.Equal (expectedClip, View.GetClip ()!.GetBounds ()); @@ -1002,7 +1002,7 @@ public void SetClip_Default_ClipsToViewport () view.Viewport = view.Viewport with { X = 1, Y = 1 }; // Act - view.ClipViewport (); + view.AddViewportToClip (); // Assert Assert.Equal (expectedClip, View.GetClip ()!.GetBounds ()); diff --git a/UnitTests/View/ViewTests.cs b/UnitTests/View/ViewTests.cs index c169013e99..9a76f8e83e 100644 --- a/UnitTests/View/ViewTests.cs +++ b/UnitTests/View/ViewTests.cs @@ -163,7 +163,7 @@ public void Clear_Viewport_Can_Use_Driver_AddRune_Or_AddStr_Methods () view.DrawingContent += (s, e) => { - Region savedClip = view.ClipViewport (); + Region savedClip = view.AddViewportToClip (); for (var row = 0; row < view.Viewport.Height; row++) { @@ -226,7 +226,7 @@ public void Clear_Can_Use_Driver_AddRune_Or_AddStr_Methods () view.DrawingContent += (s, e) => { - Region savedClip = view.ClipViewport (); + Region savedClip = view.AddViewportToClip (); for (var row = 0; row < view.Viewport.Height; row++) { From ae85fa22611278f85c457eb401afd9b530f0b0da Mon Sep 17 00:00:00 2001 From: Tig Date: Sat, 14 Dec 2024 11:01:40 -0700 Subject: [PATCH 2/7] Tweaked Arrangment scenario temporarily --- UICatalog/Scenarios/Arrangement.cs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/UICatalog/Scenarios/Arrangement.cs b/UICatalog/Scenarios/Arrangement.cs index 33ac9ee84c..df768a49a7 100644 --- a/UICatalog/Scenarios/Arrangement.cs +++ b/UICatalog/Scenarios/Arrangement.cs @@ -185,6 +185,9 @@ public override void Main () }; testFrame.Add (datePicker); + + testFrame.Add (new TransparentView ()); + adornmentsEditor.AutoSelectSuperView = testFrame; arrangementEditor.AutoSelectSuperView = testFrame; @@ -298,4 +301,29 @@ public override List GetDemoKeyStrokes () return keys; } + + public class TransparentView : FrameView + { + public TransparentView() + { + Title = "Transparent"; + Text = "Text"; + X = 0; + Y = 0; + Width = 30; + Height = 10; + Arrangement = ViewArrangement.Overlapped | ViewArrangement.Resizable | ViewArrangement.Movable; + ViewportSettings |= Terminal.Gui.ViewportSettings.Transparent; + + Padding!.Thickness = new Thickness (1); + + Add ( + new Button () + { + Title = "_Hi", + X = Pos.Center (), + Y = Pos.Center () + }); + } + } } From c547d7881dd32e6d3c1652dcb1ac1db2aa5699a2 Mon Sep 17 00:00:00 2001 From: Tig Date: Sat, 14 Dec 2024 11:48:40 -0700 Subject: [PATCH 3/7] tweaked editor --- .../Editors/ViewportSettingsEditor.cs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/UICatalog/Scenarios/Editors/ViewportSettingsEditor.cs b/UICatalog/Scenarios/Editors/ViewportSettingsEditor.cs index ab77fe4a26..011ca212fc 100644 --- a/UICatalog/Scenarios/Editors/ViewportSettingsEditor.cs +++ b/UICatalog/Scenarios/Editors/ViewportSettingsEditor.cs @@ -179,7 +179,7 @@ void AllowYGreaterThanContentHeightToggle (object? sender, CancelEventArgs e) _cbClearContentOnly = new() { Title = "ClearContentOnly", - X = Pos.Right (_contentSizeHeight) + 1, - Y = Pos.Top (labelContentSize), + X = 0, + Y = Pos.Bottom (labelContentSize), CanFocus = true }; _cbClearContentOnly.CheckedStateChanging += ClearContentOnlyToggle; @@ -261,7 +261,7 @@ void ClearContentOnlyToggle (object? sender, CancelEventArgs e) { Title = "ClipContentOnly", X = Pos.Right (_cbClearContentOnly) + 1, - Y = Pos.Top (labelContentSize), + Y = Pos.Bottom (labelContentSize), CanFocus = true }; _cbClipContentOnly.CheckedStateChanging += ClipContentOnlyToggle; @@ -282,7 +282,7 @@ void ClipContentOnlyToggle (object? sender, CancelEventArgs e) { Title = "Transparent", X = Pos.Right (_cbClipContentOnly) + 1, - Y = Pos.Top (labelContentSize), + Y = Pos.Bottom (labelContentSize), CanFocus = true }; _cbTransparent.CheckedStateChanging += TransparentToggle; @@ -301,9 +301,9 @@ void TransparentToggle (object? sender, CancelEventArgs e) _cbVerticalScrollBar = new() { - Title = "VerticalScrollBar.Visible", + Title = "VerticalScrollBar", X = 0, - Y = Pos.Bottom (labelContentSize), + Y = Pos.Bottom (_cbClearContentOnly), CanFocus = false }; _cbVerticalScrollBar.CheckedStateChanging += VerticalScrollBarToggle; @@ -315,7 +315,7 @@ void VerticalScrollBarToggle (object? sender, CancelEventArgs e) _cbAutoShowVerticalScrollBar = new() { - Title = "VerticalScrollBar.AutoShow", + Title = "AutoShow", X = Pos.Right (_cbVerticalScrollBar) + 1, Y = Pos.Top (_cbVerticalScrollBar), CanFocus = false @@ -329,7 +329,7 @@ void AutoShowVerticalScrollBarToggle (object? sender, CancelEventArgs e) _cbAutoShowHorizontalScrollBar = new() { - Title = "HorizontalScrollBar.AutoShow ", + Title = "AutoShow ", X = Pos.Right (_cbHorizontalScrollBar) + 1, Y = Pos.Top (_cbHorizontalScrollBar), CanFocus = false From d4fbba655b248a2aabe74c43b1ae8f6c4f403bc1 Mon Sep 17 00:00:00 2001 From: Tig Date: Sun, 15 Dec 2024 08:49:49 -0700 Subject: [PATCH 4/7] fixed transparent bug --- Terminal.Gui/View/View.Drawing.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Terminal.Gui/View/View.Drawing.cs b/Terminal.Gui/View/View.Drawing.cs index ee7dccd871..b5e2486a69 100644 --- a/Terminal.Gui/View/View.Drawing.cs +++ b/Terminal.Gui/View/View.Drawing.cs @@ -53,7 +53,7 @@ public void Draw () Region? contentClip = null; // TODO: This can be further optimized by checking NeedsDraw below and only clearing, drawing text, drawing content, etc. if it is true. - if (NeedsDraw || SubViewNeedsDraw) + if (NeedsDraw || SubViewNeedsDraw || ViewportSettings.HasFlag(ViewportSettings.Transparent)) { // Draw the Border and Padding. if (this is Adornment) From 557e6370556b672978967440a11ca06e2088f081 Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 16 Dec 2024 18:06:49 -0700 Subject: [PATCH 5/7] tweaked Arragnemetns Scenario to test nested transparent views --- UICatalog/Scenarios/Arrangement.cs | 64 +++++++++++++++++++----------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/UICatalog/Scenarios/Arrangement.cs b/UICatalog/Scenarios/Arrangement.cs index df768a49a7..b8d06b1827 100644 --- a/UICatalog/Scenarios/Arrangement.cs +++ b/UICatalog/Scenarios/Arrangement.cs @@ -185,8 +185,28 @@ public override void Main () }; testFrame.Add (datePicker); + TransparentView transparentView = new () + { + Id = "transparentView", + X = 5, + Y = 11, + Width = 35, + Height = 15 + }; - testFrame.Add (new TransparentView ()); + transparentView.Add ( + new TransparentView () + { + Title = "Transparent SubView", + Text = "Transparent SubView", + Id = "transparentSubView", + X = 10, + Y = 10, + Width = 10, + Height = 5 + + }); + testFrame.Add (transparentView); adornmentsEditor.AutoSelectSuperView = testFrame; arrangementEditor.AutoSelectSuperView = testFrame; @@ -301,29 +321,27 @@ public override List GetDemoKeyStrokes () return keys; } +} - public class TransparentView : FrameView +public class TransparentView : FrameView +{ + public TransparentView () { - public TransparentView() - { - Title = "Transparent"; - Text = "Text"; - X = 0; - Y = 0; - Width = 30; - Height = 10; - Arrangement = ViewArrangement.Overlapped | ViewArrangement.Resizable | ViewArrangement.Movable; - ViewportSettings |= Terminal.Gui.ViewportSettings.Transparent; - - Padding!.Thickness = new Thickness (1); - - Add ( - new Button () - { - Title = "_Hi", - X = Pos.Center (), - Y = Pos.Center () - }); - } + Title = "Transparent"; + base.Text = "Text"; + Arrangement = ViewArrangement.Overlapped | ViewArrangement.Resizable | ViewArrangement.Movable; + ViewportSettings |= Terminal.Gui.ViewportSettings.Transparent; + base.Add ( + new Button () + { + Title = "_Hi", + X = Pos.Center (), + Y = Pos.Center (), + ShadowStyle = ShadowStyle.None, + ColorScheme = Colors.ColorSchemes ["Toplevel"], + }); } + + /// + protected override bool OnMouseEvent (MouseEventArgs mouseEvent) { return false; } } From f24c7bd8f21604e51557c8ad4e806d398646730c Mon Sep 17 00:00:00 2001 From: Tig Date: Mon, 16 Dec 2024 18:15:57 -0700 Subject: [PATCH 6/7] tweaks --- UICatalog/Scenarios/Arrangement.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/UICatalog/Scenarios/Arrangement.cs b/UICatalog/Scenarios/Arrangement.cs index df768a49a7..1d0c69f5ad 100644 --- a/UICatalog/Scenarios/Arrangement.cs +++ b/UICatalog/Scenarios/Arrangement.cs @@ -185,9 +185,10 @@ public override void Main () }; testFrame.Add (datePicker); - testFrame.Add (new TransparentView ()); + testFrame.Add (new TransparentView () { Title = "Transparent #2"}); + adornmentsEditor.AutoSelectSuperView = testFrame; arrangementEditor.AutoSelectSuperView = testFrame; @@ -308,21 +309,22 @@ public TransparentView() { Title = "Transparent"; Text = "Text"; - X = 0; - Y = 0; + X = 5; + Y = 10; Width = 30; Height = 10; Arrangement = ViewArrangement.Overlapped | ViewArrangement.Resizable | ViewArrangement.Movable; ViewportSettings |= Terminal.Gui.ViewportSettings.Transparent; + BorderStyle = LineStyle.Double; + CanFocus = true; - Padding!.Thickness = new Thickness (1); - - Add ( + base.Add ( new Button () { Title = "_Hi", X = Pos.Center (), - Y = Pos.Center () + Y = Pos.Center (), + ShadowStyle = ShadowStyle.None }); } } From fa31a292c50228af8364d07ca26a0e963a3d78b1 Mon Sep 17 00:00:00 2001 From: Tig Date: Sun, 29 Dec 2024 15:54:28 -0700 Subject: [PATCH 7/7] Tweaked viewportsettings scenario --- UICatalog/Scenarios/Arrangement.cs | 8 +- UICatalog/Scenarios/ViewportSettings.cs | 291 ++---------------------- 2 files changed, 24 insertions(+), 275 deletions(-) diff --git a/UICatalog/Scenarios/Arrangement.cs b/UICatalog/Scenarios/Arrangement.cs index b8d06b1827..bbd4c23f1a 100644 --- a/UICatalog/Scenarios/Arrangement.cs +++ b/UICatalog/Scenarios/Arrangement.cs @@ -195,7 +195,7 @@ public override void Main () }; transparentView.Add ( - new TransparentView () + new View () { Title = "Transparent SubView", Text = "Transparent SubView", @@ -212,6 +212,12 @@ public override void Main () arrangementEditor.AutoSelectSuperView = testFrame; testFrame.SetFocus (); + + testFrame.Add ( + new Button () + { + Title = "Hey", + }); Application.Run (app); timer.Close (); app.Dispose (); diff --git a/UICatalog/Scenarios/ViewportSettings.cs b/UICatalog/Scenarios/ViewportSettings.cs index 4842f1529f..e8f418505b 100644 --- a/UICatalog/Scenarios/ViewportSettings.cs +++ b/UICatalog/Scenarios/ViewportSettings.cs @@ -30,6 +30,7 @@ public ScrollingDemoView () SetContentSize (new (60, 40)); ViewportSettings |= Terminal.Gui.ViewportSettings.ClearContentOnly; ViewportSettings |= Terminal.Gui.ViewportSettings.ClipContentOnly; + VerticalScrollBar.Visible = true; // Things this view knows how to do AddCommand (Command.ScrollDown, () => ScrollVertical (1)); @@ -112,288 +113,23 @@ public override void Main () }; app.Add (editor); + ViewportSettingsEditor viewportSettingsEditor = new ViewportSettingsEditor () + { + X = Pos.Right (editor), + }; + app.Add (viewportSettingsEditor); + var view = new ScrollingDemoView { Title = "Demo View", X = Pos.Right (editor), + Y = Pos.Bottom (viewportSettingsEditor), Width = Dim.Fill (), Height = Dim.Fill () }; app.Add (view); - // Add Scroll Setting UI to Padding - view.Padding!.Thickness = view.Padding.Thickness with { Top = view.Padding.Thickness.Top + 6 }; - view.Padding.CanFocus = true; - - Label frameLabel = new () - { - Text = "Frame\nContent", - Id = "frameLabel", - Y = 0 - }; - view.Padding.Add (frameLabel); - - var cbAllowNegativeX = new CheckBox - { - Title = "Allow _X < 0", - Y = Pos.Bottom (frameLabel), - CanFocus = true - }; - cbAllowNegativeX.CheckedState = view.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.AllowNegativeX) ? CheckState.Checked : CheckState.UnChecked; - - view.Padding.Add (cbAllowNegativeX); - - var cbAllowNegativeY = new CheckBox - { - Title = "Allow _Y < 0", - X = Pos.Right (cbAllowNegativeX) + 1, - Y = Pos.Bottom (frameLabel), - CanFocus = true, - }; - cbAllowNegativeY.CheckedState = view.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.AllowNegativeY) ? CheckState.Checked : CheckState.UnChecked; - - view.Padding.Add (cbAllowNegativeY); - - var cbAllowXGreaterThanContentWidth = new CheckBox - { - Title = "All_ow X > Content", - Y = Pos.Bottom (cbAllowNegativeX), - CanFocus = true - }; - cbAllowXGreaterThanContentWidth.CheckedState = view.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.AllowXGreaterThanContentWidth) ? CheckState.Checked : CheckState.UnChecked; - - view.Padding.Add (cbAllowXGreaterThanContentWidth); - - void AllowNegativeXToggle (object sender, CancelEventArgs e) - { - if (e.NewValue == CheckState.Checked) - { - view.ViewportSettings |= Terminal.Gui.ViewportSettings.AllowNegativeX; - } - else - { - view.ViewportSettings &= ~Terminal.Gui.ViewportSettings.AllowNegativeX; - } - } - - void AllowXGreaterThanContentWidthToggle (object sender, CancelEventArgs e) - { - if (e.NewValue == CheckState.Checked) - { - view.ViewportSettings |= Terminal.Gui.ViewportSettings.AllowXGreaterThanContentWidth; - } - else - { - view.ViewportSettings &= ~Terminal.Gui.ViewportSettings.AllowXGreaterThanContentWidth; - } - } - - var cbAllowYGreaterThanContentHeight = new CheckBox - { - Title = "Allo_w Y > Content", - X = Pos.Right (cbAllowXGreaterThanContentWidth) + 1, - Y = Pos.Bottom (cbAllowNegativeX), - CanFocus = true - }; - cbAllowYGreaterThanContentHeight.CheckedState = view.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.AllowYGreaterThanContentHeight) ? CheckState.Checked : CheckState.UnChecked; - - view.Padding.Add (cbAllowYGreaterThanContentHeight); - - void AllowNegativeYToggle (object sender, CancelEventArgs e) - { - if (e.NewValue == CheckState.Checked) - { - view.ViewportSettings |= Terminal.Gui.ViewportSettings.AllowNegativeY; - } - else - { - view.ViewportSettings &= ~Terminal.Gui.ViewportSettings.AllowNegativeY; - } - } - - void AllowYGreaterThanContentHeightToggle (object sender, CancelEventArgs e) - { - if (e.NewValue == CheckState.Checked) - { - view.ViewportSettings |= Terminal.Gui.ViewportSettings.AllowYGreaterThanContentHeight; - } - else - { - view.ViewportSettings &= ~Terminal.Gui.ViewportSettings.AllowYGreaterThanContentHeight; - } - } - - var labelContentSize = new Label - { - Title = "ContentSi_ze:", - Y = Pos.Bottom (cbAllowYGreaterThanContentHeight) - }; - - NumericUpDown contentSizeWidth = new NumericUpDown - { - Value = view.GetContentSize ().Width, - X = Pos.Right (labelContentSize) + 1, - Y = Pos.Top (labelContentSize), - CanFocus = true - }; - contentSizeWidth.ValueChanging += ContentSizeWidthValueChanged; - - void ContentSizeWidthValueChanged (object sender, CancelEventArgs e) - { - if (e.NewValue < 0) - { - e.Cancel = true; - - return; - } - // BUGBUG: set_ContentSize is supposed to be `protected`. - view.SetContentSize (view.GetContentSize () with { Width = e.NewValue }); - } - - var labelComma = new Label - { - Title = ",", - X = Pos.Right (contentSizeWidth), - Y = Pos.Top (labelContentSize) - }; - - NumericUpDown contentSizeHeight = new NumericUpDown - { - Value = view.GetContentSize ().Height, - X = Pos.Right (labelComma) + 1, - Y = Pos.Top (labelContentSize), - CanFocus = true - }; - contentSizeHeight.ValueChanging += ContentSizeHeightValueChanged; - - void ContentSizeHeightValueChanged (object sender, CancelEventArgs e) - { - if (e.NewValue < 0) - { - e.Cancel = true; - - return; - } - // BUGBUG: set_ContentSize is supposed to be `protected`. - view.SetContentSize (view.GetContentSize () with { Height = e.NewValue }); - } - - var cbClearContentOnly = new CheckBox - { - Title = "C_learContentOnly", - X = Pos.Right (contentSizeHeight) + 1, - Y = Pos.Top (labelContentSize), - CanFocus = true - }; - cbClearContentOnly.CheckedState = view.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.ClearContentOnly) ? CheckState.Checked : CheckState.UnChecked; - cbClearContentOnly.CheckedStateChanging += ClearContentOnlyToggle; - - void ClearContentOnlyToggle (object sender, CancelEventArgs e) - { - if (e.NewValue == CheckState.Checked) - { - view.ViewportSettings |= Terminal.Gui.ViewportSettings.ClearContentOnly; - } - else - { - view.ViewportSettings &= ~Terminal.Gui.ViewportSettings.ClearContentOnly; - } - } - - var cbClipContentOnly = new CheckBox - { - Title = "_ClipContentOnly", - X = Pos.Right (cbClearContentOnly) + 1, - Y = Pos.Top (labelContentSize), - CanFocus = true - }; - cbClipContentOnly.CheckedState = view.ViewportSettings.HasFlag (Terminal.Gui.ViewportSettings.ClipContentOnly) ? CheckState.Checked : CheckState.UnChecked; - cbClipContentOnly.CheckedStateChanging += ClipContentOnlyOnlyToggle; - - void ClipContentOnlyOnlyToggle (object sender, CancelEventArgs e) - { - if (e.NewValue == CheckState.Checked) - { - view.ViewportSettings |= Terminal.Gui.ViewportSettings.ClipContentOnly; - } - else - { - view.ViewportSettings &= ~Terminal.Gui.ViewportSettings.ClipContentOnly; - } - } - - var cbVerticalScrollBar = new CheckBox - { - Title = "_VerticalScrollBar.Visible", - X = 0, - Y = Pos.Bottom (labelContentSize), - CanFocus = false - }; - cbVerticalScrollBar.CheckedState = view.VerticalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked; - cbVerticalScrollBar.CheckedStateChanging += VerticalScrollBarToggle; - - void VerticalScrollBarToggle (object sender, CancelEventArgs e) - { - view.VerticalScrollBar.Visible = e.NewValue == CheckState.Checked; - } - - var cbHorizontalScrollBar = new CheckBox - { - Title = "_HorizontalScrollBar.Visible", - X = Pos.Right (cbVerticalScrollBar) + 1, - Y = Pos.Bottom (labelContentSize), - CanFocus = false, - }; - cbHorizontalScrollBar.CheckedState = view.HorizontalScrollBar.Visible ? CheckState.Checked : CheckState.UnChecked; - cbHorizontalScrollBar.CheckedStateChanging += HorizontalScrollBarToggle; - - void HorizontalScrollBarToggle (object sender, CancelEventArgs e) - { - view.HorizontalScrollBar.Visible = e.NewValue == CheckState.Checked; - } - - view.VerticalScrollBar.AutoShow = true; - var cbAutoShowVerticalScrollBar = new CheckBox - { - Title = "VerticalScrollBar._AutoShow", - X = Pos.Right (cbHorizontalScrollBar) + 1, - Y = Pos.Bottom (labelContentSize), - CanFocus = false, - CheckedState = view.VerticalScrollBar.AutoShow ? CheckState.Checked : CheckState.UnChecked - }; - cbAutoShowVerticalScrollBar.CheckedStateChanging += AutoShowVerticalScrollBarToggle; - - void AutoShowVerticalScrollBarToggle (object sender, CancelEventArgs e) - { - view.VerticalScrollBar.AutoShow = e.NewValue == CheckState.Checked; - } - - view.HorizontalScrollBar.AutoShow = true; - var cbAutoShowHorizontalScrollBar = new CheckBox - { - Title = "HorizontalScrollBar.A_utoShow ", - X = Pos.Right (cbAutoShowVerticalScrollBar) + 1, - Y = Pos.Bottom (labelContentSize), - CanFocus = false, - CheckedState = view.HorizontalScrollBar.AutoShow ? CheckState.Checked : CheckState.UnChecked - }; - cbAutoShowHorizontalScrollBar.CheckedStateChanging += AutoShowHorizontalScrollBarToggle; - - void AutoShowHorizontalScrollBarToggle (object sender, CancelEventArgs e) - { - view.HorizontalScrollBar.AutoShow = e.NewValue == CheckState.Checked; - } - - cbAllowNegativeX.CheckedStateChanging += AllowNegativeXToggle; - cbAllowNegativeY.CheckedStateChanging += AllowNegativeYToggle; - - cbAllowXGreaterThanContentWidth.CheckedStateChanging += AllowXGreaterThanContentWidthToggle; - cbAllowYGreaterThanContentHeight.CheckedStateChanging += AllowYGreaterThanContentHeightToggle; - - - view.Padding.Add (labelContentSize, contentSizeWidth, labelComma, contentSizeHeight, cbClearContentOnly, cbClipContentOnly, cbVerticalScrollBar, cbHorizontalScrollBar, cbAutoShowVerticalScrollBar, cbAutoShowHorizontalScrollBar); - // Add demo views to show that things work correctly var textField = new TextField { X = 20, Y = 7, Width = 15, Text = "Test Te_xtField" }; @@ -436,7 +172,7 @@ void AutoShowHorizontalScrollBarToggle (object sender, CancelEventArgs MessageBox.Query ("Hi", $"You pressed {((Button)sender)?.Text}", "_Ok"); @@ -475,12 +211,19 @@ void AutoShowHorizontalScrollBarToggle (object sender, CancelEventArgs { editor.ViewToEdit = view; }; + editor.Initialized += (s, e) => + { + editor.ViewToEdit = view; + }; editor.AutoSelectViewToEdit = true; editor.AutoSelectSuperView = view; editor.AutoSelectAdornments = false; + view.Initialized += (s, e) => + { + viewportSettingsEditor.ViewToEdit = view; + }; view.SetFocus (); Application.Run (app); app.Dispose ();