diff --git a/Terminal.Gui/View/Orientation/IOrientation.cs b/Terminal.Gui/View/Orientation/IOrientation.cs new file mode 100644 index 000000000..908ce32bf --- /dev/null +++ b/Terminal.Gui/View/Orientation/IOrientation.cs @@ -0,0 +1,127 @@ + +namespace Terminal.Gui; +using System; + +/// +/// Implement this interface to provide orientation support. +/// +public interface IOrientation +{ + /// + /// Gets or sets the orientation of the View. + /// + Orientation Orientation { get; set; } + + /// + /// Raised when is changing. Can be cancelled. + /// + public event EventHandler> OrientationChanging; + + /// + /// Called when is changing. + /// + /// The current orienation. + /// The new orienation. + /// to cancel the change. + public bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation) { return false; } + + /// + /// + /// + public event EventHandler> OrientationChanged; + + /// + /// Called when has been changed. + /// + /// + /// + /// + public void OnOrientationChanged (Orientation oldOrientation, Orientation newOrientation) { return; } +} + + +/// +/// Helper class for implementing . +/// +public class OrientationHelper +{ + private Orientation _orientation = Orientation.Vertical; + private readonly IOrientation _owner; + + /// + /// Initializes a new instance of the class. + /// + /// + public OrientationHelper (IOrientation owner) + { + _owner = owner; + } + + /// + /// Gets or sets the orientation of the View. + /// + public Orientation Orientation + { + get => _orientation; + set + { + var args = new CancelEventArgs (in _orientation, ref value); + OrientationChanging?.Invoke (_owner, args); + if (args.Cancel) + { + return; + } + + if (_owner?.OnOrientationChanging (value, _orientation) ?? false) + { + return; + } + + Orientation old = _orientation; + if (_orientation != value) + { + _orientation = value; + _owner.Orientation = value; + } + + args = new CancelEventArgs (in old, ref _orientation); + OrientationChanged?.Invoke (_owner, args); + + _owner?.OnOrientationChanged (old, _orientation); + } + } + + /// + /// + /// + public event EventHandler> OrientationChanging; + + /// + /// + /// + /// + /// + /// + protected bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation) + { + return _owner?.OnOrientationChanging (currentOrientation, newOrientation) ?? false; + } + + /// + /// + /// + public event EventHandler> OrientationChanged; + + /// + /// + /// + /// + /// + /// + protected void OnOrientationChanged (Orientation oldOrientation, Orientation newOrientation) + { + _owner?.OnOrientationChanged (oldOrientation, newOrientation); + } +} + + diff --git a/Terminal.Gui/Views/GraphView/Orientation.cs b/Terminal.Gui/View/Orientation/Orientation.cs similarity index 100% rename from Terminal.Gui/Views/GraphView/Orientation.cs rename to Terminal.Gui/View/Orientation/Orientation.cs diff --git a/Terminal.Gui/Views/OrientationEventArgs.cs b/Terminal.Gui/Views/OrientationEventArgs.cs deleted file mode 100644 index 8a633ca83..000000000 --- a/Terminal.Gui/Views/OrientationEventArgs.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Terminal.Gui; - -/// for events. -public class OrientationEventArgs : EventArgs -{ - /// Constructs a new instance. - /// the new orientation - public OrientationEventArgs (Orientation orientation) - { - Orientation = orientation; - Cancel = false; - } - - /// If set to true, the orientation change operation will be canceled, if applicable. - public bool Cancel { get; set; } - - /// The new orientation. - public Orientation Orientation { get; set; } -} \ No newline at end of file diff --git a/Terminal.Gui/Views/RadioGroup.cs b/Terminal.Gui/Views/RadioGroup.cs index f0dc5174b..1565193b3 100644 --- a/Terminal.Gui/Views/RadioGroup.cs +++ b/Terminal.Gui/Views/RadioGroup.cs @@ -1,14 +1,14 @@ namespace Terminal.Gui; /// Displays a group of labels each with a selected indicator. Only one of those can be selected at a given time. -public class RadioGroup : View, IDesignable +public class RadioGroup : View, IDesignable, IOrientation { private int _cursor; private List<(int pos, int length)> _horizontal; private int _horizontalSpace = 2; - private Orientation _orientation = Orientation.Vertical; private List _radioLabels = []; private int _selected; + private readonly OrientationHelper _orientationHelper; /// /// Initializes a new instance of the class. @@ -103,6 +103,13 @@ public class RadioGroup : View, IDesignable return true; }); + _orientationHelper = new OrientationHelper (this); + _orientationHelper.OrientationChanging += (sender, e) => OrientationChanging?.Invoke (this, e); + _orientationHelper.OrientationChanged += (sender, e) => OrientationChanged?.Invoke (this, e); + + //OrientationChanging += (sender, e) => OnOrientationChanging (e.CurrentValue, e.NewValue); + //OrientationChanged += (sender, e) => OnOrientationChanged (e.CurrentValue, e.NewValue); + SetupKeyBindings (); LayoutStarted += RadioGroup_LayoutStarted; @@ -142,15 +149,15 @@ public class RadioGroup : View, IDesignable int viewportX = e.MouseEvent.Position.X; int viewportY = e.MouseEvent.Position.Y; - int pos = _orientation == Orientation.Horizontal ? viewportX : viewportY; + int pos = Orientation == Orientation.Horizontal ? viewportX : viewportY; - int rCount = _orientation == Orientation.Horizontal + int rCount = Orientation == Orientation.Horizontal ? _horizontal.Last ().pos + _horizontal.Last ().length : _radioLabels.Count; if (pos < rCount) { - int c = _orientation == Orientation.Horizontal + int c = Orientation == Orientation.Horizontal ? _horizontal.FindIndex (x => x.pos <= viewportX && x.pos + x.length - 2 >= viewportX) : viewportY; @@ -173,7 +180,7 @@ public class RadioGroup : View, IDesignable get => _horizontalSpace; set { - if (_horizontalSpace != value && _orientation == Orientation.Horizontal) + if (_horizontalSpace != value && Orientation == Orientation.Horizontal) { _horizontalSpace = value; UpdateTextFormatterText (); @@ -182,16 +189,6 @@ public class RadioGroup : View, IDesignable } } - /// - /// Gets or sets the for this . The default is - /// . - /// - public Orientation Orientation - { - get => _orientation; - set => OnOrientationChanged (value); - } - /// /// The radio labels to display. A key binding will be added for each radio enabling the user to select /// and/or focus the radio label using the keyboard. See for details on how HotKeys work. @@ -323,30 +320,45 @@ public class RadioGroup : View, IDesignable } } - /// Called when the view orientation has changed. Invokes the event. - /// - /// True of the event was cancelled. - public virtual bool OnOrientationChanged (Orientation newOrientation) + /// + /// Gets or sets the for this . The default is + /// . + /// + public Orientation Orientation { - var args = new OrientationEventArgs (newOrientation); - OrientationChanged?.Invoke (this, args); - - if (!args.Cancel) - { - _orientation = newOrientation; - SetupKeyBindings (); - SetContentSize (); - } - - return args.Cancel; + get => _orientationHelper.Orientation; + set => _orientationHelper.Orientation = value; } + #region IOrientation + /// + public event EventHandler> OrientationChanging; + + /// + public bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation) + { + return false; + } + + /// + public event EventHandler> OrientationChanged; + + /// Called when has changed. + /// + /// + public void OnOrientationChanged (Orientation oldOrientation, Orientation newOrientation) + { + SetupKeyBindings (); + SetContentSize (); + } + #endregion IOrientation + // TODO: This should be cancelable /// Called whenever the current selected item changes. Invokes the event. /// /// public virtual void OnSelectedItemChanged (int selectedItem, int previousSelectedItem) - { + { if (_selected == selectedItem) { return; @@ -355,12 +367,6 @@ public class RadioGroup : View, IDesignable SelectedItemChanged?.Invoke (this, new (selectedItem, previousSelectedItem)); } - /// - /// Fired when the view orientation has changed. Can be cancelled by setting - /// to true. - /// - public event EventHandler OrientationChanged; - /// public override Point? PositionCursor () { @@ -429,7 +435,7 @@ public class RadioGroup : View, IDesignable private void SetContentSize () { - switch (_orientation) + switch (Orientation) { case Orientation.Vertical: var width = 0; @@ -469,3 +475,27 @@ public class RadioGroup : View, IDesignable return true; } } + +public class RadioGroupHorizontal : RadioGroup, IOrientation +{ + private bool _preventOrientationChange = false; + public RadioGroupHorizontal () : base () + { + Orientation = Orientation.Horizontal; + _preventOrientationChange = true; + + OrientationChanging += RadioGroupHorizontal_OrientationChanging; + } + + private void RadioGroupHorizontal_OrientationChanging (object sender, CancelEventArgs e) + { + //e.Cancel = _preventOrientationChange; + } + + /// + bool IOrientation.OnOrientationChanging (Orientation currrentOrientation, Orientation newOrientation) + { + return _preventOrientationChange; + } + +} \ No newline at end of file diff --git a/Terminal.Gui/Views/Slider.cs b/Terminal.Gui/Views/Slider.cs index 61ac401d6..a613ce7d5 100644 --- a/Terminal.Gui/Views/Slider.cs +++ b/Terminal.Gui/Views/Slider.cs @@ -310,17 +310,16 @@ public class Slider : View #region Events /// - /// Fired when the slider orientation has changed. Can be cancelled by setting - /// to true. + /// Fired when the slider orientation has changed. Can be cancelled. /// - public event EventHandler OrientationChanged; + public event EventHandler> OrientationChanged; /// Called when the slider orientation has changed. Invokes the event. /// /// True of the event was cancelled. public virtual bool OnOrientationChanged (Orientation newOrientation) { - var args = new OrientationEventArgs (newOrientation); + var args = new CancelEventArgs (in _config._sliderOrientation, ref newOrientation); OrientationChanged?.Invoke (this, args); if (!args.Cancel) diff --git a/UICatalog/Scenarios/ExpanderButton.cs b/UICatalog/Scenarios/ExpanderButton.cs index 2959d338a..f0d5c8073 100644 --- a/UICatalog/Scenarios/ExpanderButton.cs +++ b/UICatalog/Scenarios/ExpanderButton.cs @@ -74,7 +74,7 @@ public class ExpanderButton : Button /// True of the event was cancelled. protected virtual bool OnOrientationChanging (Orientation newOrientation) { - var args = new OrientationEventArgs (newOrientation); + var args = new CancelEventArgs (in _orientation, ref newOrientation); OrientationChanging?.Invoke (this, args); if (!args.Cancel) @@ -105,10 +105,9 @@ public class ExpanderButton : Button } /// - /// Fired when the orientation has changed. Can be cancelled by setting - /// to true. + /// Fired when the orientation has changed. Can be cancelled. /// - public event EventHandler OrientationChanging; + public event EventHandler> OrientationChanging; /// /// The glyph to display when the view is collapsed.