diff --git a/Terminal.Gui/View/Orientation/IOrientation.cs b/Terminal.Gui/View/Orientation/IOrientation.cs
index 25bdf7fcc..52bf2f49f 100644
--- a/Terminal.Gui/View/Orientation/IOrientation.cs
+++ b/Terminal.Gui/View/Orientation/IOrientation.cs
@@ -37,100 +37,4 @@ public interface IOrientation
///
///
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
- {
- if (_orientation == value)
- {
- return;
- }
-
- 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;
-
- if (_owner is { })
- {
- _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);
- }
-}
-
-
+}
\ No newline at end of file
diff --git a/Terminal.Gui/View/Orientation/OrientationHelper.cs b/Terminal.Gui/View/Orientation/OrientationHelper.cs
index f2278ed98..613557e10 100644
--- a/Terminal.Gui/View/Orientation/OrientationHelper.cs
+++ b/Terminal.Gui/View/Orientation/OrientationHelper.cs
@@ -3,6 +3,14 @@
///
/// Helper class for implementing .
///
+///
+///
+/// Implements the standard pattern for changing/changed events.
+///
+///
+/// Views that implement should add a OrientationHelper property. See as an example.
+///
+///
public class OrientationHelper
{
private Orientation _orientation = Orientation.Vertical;
@@ -11,11 +19,8 @@ public class OrientationHelper
///
/// Initializes a new instance of the class.
///
- ///
- public OrientationHelper (IOrientation owner)
- {
- _owner = owner;
- }
+ /// Specifies the object that owns this helper instance.
+ public OrientationHelper (IOrientation owner) { _owner = owner; }
///
/// Gets or sets the orientation of the View.
@@ -30,19 +35,25 @@ public class OrientationHelper
return;
}
- var args = new CancelEventArgs (in _orientation, ref value);
- OrientationChanging?.Invoke (_owner, args);
- if (args.Cancel)
- {
- return;
- }
-
+ // Best practice is to invoke the virtual method first.
+ // This allows derived classes to handle the event and potentially cancel it.
if (_owner?.OnOrientationChanging (value, _orientation) ?? false)
{
return;
}
+ // If the event is not canceled by the virtual method, raise the event to notify any external subscribers.
+ CancelEventArgs args = new (in _orientation, ref value);
+ OrientationChanging?.Invoke (_owner, args);
+
+ if (args.Cancel)
+ {
+ return;
+ }
+
+ // If the event is not canceled, update the value.
Orientation old = _orientation;
+
if (_orientation != value)
{
_orientation = value;
@@ -53,42 +64,40 @@ public class OrientationHelper
}
}
- args = new CancelEventArgs (in old, ref _orientation);
- OrientationChanged?.Invoke (_owner, args);
-
+ // Best practice is to invoke the virtual method first.
_owner?.OnOrientationChanged (old, _orientation);
+
+ // Even though Changed is not cancelable, it is still a good practice to raise the event after.
+ args = new (in old, ref _orientation);
+ OrientationChanged?.Invoke (_owner, args);
}
}
///
- ///
+ /// Raised when the orientation is changing. This is cancelable.
///
+ ///
+ ///
+ /// Views that implement should raise after the orientation has changed
+ /// (_orientationHelper.OrientationChanging += (sender, e) => OrientationChanging?.Invoke (this, e);).
+ ///
+ ///
+ /// This event will be raised after the method is called (assuming it was not canceled).
+ ///
+ ///
public event EventHandler> OrientationChanging;
///
- ///
- ///
- ///
- ///
- ///
- protected bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation)
- {
- return _owner?.OnOrientationChanging (currentOrientation, newOrientation) ?? false;
- }
-
- ///
- ///
+ /// Raised when the orientation has changed.
///
+ ///
+ ///
+ /// Views that implement should raise after the orientation has changed
+ /// (_orientationHelper.OrientationChanged += (sender, e) => OrientationChanged?.Invoke (this, e);).
+ ///
+ ///
+ /// This event will be raised after the method is called.
+ ///
+ ///
public event EventHandler> OrientationChanged;
-
- ///
- ///
- ///
- ///
- ///
- ///
- protected void OnOrientationChanged (Orientation oldOrientation, Orientation newOrientation)
- {
- _owner?.OnOrientationChanged (oldOrientation, newOrientation);
- }
}
diff --git a/Terminal.Gui/Views/RadioGroup.cs b/Terminal.Gui/Views/RadioGroup.cs
index 49e821772..1113cf9de 100644
--- a/Terminal.Gui/Views/RadioGroup.cs
+++ b/Terminal.Gui/Views/RadioGroup.cs
@@ -44,6 +44,7 @@ public class RadioGroup : View, IDesignable, IOrientation
{
return false;
}
+
MoveDownRight ();
return true;
@@ -58,6 +59,7 @@ public class RadioGroup : View, IDesignable, IOrientation
{
return false;
}
+
MoveHome ();
return true;
@@ -72,6 +74,7 @@ public class RadioGroup : View, IDesignable, IOrientation
{
return false;
}
+
MoveEnd ();
return true;
@@ -93,6 +96,7 @@ public class RadioGroup : View, IDesignable, IOrientation
ctx =>
{
SetFocus ();
+
if (ctx.KeyBinding?.Context is { } && (int)ctx.KeyBinding?.Context! < _radioLabels.Count)
{
SelectedItem = (int)ctx.KeyBinding?.Context!;
@@ -103,13 +107,10 @@ public class RadioGroup : View, IDesignable, IOrientation
return true;
});
- _orientationHelper = new OrientationHelper (this);
+ _orientationHelper = new (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;
@@ -331,16 +332,14 @@ public class RadioGroup : View, IDesignable, IOrientation
}
#region IOrientation
- ///
+
+ ///
public event EventHandler> OrientationChanging;
- ///
- public bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation)
- {
- return false;
- }
+ ///
+ public bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation) { return false; }
- ///
+ ///
public event EventHandler> OrientationChanged;
/// Called when has changed.
@@ -351,6 +350,7 @@ public class RadioGroup : View, IDesignable, IOrientation
SetupKeyBindings ();
SetContentSize ();
}
+
#endregion IOrientation
// TODO: This should be cancelable
@@ -363,6 +363,7 @@ public class RadioGroup : View, IDesignable, IOrientation
{
return;
}
+
_selected = selectedItem;
SelectedItemChanged?.Invoke (this, new (selectedItem, previousSelectedItem));
}
@@ -384,6 +385,7 @@ public class RadioGroup : View, IDesignable, IOrientation
{
x = _horizontal [_cursor].pos;
}
+
break;
default:
@@ -470,34 +472,11 @@ public class RadioGroup : View, IDesignable, IOrientation
}
}
- ///
+ ///
public bool EnableForDesign ()
{
RadioLabels = new [] { "Option _1", "Option _2", "Option _3" };
+
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/UnitTests/View/Orientation/OrientationTests.cs b/UnitTests/View/Orientation/OrientationTests.cs
index 3e5734be0..01eeda71f 100644
--- a/UnitTests/View/Orientation/OrientationTests.cs
+++ b/UnitTests/View/Orientation/OrientationTests.cs
@@ -25,14 +25,19 @@ public class OrientationTests
public bool CancelOnOrientationChanging { get; set; }
+ public bool OnOrientationChangingCalled { get; private set; }
+ public bool OnOrientationChangedCalled { get; private set; }
+
public bool OnOrientationChanging (Orientation currentOrientation, Orientation newOrientation)
{
+ OnOrientationChangingCalled = true;
// Custom logic before orientation changes
return CancelOnOrientationChanging; // Return true to cancel the change
}
public void OnOrientationChanged (Orientation oldOrientation, Orientation newOrientation)
{
+ OnOrientationChangedCalled = true;
// Custom logic after orientation has changed
}
}
@@ -87,4 +92,45 @@ public class OrientationTests
Assert.False (orientationChanged, "OrientationChanged event was invoked despite cancellation.");
Assert.Equal (Orientation.Vertical, customView.Orientation); // Assuming Vertical is the default orientation
}
+
+
+ [Fact]
+ public void OrientationChanging_VirtualMethodCalledBeforeEvent ()
+ {
+ // Arrange
+ var radioGroup = new CustomView ();
+ bool eventCalled = false;
+
+ radioGroup.OrientationChanging += (sender, e) =>
+ {
+ eventCalled = true;
+ Assert.True (radioGroup.OnOrientationChangingCalled, "OnOrientationChanging was not called before the event.");
+ };
+
+ // Act
+ radioGroup.Orientation = Orientation.Horizontal;
+
+ // Assert
+ Assert.True (eventCalled, "OrientationChanging event was not called.");
+ }
+
+ [Fact]
+ public void OrientationChanged_VirtualMethodCalledBeforeEvent ()
+ {
+ // Arrange
+ var radioGroup = new CustomView ();
+ bool eventCalled = false;
+
+ radioGroup.OrientationChanged += (sender, e) =>
+ {
+ eventCalled = true;
+ Assert.True (radioGroup.OnOrientationChangedCalled, "OnOrientationChanged was not called before the event.");
+ };
+
+ // Act
+ radioGroup.Orientation = Orientation.Horizontal;
+
+ // Assert
+ Assert.True (eventCalled, "OrientationChanged event was not called.");
+ }
}