浏览代码

implemented menu checked and test scenario in UI Catalog

Charlie Kindel 5 年之前
父节点
当前提交
dc4636a458

+ 37 - 1
Terminal.Gui/Core/ConsoleDriver.cs

@@ -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>

+ 56 - 7
Terminal.Gui/Views/Menu.cs

@@ -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;
 			}

+ 5 - 3
UICatalog/Scenario.cs

@@ -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);
 		}

+ 1 - 1
UICatalog/Scenarios/AllViewsTester.cs

@@ -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 ();
 

+ 1 - 1
UICatalog/Scenarios/Clipping.cs

@@ -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 ();
 

+ 13 - 7
UICatalog/Scenarios/Editor.cs

@@ -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";

+ 14 - 7
UICatalog/Scenarios/Keys.cs

@@ -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 (),
 			};
 

+ 2 - 2
UICatalog/Scenarios/SystemConsole.cs

@@ -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 ()

+ 1 - 1
UICatalog/Scenarios/WindowsAndFrameViews.cs

@@ -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 ();
 

+ 66 - 56
UICatalog/UICatalog.cs

@@ -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)