diff --git a/Terminal.Gui/View/View.Content.cs b/Terminal.Gui/View/View.Content.cs index 719427d70..3f3790ddd 100644 --- a/Terminal.Gui/View/View.Content.cs +++ b/Terminal.Gui/View/View.Content.cs @@ -348,6 +348,14 @@ public partial class View } } + if (!ViewportSettings.HasFlag (ViewportSettings.AllowNegativeXWhenWidthGreaterThanContentWidth)) + { + if (Viewport.Width > GetContentSize ().Width) + { + newViewport.X = 0; + } + } + if (!ViewportSettings.HasFlag (ViewportSettings.AllowYGreaterThanContentHeight)) { if (newViewport.Y >= GetContentSize ().Height) @@ -356,6 +364,14 @@ public partial class View } } + if (!ViewportSettings.HasFlag (ViewportSettings.AllowNegativeYWhenHeightGreaterThanContentHeight)) + { + if (Viewport.Height > GetContentSize ().Height) + { + newViewport.Y = 0; + } + } + // IMPORTANT: Check for negative location AFTER checking for location greater than content width if (!ViewportSettings.HasFlag (ViewportSettings.AllowNegativeY)) { diff --git a/Terminal.Gui/View/ViewportSettings.cs b/Terminal.Gui/View/ViewportSettings.cs index a84899394..32b734067 100644 --- a/Terminal.Gui/View/ViewportSettings.cs +++ b/Terminal.Gui/View/ViewportSettings.cs @@ -76,7 +76,7 @@ public enum ViewportSettings AllowYGreaterThanContentHeight = 8, /// - /// If set, .Size can be set values greater than + /// If set, .Location can be set values greater than /// enabling scrolling beyond the bottom-right /// of the content area. /// @@ -87,11 +87,42 @@ public enum ViewportSettings /// AllowLocationGreaterThanContentSize = AllowXGreaterThanContentWidth | AllowYGreaterThanContentHeight, + /// + /// If set and .Width is greater than + /// .Width .X can be negative. + /// + /// When not set, .X will be constrained to non-negative values, preventing + /// scrolling beyond the left of the Viewport. + /// + /// + /// This can be useful in infinite scrolling scenarios. + /// + /// + AllowNegativeXWhenWidthGreaterThanContentWidth = 16, + + /// + /// If set and .Height is greater than + /// .Height .Y can be negative. + /// + /// When not set, .Y will be constrained to non-negative values, preventing + /// scrolling above the top of the Viewport. + /// + /// + /// This can be useful in infinite scrolling scenarios. + /// + /// + AllowNegativeYWhenHeightGreaterThanContentHeight = 32, + + /// + /// The combination of and . + /// + AllowNegativeLocationWhenSizeGreaterThanContentSize = AllowNegativeXWhenWidthGreaterThanContentWidth | AllowNegativeYWhenHeightGreaterThanContentHeight, + /// /// By default, clipping is applied to the . Setting this flag will cause clipping to be /// applied to the visible content area. /// - ClipContentOnly = 16, + ClipContentOnly = 64, /// /// If set will clear only the portion of the content @@ -100,5 +131,5 @@ public enum ViewportSettings /// must be set for this setting to work (clipping beyond the visible area must be /// disabled). /// - ClearContentOnly = 32, + ClearContentOnly = 128, } diff --git a/Terminal.Gui/Views/ScrollBar/ScrollBar.cs b/Terminal.Gui/Views/ScrollBar/ScrollBar.cs index bc1892c8b..10df243a1 100644 --- a/Terminal.Gui/Views/ScrollBar/ScrollBar.cs +++ b/Terminal.Gui/Views/ScrollBar/ScrollBar.cs @@ -17,7 +17,8 @@ namespace Terminal.Gui; /// See the Scrolling Deep Dive. /// /// -/// By default, the built-in View scrollbars (/) have both and set to +/// By default, the built-in View scrollbars (/ +/// ) have both and set to /// . /// To enable them, either set set to or explicitly set /// @@ -184,7 +185,8 @@ public class ScrollBar : View, IOrientation, IDesignable #endregion /// - /// Gets or sets the amount each mouse wheel event, or click on the increment/decrement buttons, will incremenet/decrement the . + /// Gets or sets the amount each mouse wheel event, or click on the increment/decrement buttons, will + /// incremenet/decrement the . /// /// /// The default is 1. diff --git a/Terminal.Gui/Views/ScrollBar/ScrollSlider.cs b/Terminal.Gui/Views/ScrollBar/ScrollSlider.cs index 19159b8cf..899ee56e0 100644 --- a/Terminal.Gui/Views/ScrollBar/ScrollSlider.cs +++ b/Terminal.Gui/Views/ScrollBar/ScrollSlider.cs @@ -1,8 +1,6 @@ #nullable enable using System.ComponentModel; -using System.Diagnostics; -using System.Drawing; namespace Terminal.Gui; @@ -13,11 +11,6 @@ namespace Terminal.Gui; /// /// /// -/// If is set, it will be displayed centered within the slider. Set -/// to automatically have the Text -/// be show what percent the slider is to the Superview's Viewport size. -/// -/// /// Used to represent the proportion of the visible content to the Viewport in a . /// /// @@ -105,7 +98,7 @@ public class ScrollSlider : View, IOrientation, IDesignable /// /// Gets or sets the size of the ScrollSlider. This is a helper that gets or sets Width or Height depending /// on . The size will be clamped between 1 and the dimension of - /// the 's Viewport. + /// the 's Viewport. /// /// /// diff --git a/UICatalog/Scenarios/CharacterMap/CharMap.cs b/UICatalog/Scenarios/CharacterMap/CharMap.cs index 62ab02f46..6f4093a36 100644 --- a/UICatalog/Scenarios/CharacterMap/CharMap.cs +++ b/UICatalog/Scenarios/CharacterMap/CharMap.cs @@ -134,7 +134,6 @@ public class CharMap : View, IDesignable KeyBindings.Add (Key.End, Command.End); MouseClick += Handle_MouseClick; - MouseEvent += Handle_MouseEvent; SetContentSize (new (COLUMN_WIDTH * 16 + RowLabelWidth, MAX_CODE_POINT / 16 * _rowHeight + HEADER_HEIGHT)); @@ -468,39 +467,36 @@ public class CharMap : View, IDesignable // TODO: Use this to demonstrate using a popover to show glyph info on hover public event EventHandler? Hover; - private void Handle_MouseEvent (object? sender, MouseEventArgs e) + /// + protected override bool OnMouseEvent (MouseEventArgs mouseEvent) { - if (e.Flags == MouseFlags.WheeledDown) + if (mouseEvent.Flags == MouseFlags.WheeledDown) { ScrollVertical (1); - e.Handled = true; - - return; + return mouseEvent.Handled = true; } - if (e.Flags == MouseFlags.WheeledUp) + if (mouseEvent.Flags == MouseFlags.WheeledUp) { ScrollVertical (-1); - e.Handled = true; - - return; + return mouseEvent.Handled = true; } - if (e.Flags == MouseFlags.WheeledRight) + if (mouseEvent.Flags == MouseFlags.WheeledRight) { ScrollHorizontal (1); - e.Handled = true; - - return; + return mouseEvent.Handled = true; } - if (e.Flags == MouseFlags.WheeledLeft) + if (mouseEvent.Flags == MouseFlags.WheeledLeft) { ScrollHorizontal (-1); - e.Handled = true; + return mouseEvent.Handled = true; } - } + return false; + } + private void Handle_MouseClick (object? sender, MouseEventArgs me) { if (me.Flags != MouseFlags.ReportMousePosition && me.Flags != MouseFlags.Button1Clicked && me.Flags != MouseFlags.Button1DoubleClicked) diff --git a/UICatalog/Scenarios/Scrolling.cs b/UICatalog/Scenarios/Scrolling.cs index 78eb9355a..1ff83a96b 100644 --- a/UICatalog/Scenarios/Scrolling.cs +++ b/UICatalog/Scenarios/Scrolling.cs @@ -29,7 +29,6 @@ public class Scrolling : Scenario Width = 60, Height = 20 }; - demoView.SetContentSize (new (80, 25)); label.Text = $"{demoView}\nContentSize: {demoView.GetContentSize ()}\nViewport.Location: {demoView.Viewport.Location}"; @@ -149,6 +148,8 @@ public class DemoView : View private void OnInitialized (object sender, EventArgs e) { + SetContentSize (new (80, 25)); + var rulerView = new View { Height = Dim.Fill (), @@ -161,6 +162,16 @@ public class DemoView : View Add (rulerView); + var centeredLabel = new Label () + { + X = Pos.Center (), + Y = Pos.Center (), + TextAlignment = Alignment.Center, + VerticalTextAlignment = Alignment.Center, + Text = $"This label is centred.\nContentSize is {GetContentSize ()}" + }; + Add (centeredLabel); + var pressMeButton = new Button { X = 1, @@ -209,7 +220,7 @@ public class DemoView : View Y = 40, Width = 50, ColorScheme = Colors.ColorSchemes ["Error"], - Text = "Last line" + Text = "Last line - Beyond content area @ Y = 40" } ); @@ -229,4 +240,33 @@ public class DemoView : View }; Add (anchorButton); } + + protected override bool OnMouseEvent (MouseEventArgs mouseEvent) + { + if (mouseEvent.Flags == MouseFlags.WheeledDown) + { + ScrollVertical (1); + return mouseEvent.Handled = true; + } + + if (mouseEvent.Flags == MouseFlags.WheeledUp) + { + ScrollVertical (-1); + return mouseEvent.Handled = true; + } + + if (mouseEvent.Flags == MouseFlags.WheeledRight) + { + ScrollHorizontal (1); + return mouseEvent.Handled = true; + } + + if (mouseEvent.Flags == MouseFlags.WheeledLeft) + { + ScrollHorizontal (-1); + return mouseEvent.Handled = true; + } + + return false; + } }