//
// Checkbox.cs: Checkbox control
//
// Authors:
// Miguel de Icaza (miguel@gnome.org)
//
using System;
using NStack;
namespace Terminal.Gui {
///
/// The shows an on/off toggle that the user can set
///
public class CheckBox : View {
Rune charNullChecked;
Rune charChecked;
Rune charUnChecked;
bool? @checked;
bool allowNullChecked;
///
/// Toggled event, raised when the is toggled.
///
///
/// Client code can hook up to this event, it is
/// raised when the is activated either with
/// the mouse or the keyboard. The passed bool contains the previous state.
///
public event EventHandler Toggled;
///
/// Called when the property changes. Invokes the event.
///
public virtual void OnToggled (ToggleEventArgs e)
{
Toggled?.Invoke (this, e);
}
///
/// Initializes a new instance of based on the given text, using layout.
///
public CheckBox () : this (string.Empty) { }
///
/// Initializes a new instance of based on the given text, using layout.
///
/// S.
/// If set to true is checked.
public CheckBox (ustring s, bool is_checked = false) : base ()
{
SetInitialProperties (s, is_checked);
}
///
/// Initializes a new instance of using layout.
///
///
/// The size of is computed based on the
/// text length. This is not toggled.
///
public CheckBox (int x, int y, ustring s) : this (x, y, s, false)
{
}
///
/// Initializes a new instance of using layout.
///
///
/// The size of is computed based on the
/// text length.
///
public CheckBox (int x, int y, ustring s, bool is_checked) : base (new Rect (x, y, s.Length, 1))
{
SetInitialProperties (s, is_checked);
}
// TODO: v2 - Remove constructors with parameters
///
/// Private helper to set the initial properties of the View that were provided via constructors.
///
///
///
void SetInitialProperties (ustring s, bool is_checked)
{
charNullChecked = new Rune (Driver != null ? Driver.NullChecked : '?');
charChecked = new Rune (Driver != null ? Driver.Checked : '√');
charUnChecked = new Rune (Driver != null ? Driver.UnChecked : '╴');
Checked = is_checked;
HotKeySpecifier = new Rune ('_');
CanFocus = true;
AutoSize = true;
Text = s;
OnResizeNeeded ();
// Things this view knows how to do
AddCommand (Command.ToggleChecked, () => ToggleChecked ());
// Default keybindings for this view
AddKeyBinding ((Key)' ', Command.ToggleChecked);
AddKeyBinding (Key.Space, Command.ToggleChecked);
}
///
protected override void UpdateTextFormatterText ()
{
switch (TextAlignment) {
case TextAlignment.Left:
case TextAlignment.Centered:
case TextAlignment.Justified:
TextFormatter.Text = ustring.Make (GetCheckedState ()) + " " + GetFormatterText ();
break;
case TextAlignment.Right:
TextFormatter.Text = GetFormatterText () + " " + ustring.Make (GetCheckedState ());
break;
}
}
Rune GetCheckedState ()
{
switch (Checked) {
case true: return charChecked;
case false: return charUnChecked;
default: return charNullChecked;
}
}
ustring GetFormatterText ()
{
if (AutoSize || ustring.IsNullOrEmpty (Text) || Frame.Width <= 2) {
return Text;
}
return Text.RuneSubstring (0, Math.Min (Frame.Width - 2, Text.RuneCount));
}
///
/// The state of the
///
public bool? Checked {
get => @checked;
set {
if (value == null && !AllowNullChecked) {
return;
}
@checked = value;
UpdateTextFormatterText ();
OnResizeNeeded ();
}
}
///
/// If allows to be null, true or false.
/// If only allows to be true or false.
///
public bool AllowNullChecked {
get => allowNullChecked;
set {
allowNullChecked = value;
if (Checked == null) {
Checked = false;
}
}
}
///
public override void PositionCursor ()
{
Move (0, 0);
}
///
public override bool ProcessKey (KeyEvent kb)
{
var result = InvokeKeybindings (kb);
if (result != null)
return (bool)result;
return base.ProcessKey (kb);
}
///
public override bool ProcessHotKey (KeyEvent kb)
{
if (kb.Key == (Key.AltMask | HotKey))
return ToggleChecked ();
return false;
}
bool ToggleChecked ()
{
if (!HasFocus) {
SetFocus ();
}
var previousChecked = Checked;
if (AllowNullChecked) {
switch (previousChecked) {
case null:
Checked = true;
break;
case true:
Checked = false;
break;
case false:
Checked = null;
break;
}
} else {
Checked = !Checked;
}
OnToggled (new ToggleEventArgs (previousChecked, Checked));
SetNeedsDisplay ();
return true;
}
///
public override bool MouseEvent (MouseEvent me)
{
if (!me.Flags.HasFlag (MouseFlags.Button1Clicked) || !CanFocus)
return false;
ToggleChecked ();
return true;
}
///
public override bool OnEnter (View view)
{
Application.Driver.SetCursorVisibility (CursorVisibility.Invisible);
return base.OnEnter (view);
}
}
}