implemented menu checked and test scenario in UI Catalog

This commit is contained in:
Charlie Kindel
2020-06-06 22:46:46 -06:00
parent 19a717ee38
commit dc4636a458
10 changed files with 196 additions and 86 deletions

View File

@@ -153,7 +153,7 @@ namespace Terminal.Gui {
/// typically in containers such as <see cref="Window"/> and <see cref="FrameView"/> to set the scheme that is used by all the
/// views contained inside.
/// </summary>
public class ColorScheme {
public class ColorScheme : IEquatable<ColorScheme> {
Attribute _normal;
Attribute _focus;
Attribute _hotNormal;
@@ -313,6 +313,42 @@ namespace Terminal.Gui {
preparingScheme = false;
return attribute;
}
public override bool Equals (object obj)
{
return Equals (obj as ColorScheme);
}
public bool Equals (ColorScheme other)
{
return other != null &&
EqualityComparer<Attribute>.Default.Equals (_normal, other._normal) &&
EqualityComparer<Attribute>.Default.Equals (_focus, other._focus) &&
EqualityComparer<Attribute>.Default.Equals (_hotNormal, other._hotNormal) &&
EqualityComparer<Attribute>.Default.Equals (_hotFocus, other._hotFocus) &&
EqualityComparer<Attribute>.Default.Equals (_disabled, other._disabled);
}
public override int GetHashCode ()
{
int hashCode = -1242460230;
hashCode = hashCode * -1521134295 + _normal.GetHashCode ();
hashCode = hashCode * -1521134295 + _focus.GetHashCode ();
hashCode = hashCode * -1521134295 + _hotNormal.GetHashCode ();
hashCode = hashCode * -1521134295 + _hotFocus.GetHashCode ();
hashCode = hashCode * -1521134295 + _disabled.GetHashCode ();
return hashCode;
}
public static bool operator == (ColorScheme left, ColorScheme right)
{
return EqualityComparer<ColorScheme>.Default.Equals (left, right);
}
public static bool operator != (ColorScheme left, ColorScheme right)
{
return !(left == right);
}
}
/// <summary>

View File

@@ -12,12 +12,11 @@ using System;
using NStack;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;
namespace Terminal.Gui {
/// <summary>
/// A <see cref="MenuItem"/> has a title, an associated help text, and an action to execute on activation.
/// A <see cref="MenuItemCheckType"/> has a title, an associated help text, and an action to execute on activation.
/// </summary>
public class MenuItem {
@@ -112,7 +111,39 @@ namespace Terminal.Gui {
return CanExecute == null ? true : CanExecute ();
}
internal int Width => Title.Length + Help.Length + 1 + 2;
internal int Width => Title.Length + Help.Length + 1 + 2 +
(Checked || CheckType.HasFlag (MenuItemCheckType.Checked) || CheckType.HasFlag (MenuItemCheckType.Radio) ? 2 : 0);
/// <summary>
/// Sets or gets whether the <see cref="MenuItem"/> shows a check indicator or not. See <see cref="MenuItemCheckType"/>.
/// </summary>
public bool Checked { set; get; }
/// <summary>
/// Specifies how a <see cref="MenuItem"/> shows selection state.
/// </summary>
[Flags]
public enum MenuItemCheckType : uint {
/// <summary>
/// The menu item will be shown normally, with no check indicator.
/// </summary>
NoCheck = 0b_0000_0000,
/// <summary>
/// The menu item will indicate checked/un-checked state (see <see cref="Checked"/>.
/// </summary>
Checked = 0b_0000_0001,
/// <summary>
/// The menu item is part of a menu radio group (see <see cref="Checked"/> and will indicate selected state.
/// </summary>
Radio = 0b_0000_0010,
};
/// <summary>
/// Sets or gets the type selection indicator the menu item will be displayed with.
/// </summary>
public MenuItemCheckType CheckType { get; set; }
/// <summary>
/// Gets or sets the parent for this <see cref="MenuItem"/>
@@ -308,11 +339,30 @@ namespace Terminal.Gui {
continue;
}
ustring textToDraw;
var checkChar = (char)0x25cf;
var uncheckedChar = (char)0x25cc;
if (item.CheckType.HasFlag (MenuItem.MenuItemCheckType.Checked)) {
checkChar = (char)0x221a;
uncheckedChar = ' ';
}
// Support Checked even though CHeckType wasn't set
if (item.Checked) {
textToDraw = checkChar + " " + item.Title;
} else if (item.CheckType.HasFlag (MenuItem.MenuItemCheckType.Checked) ||
item.CheckType.HasFlag (MenuItem.MenuItemCheckType.Radio)) {
textToDraw = uncheckedChar + " " + item.Title;
} else {
textToDraw = item.Title;
}
Move (2, i + 1);
if (!item.IsEnabled ())
DrawHotString (item.Title, ColorScheme.Disabled, ColorScheme.Disabled);
DrawHotString (textToDraw, ColorScheme.Disabled, ColorScheme.Disabled);
else
DrawHotString (item.Title,
DrawHotString (textToDraw,
i == current ? ColorScheme.HotFocus : ColorScheme.HotNormal,
i == current ? ColorScheme.Focus : ColorScheme.Normal);
@@ -1172,8 +1222,7 @@ namespace Terminal.Gui {
Application.GrabMouse (current);
} else if (IsMenuOpen && (me.View is MenuBar || me.View is Menu)) {
Application.GrabMouse (me.View);
}
else {
} else {
handled = false;
return false;
}

View File

@@ -63,7 +63,8 @@ namespace UICatalog {
/// the Scenario picker UI.
/// Override <see cref="Init(Toplevel)"/> to provide any <see cref="Terminal.Gui.Toplevel"/> behavior needed.
/// </summary>
/// <param name="top"></param>
/// <param name="top">The Toplevel created by the UI Catalog host.</param>
/// <param name="colorScheme">The colorscheme to use.</param>
/// <remarks>
/// <para>
/// Thg base implementation calls <see cref="Application.Init"/>, sets <see cref="Top"/> to the passed in <see cref="Toplevel"/>, creates a <see cref="Window"/> for <see cref="Win"/> and adds it to <see cref="Top"/>.
@@ -72,7 +73,7 @@ namespace UICatalog {
/// Overrides that do not call the base.<see cref="Run"/>, must call <see cref="Application.Init "/> before creating any views or calling other Terminal.Gui APIs.
/// </para>
/// </remarks>
public virtual void Init(Toplevel top)
public virtual void Init(Toplevel top, ColorScheme colorScheme)
{
Application.Init ();
@@ -85,7 +86,8 @@ namespace UICatalog {
X = 0,
Y = 0,
Width = Dim.Fill (),
Height = Dim.Fill ()
Height = Dim.Fill (),
ColorScheme = colorScheme,
};
Top.Add (Win);
}

View File

@@ -36,7 +36,7 @@ namespace UICatalog {
TextField _hText;
int _hVal = 0;
public override void Init (Toplevel top)
public override void Init (Toplevel top, ColorScheme colorScheme)
{
Application.Init ();

View File

@@ -7,7 +7,7 @@ namespace UICatalog {
class Clipping : Scenario {
public override void Init (Toplevel top)
public override void Init (Toplevel top, ColorScheme colorScheme)
{
Application.Init ();

View File

@@ -14,13 +14,14 @@ namespace UICatalog {
private TextView _textView;
private bool _saved = true;
public override void Init (Toplevel top)
public override void Init (Toplevel top, ColorScheme colorScheme)
{
base.Init (top);
}
Application.Init ();
Top = top;
if (Top == null) {
Top = Application.Top;
}
public override void Setup ()
{
var menu = new MenuBar (new MenuBarItem [] {
new MenuBarItem ("_File", new MenuItem [] {
new MenuItem ("_New", "", () => New()),
@@ -50,7 +51,8 @@ namespace UICatalog {
X = 0,
Y = 1,
Width = Dim.Fill (),
Height = Dim.Fill ()
Height = Dim.Fill (),
ColorScheme = colorScheme,
};
Top.Add (Win);
@@ -59,7 +61,7 @@ namespace UICatalog {
Y = 0,
Width = Dim.Fill (),
Height = Dim.Fill (),
};
LoadFile ();
@@ -67,6 +69,10 @@ namespace UICatalog {
Win.Add (_textView);
}
public override void Setup ()
{
}
private void New ()
{
Win.Title = _fileName = "Untitled";

View File

@@ -48,7 +48,7 @@ namespace UICatalog {
}
}
public override void Init (Toplevel top)
public override void Init (Toplevel top, ColorScheme colorScheme)
{
Application.Init ();
Top = top;
@@ -57,7 +57,8 @@ namespace UICatalog {
X = 0,
Y = 0,
Width = Dim.Fill (),
Height = Dim.Fill ()
Height = Dim.Fill (),
ColorScheme = colorScheme,
};
Top.Add (Win);
}
@@ -100,13 +101,18 @@ namespace UICatalog {
Y = Pos.Top (editLabel) + 4,
};
Win.Add (keyLogLabel);
var fakeKeyPress = new KeyEvent (Key.ControlA, new KeyModifiers () {
Alt = true,
Ctrl = true,
Shift = true
});
var maxLogEntry = $"Key{"",-5}: {fakeKeyPress}".Length;
var yOffset = (Top == Application.Top ? 1 : 6);
var keyStrokelist = new List<string> ();
var keyStrokeListView = new ListView (keyStrokelist) {
X = 0,
Y = Pos.Top (keyLogLabel) + yOffset,
Width = Dim.Percent (40),
Width = maxLogEntry,
Height = Dim.Fill (),
};
keyStrokeListView.ColorScheme = Colors.TopLevel;
@@ -119,11 +125,12 @@ namespace UICatalog {
};
Win.Add (processKeyLogLabel);
maxLogEntry = $"{fakeKeyPress}".Length;
yOffset = (Top == Application.Top ? 1 : 6);
var processKeyListView = new ListView (_processKeyList) {
X = Pos.Left (processKeyLogLabel),
Y = Pos.Top (processKeyLogLabel) + yOffset,
Width = Dim.Percent (60),
Width = maxLogEntry,
Height = Dim.Fill (),
};
processKeyListView.ColorScheme = Colors.TopLevel;
@@ -141,7 +148,7 @@ namespace UICatalog {
var processHotKeyListView = new ListView (_processHotKeyList) {
X = Pos.Left (processHotKeyLogLabel),
Y = Pos.Top (processHotKeyLogLabel) + yOffset,
Width = Dim.Percent (50),
Width = maxLogEntry,
Height = Dim.Fill (),
};
processHotKeyListView.ColorScheme = Colors.TopLevel;
@@ -159,7 +166,7 @@ namespace UICatalog {
var processColdKeyListView = new ListView (_processColdKeyList) {
X = Pos.Left (processColdKeyLogLabel),
Y = Pos.Top (processColdKeyLogLabel) + yOffset,
Width = Dim.Fill (),
Width = maxLogEntry,
Height = Dim.Fill (),
};

View File

@@ -5,10 +5,10 @@ namespace UICatalog {
[ScenarioCategory ("Bug Repro")]
[ScenarioCategory ("Console")]
class UseSystemConsole : Scenario {
public override void Init (Toplevel top)
public override void Init (Toplevel top, ColorScheme colorScheme)
{
Application.UseSystemConsole = true;
base.Init (top);
base.Init (top, colorScheme);
}
public override void RequestStop ()

View File

@@ -8,7 +8,7 @@ namespace UICatalog {
[ScenarioCategory ("Layout")]
[ScenarioCategory ("Bug Repro")]
class WindowsAndFrameViews : Scenario {
public override void Init (Toplevel top)
public override void Init (Toplevel top, ColorScheme colorScheme)
{
Application.Init ();

View File

@@ -71,7 +71,7 @@ namespace UICatalog {
var item = _scenarios.FindIndex (t => Scenario.ScenarioMetadata.GetName (t).Equals (args [0], StringComparison.OrdinalIgnoreCase));
_runningScenario = (Scenario)Activator.CreateInstance (_scenarios [item]);
Application.Init ();
_runningScenario.Init (Application.Top);
_runningScenario.Init (Application.Top, _baseColorScheme);
_runningScenario.Setup ();
_runningScenario.Run ();
_runningScenario = null;
@@ -82,7 +82,7 @@ namespace UICatalog {
while (scenario != null) {
Application.UseSystemConsole = _useSystemConsole;
Application.Init ();
scenario.Init (Application.Top);
scenario.Init (Application.Top, _baseColorScheme);
scenario.Setup ();
scenario.Run ();
scenario = GetScenarioToRun ();
@@ -123,56 +123,83 @@ namespace UICatalog {
return _runningScenario;
}
static MenuItem CheckedMenuMenuItem(ustring menuItem, Action action, Func<bool> checkFunction)
static MenuItem [] CreateDiagnosticMenuItems ()
{
var mi = new MenuItem ();
mi.Title = $"{(checkFunction () ? (char)0x25cf : (char)0x25cc)} {menuItem}";
mi.Action = () => {
action?.Invoke ();
mi.Title = $"{(checkFunction () ? (char)0x25cf : (char)0x25cc)} {menuItem}";
MenuItem CheckedMenuMenuItem (ustring menuItem, Action action, Func<bool> checkFunction)
{
var mi = new MenuItem ();
mi.Title = menuItem;
mi.CheckType |= MenuItem.MenuItemCheckType.Checked;
mi.Checked = checkFunction ();
mi.Action = () => {
action?.Invoke ();
mi.Title = menuItem;
mi.Checked = checkFunction ();
};
return mi;
}
return new MenuItem [] {
CheckedMenuMenuItem ("Use _System Console",
() => {
_useSystemConsole = !_useSystemConsole;
},
() => _useSystemConsole),
CheckedMenuMenuItem ("Diagnostics: _Frame Padding",
() => {
ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FramePadding;
_top.SetNeedsDisplay ();
},
() => (ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FramePadding) == ConsoleDriver.DiagnosticFlags.FramePadding),
CheckedMenuMenuItem ("Diagnostics: Frame _Ruler",
() => {
ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FrameRuler;
_top.SetNeedsDisplay ();
},
() => (ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FrameRuler) == ConsoleDriver.DiagnosticFlags.FrameRuler),
};
return mi;
}
static MenuItem RadioMenuItem (ustring menuItem, Action action, Func<bool> checkFunction)
static void SetColorScheme ()
{
var mi = new MenuItem ();
mi.Title = $"{(checkFunction () ? (char)0x25cf : (char)0x25cc)} {menuItem}";
mi.Action = () => {
action?.Invoke ();
mi.Title = $"{(checkFunction () ? (char)0x25cf : (char)0x25cc)} {menuItem}";
};
return mi;
_leftPane.ColorScheme = _baseColorScheme;
_rightPane.ColorScheme = _baseColorScheme;
_top?.SetNeedsDisplay ();
}
static ColorScheme _defaultColorScheme = Colors.ColorSchemes.Values.First ();
static MenuItem[] GetColorSchemeMenuItems ()
static ColorScheme _baseColorScheme;
static MenuItem [] CreateColorSchemeMenuItems ()
{
var menuItems = Colors.ColorSchemes.Select (s => RadioMenuItem (s.Key, () => {
_defaultColorScheme = s.Value;
// SetSelection (s.Key, s.Value);
}, () => _defaultColorScheme == s.Value)).ToArray ();
//void SetSelection (string key, ColorScheme cs)
//{
// foreach(var menu in menuItems) {
// menu.Title = $"{(cs == _defaultColorScheme ? (char)0x25cf : (char)0x25cc)} {key}";
// }
//}
return menuItems;
List<MenuItem> menuItems = new List<MenuItem> ();
foreach (var sc in Colors.ColorSchemes) {
var item = new MenuItem ();
item.Title = sc.Key;
item.CheckType |= MenuItem.MenuItemCheckType.Radio;
item.Checked = sc.Value == _baseColorScheme;
item.Action += () => {
_baseColorScheme = sc.Value;
SetColorScheme ();
foreach (var menuItem in menuItems) {
menuItem.Checked = menuItem.Title.Equals (sc.Key) && sc.Value == _baseColorScheme;
}
};
menuItems.Add (item);
}
return menuItems.ToArray ();
}
/// <summary>
/// Create all controls. This gets called once and the controls remain with their state between Sceanrio runs.
/// </summary>
private static void Setup ()
{
// Set this here because not initilzied until driver is loaded
_baseColorScheme = Colors.Base;
StringBuilder aboutMessage = new StringBuilder ();
aboutMessage.AppendLine ("UI Catalog is a comprehensive sample library for Terminal.Gui");
aboutMessage.AppendLine ("");
aboutMessage.AppendLine ($"Version: {typeof(UICatalogApp).Assembly.GetName ().Version}");
aboutMessage.AppendLine ($"Version: {typeof (UICatalogApp).Assembly.GetName ().Version}");
aboutMessage.AppendLine ($"Using Terminal.Gui Version: {typeof (Terminal.Gui.Application).Assembly.GetName ().Version}");
aboutMessage.AppendLine ("");
@@ -180,27 +207,8 @@ namespace UICatalog {
new MenuBarItem ("_File", new MenuItem [] {
new MenuItem ("_Quit", "", () => Application.RequestStop() )
}),
new MenuBarItem ("_Settings", new MenuItem [] {
new MenuItem("Primary Color Scheme", new MenuBarItem(GetColorSchemeMenuItems())),
CheckedMenuMenuItem ("Use _System Console",
() => {
_useSystemConsole = !_useSystemConsole;
},
() => _useSystemConsole),
CheckedMenuMenuItem ("Diagnostics: _Frame Padding",
() => {
ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FramePadding;
_top.SetNeedsDisplay ();
},
() => (ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FramePadding) == ConsoleDriver.DiagnosticFlags.FramePadding),
CheckedMenuMenuItem ("Diagnostics: Frame _Ruler",
() => {
ConsoleDriver.Diagnostics ^= ConsoleDriver.DiagnosticFlags.FrameRuler;
_top.SetNeedsDisplay ();
},
() => (ConsoleDriver.Diagnostics & ConsoleDriver.DiagnosticFlags.FrameRuler) == ConsoleDriver.DiagnosticFlags.FrameRuler),
}),
new MenuBarItem ("_Color Scheme", CreateColorSchemeMenuItems()),
new MenuBarItem ("_Diagostics", CreateDiagnosticMenuItems()),
new MenuBarItem ("_About...", "About this app", () => MessageBox.Query ("About UI Catalog", aboutMessage.ToString(), "Ok")),
});
@@ -272,6 +280,8 @@ namespace UICatalog {
_numlock,
_scrolllock
});
SetColorScheme ();
}
private static void _scenarioListView_OpenSelectedItem (EventArgs e)