diff --git a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
index b5fd61084..f7563327c 100644
--- a/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/CursesDriver/CursesDriver.cs
@@ -627,7 +627,7 @@ internal class CursesDriver : ConsoleDriver {
return true;
});
- _mainLoop.WinChanged += ProcessInput;
+ _mainLoop.WinChanged = ProcessInput;
}
public override void Init (Action terminalResized)
diff --git a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
index b824663c4..b08958bd6 100644
--- a/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/FakeDriver/FakeDriver.cs
@@ -353,7 +353,7 @@ public class FakeDriver : ConsoleDriver {
_keyUpHandler = keyUpHandler;
// Note: Net doesn't support keydown/up events and thus any passed keyDown/UpHandlers will never be called
- (mainLoop.MainLoopDriver as FakeMainLoop).KeyPressed += (consoleKey) => ProcessInput (consoleKey);
+ (mainLoop.MainLoopDriver as FakeMainLoop).KeyPressed = (consoleKey) => ProcessInput (consoleKey);
}
void ProcessInput (ConsoleKeyInfo consoleKey)
diff --git a/Terminal.Gui/ConsoleDrivers/NetDriver.cs b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
index 1d10f98ce..2a9019b27 100644
--- a/Terminal.Gui/ConsoleDrivers/NetDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/NetDriver.cs
@@ -136,7 +136,7 @@ internal class NetEvents : IDisposable {
public InputResult? DequeueInput ()
{
- while (!_inputReadyCancellationTokenSource.Token.IsCancellationRequested) {
+ while (_inputReadyCancellationTokenSource != null && !_inputReadyCancellationTokenSource.Token.IsCancellationRequested) {
_waitForStart.Set ();
_winChange.Set ();
@@ -185,7 +185,12 @@ internal class NetEvents : IDisposable {
{
while (!_inputReadyCancellationTokenSource.Token.IsCancellationRequested) {
- _waitForStart.Wait (_inputReadyCancellationTokenSource.Token);
+ try {
+ _waitForStart.Wait (_inputReadyCancellationTokenSource.Token);
+ } catch (OperationCanceledException) {
+
+ return;
+ }
_waitForStart.Reset ();
if (_inputQueue.Count == 0) {
@@ -1339,9 +1344,14 @@ internal class NetMainLoop : IMainLoopDriver {
} catch (OperationCanceledException) {
return;
} finally {
- _waitForProbe.Reset ();
+ if (_waitForProbe.IsSet) {
+ _waitForProbe.Reset ();
+ }
}
+ if (_inputHandlerTokenSource.IsCancellationRequested) {
+ return;
+ }
if (_resultQueue.Count == 0) {
_resultQueue.Enqueue (_netEvents.DequeueInput ());
}
diff --git a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
index 891887563..18e6492b9 100644
--- a/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
+++ b/Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
@@ -861,9 +861,9 @@ internal class WindowsDriver : ConsoleDriver {
_mouseHandler = mouseHandler;
_mainLoop = mainLoop.MainLoopDriver as WindowsMainLoop;
- _mainLoop.ProcessInput += ProcessInput;
+ _mainLoop.ProcessInput = ProcessInput;
#if HACK_CHECK_WINCHANGED
- _mainLoop.WinChanged += ChangeWin;
+ _mainLoop.WinChanged = ChangeWin;
#endif
}
diff --git a/Terminal.Gui/Drawing/Glyphs.cs b/Terminal.Gui/Drawing/Glyphs.cs
index fa8160441..6cc4aa5fe 100644
--- a/Terminal.Gui/Drawing/Glyphs.cs
+++ b/Terminal.Gui/Drawing/Glyphs.cs
@@ -129,6 +129,11 @@ namespace Terminal.Gui {
///
public Rune Dot { get; set; } = (Rune)'∙';
+ ///
+ /// Black Circle . Default is (U+025cf) - ●.
+ ///
+ public Rune BlackCircle { get; set; } = (Rune)'●'; // Black Circle - ● U+025cf
+
///
/// Expand (e.g. for .
///
diff --git a/Terminal.Gui/Types/Point.cs b/Terminal.Gui/Types/Point.cs
index ff4f07fd8..08a824cb3 100644
--- a/Terminal.Gui/Types/Point.cs
+++ b/Terminal.Gui/Types/Point.cs
@@ -41,7 +41,7 @@ namespace Terminal.Gui
///
/// An uninitialized Point Structure.
///
-
+
public static readonly Point Empty;
///
diff --git a/Terminal.Gui/Views/Slider.cs b/Terminal.Gui/Views/Slider.cs
new file mode 100644
index 000000000..d6d67fc12
--- /dev/null
+++ b/Terminal.Gui/Views/Slider.cs
@@ -0,0 +1,1712 @@
+using Microsoft.VisualBasic.FileIO;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using Unix.Terminal;
+
+namespace Terminal.Gui;
+
+///
+/// for events.
+///
+public class SliderOptionEventArgs : EventArgs {
+ ///
+ /// Gets whether the option is set or not.
+ ///
+ public bool IsSet { get; }
+
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// indicates whether the option is set
+ public SliderOptionEventArgs (bool isSet)
+ {
+ IsSet = isSet;
+ }
+}
+
+///
+/// Represents an option in a .
+///
+/// Datatype of the option.
+public class SliderOption {
+ ///
+ /// Legend of the option.
+ ///
+ public string Legend { get; set; }
+
+ ///
+ /// Abbreviation of the Legend. When the too small to fit .
+ ///
+ public Rune LegendAbbr { get; set; }
+
+ ///
+ /// Custom data of the option.
+ ///
+ public T Data { get; set; }
+
+ ///
+ /// To Raise the event from the Slider.
+ ///
+ internal void OnSet ()
+ {
+ Set?.Invoke (this, new SliderOptionEventArgs (true));
+ }
+
+ ///
+ /// To Raise the event from the Slider.
+ ///
+ internal void OnUnSet ()
+ {
+ UnSet?.Invoke (this, new SliderOptionEventArgs (false));
+ }
+
+ ///
+ /// To Raise the event from the Slider.
+ ///
+ internal void OnChanged (bool isSet)
+ {
+ Changed?.Invoke (this, new SliderOptionEventArgs (isSet));
+ }
+
+ ///
+ /// Event Raised when this option is set.
+ ///
+ public event EventHandler Set;
+
+ ///
+ /// Event Raised when this option is unset.
+ ///
+ public event EventHandler UnSet;
+
+ ///
+ /// Event fired when the an option has changed.
+ ///
+ public event EventHandler Changed;
+}
+
+///
+/// Types
+///
+public enum SliderType {
+ ///
+ ///
+ /// ├─┼─┼─┼─┼─█─┼─┼─┼─┼─┼─┼─┤
+ ///
+ ///
+ Single,
+ ///
+ ///
+ /// ├─┼─█─┼─┼─█─┼─┼─┼─┼─█─┼─┤
+ ///
+ ///
+ Multiple,
+ ///
+ ///
+ /// ├▒▒▒▒▒▒▒▒▒█─┼─┼─┼─┼─┼─┼─┤
+ ///
+ ///
+ LeftRange,
+ ///
+ ///
+ /// ├─┼─┼─┼─┼─█▒▒▒▒▒▒▒▒▒▒▒▒▒┤
+ ///
+ ///
+ RightRange,
+ ///
+ ///
+ /// ├─┼─┼─┼─┼─█▒▒▒▒▒▒▒█─┼─┼─┤
+ ///
+ ///
+ Range
+}
+
+///
+/// Legend Style
+///
+public class SliderAttributes {
+ ///
+ /// Attribute for when the respective Option is NOT Set.
+ ///
+ public Attribute? NormalAttribute { get; set; }
+ ///
+ /// Attribute for when the respective Option is Set.
+ ///
+ public Attribute? SetAttribute { get; set; }
+ ///
+ /// Attribute for the Legends Container.
+ ///
+ public Attribute? EmptyAttribute { get; set; }
+}
+
+///
+/// Style
+///
+public class SliderStyle {
+ ///
+ /// Legend attributes
+ ///
+ public SliderAttributes LegendAttributes { get; set; }
+ ///
+ /// The glyph and the attribute used for empty spaces on the slider.
+ ///
+ public Cell EmptyChar { get; set; }
+ ///
+ /// The glyph and the attribute used for each option (tick) on the slider.
+ ///
+ public Cell OptionChar { get; set; }
+ ///
+ /// The glyph and the attribute used for options (ticks) that are set on the slider.
+ ///
+ public Cell SetChar { get; set; }
+ ///
+ /// The glyph and the attribute to indicate mouse dragging.
+ ///
+ public Cell DragChar { get; set; }
+ ///
+ /// The glyph and the attribute used for spaces between options (ticks) on the slider.
+ ///
+ public Cell SpaceChar { get; set; }
+ ///
+ /// The glyph and the attribute used for filling in ranges on the slider.
+ ///
+ public Cell RangeChar { get; set; }
+ ///
+ /// The glyph and the attribute used for the start of ranges on the slider.
+ ///
+ public Cell StartRangeChar { get; set; }
+ ///
+ /// The glyph and the attribute used for the end of ranges on the slider.
+ ///
+ public Cell EndRangeChar { get; set; }
+
+ ///
+ /// Constructs a new instance.
+ ///
+ public SliderStyle ()
+ {
+ LegendAttributes = new SliderAttributes { };
+ }
+}
+
+///
+/// All configuration are grouped in this class.
+///
+internal class SliderConfiguration {
+ internal bool _rangeAllowSingle;
+ internal bool _allowEmpty;
+
+ internal int _mouseClickXOptionThreshold;
+
+ internal bool _autoSize;
+
+ internal int _startSpacing;
+ internal int _endSpacing;
+ internal int _innerSpacing;
+
+ internal bool _showSpacing;
+ internal bool _showLegends;
+ internal bool _showLegendsAbbr;
+
+ internal SliderType _type = SliderType.Single;
+ internal Orientation _sliderOrientation = Orientation.Horizontal;
+ internal Orientation _legendsOrientation = Orientation.Horizontal;
+}
+
+///
+/// for events.
+///
+public class SliderEventArgs : EventArgs {
+ ///
+ /// Gets/sets whether the option is set or not.
+ ///
+ public Dictionary> Options { get; set; }
+
+ ///
+ /// Gets or sets the index of the option that is focused.
+ ///
+ public int Focused { get; set; }
+
+ ///
+ /// If set to true, the focus operation will be canceled, if applicable.
+ ///
+ public bool Cancel { get; set; }
+
+ ///
+ /// Initializes a new instance of
+ ///
+ /// The current options.
+ /// Index of the option that is focused. -1 if no option has the focus.
+ public SliderEventArgs (Dictionary> options, int focused = -1)
+ {
+ Options = options;
+ Focused = focused;
+ Cancel = false;
+ }
+}
+
+///
+/// for events.
+///
+public class OrientationEventArgs : EventArgs {
+ ///
+ /// The new orientation.
+ ///
+ public Orientation Orientation { get; set; }
+
+ ///
+ /// If set to true, the orientation change operation will be canceled, if applicable.
+ ///
+ public bool Cancel { get; set; }
+
+ ///
+ /// Constructs a new instance.
+ ///
+ /// the new orientation
+ public OrientationEventArgs (Orientation orientation)
+ {
+ Orientation = orientation;
+ Cancel = false;
+ }
+}
+///
+/// Slider control.
+///
+public class Slider : Slider