Charlie Kindel 5 年之前
父节点
当前提交
8feab947fd
共有 4 个文件被更改,包括 157 次插入87 次删除
  1. 58 17
      Terminal.Gui/Core/ConsoleDriver.cs
  2. 3 3
      UICatalog/Scenario.cs
  3. 95 66
      UICatalog/Scenarios/Buttons.cs
  4. 1 1
      UICatalog/UICatalog.cs

+ 58 - 17
Terminal.Gui/Core/ConsoleDriver.cs

@@ -7,6 +7,8 @@
 // Define this to enable diagnostics drawing for Window Frames
 // Define this to enable diagnostics drawing for Window Frames
 using NStack;
 using NStack;
 using System;
 using System;
+using System.Collections.Generic;
+using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 
 
 namespace Terminal.Gui {
 namespace Terminal.Gui {
@@ -317,42 +319,81 @@ namespace Terminal.Gui {
 	/// The default <see cref="ColorScheme"/>s for the application.
 	/// The default <see cref="ColorScheme"/>s for the application.
 	/// </summary>
 	/// </summary>
 	public static class Colors {
 	public static class Colors {
-		static ColorScheme _toplevel;
-		static ColorScheme _base;
-		static ColorScheme _dialog;
-		static ColorScheme _menu;
-		static ColorScheme _error;
+		static Colors ()
+		{
+			// Use reflection to dynamically create the default set of ColorSchemes from the list defiined 
+			// by the class. 
+			ColorSchemes = typeof (Colors).GetProperties ()
+				.Where(p => p.PropertyType == typeof(ColorScheme))
+				.Select (p => new KeyValuePair<string, ColorScheme> (p.Name, new ColorScheme())) // (ColorScheme)p.GetValue (p)))
+				.ToDictionary (t => t.Key, t => t.Value);
+		}
 
 
 		/// <summary>
 		/// <summary>
 		/// The application toplevel color scheme, for the default toplevel views.
 		/// The application toplevel color scheme, for the default toplevel views.
 		/// </summary>
 		/// </summary>
-		public static ColorScheme TopLevel { get { return _toplevel; } set { _toplevel = SetColorScheme (value); } }
+		/// <remarks>
+		/// <para>
+		///	This API will be deprecated in the future. Use <see cref="Colors.ColorSchemes"/> instead (e.g. <c>edit.ColorScheme = Colors.ColorSchemes["TopLevel"];</c>
+		/// </para>
+		/// </remarks>
+		public static ColorScheme TopLevel { get => GetColorScheme (); set => SetColorScheme (value); }
 
 
 		/// <summary>
 		/// <summary>
 		/// The base color scheme, for the default toplevel views.
 		/// The base color scheme, for the default toplevel views.
 		/// </summary>
 		/// </summary>
-		public static ColorScheme Base { get { return _base; } set { _base = SetColorScheme (value); } }
+		/// <remarks>
+		/// <para>
+		///	This API will be deprecated in the future. Use <see cref="Colors.ColorSchemes"/> instead (e.g. <c>edit.ColorScheme = Colors.ColorSchemes["Base"];</c>
+		/// </para>
+		/// </remarks>
+		public static ColorScheme Base { get => GetColorScheme (); set => SetColorScheme (value); }
 
 
 		/// <summary>
 		/// <summary>
 		/// The dialog color scheme, for standard popup dialog boxes
 		/// The dialog color scheme, for standard popup dialog boxes
 		/// </summary>
 		/// </summary>
-		public static ColorScheme Dialog { get { return _dialog; } set { _dialog = SetColorScheme (value); } }
+		/// <remarks>
+		/// <para>
+		///	This API will be deprecated in the future. Use <see cref="Colors.ColorSchemes"/> instead (e.g. <c>edit.ColorScheme = Colors.ColorSchemes["Dialog"];</c>
+		/// </para>
+		/// </remarks>
+		public static ColorScheme Dialog { get => GetColorScheme (); set => SetColorScheme (value); }
 
 
 		/// <summary>
 		/// <summary>
 		/// The menu bar color
 		/// The menu bar color
 		/// </summary>
 		/// </summary>
-		public static ColorScheme Menu { get { return _menu; } set { _menu = SetColorScheme (value); } }
+		/// <remarks>
+		/// <para>
+		///	This API will be deprecated in the future. Use <see cref="Colors.ColorSchemes"/> instead (e.g. <c>edit.ColorScheme = Colors.ColorSchemes["Menu"];</c>
+		/// </para>
+		/// </remarks>
+		public static ColorScheme Menu { get => GetColorScheme (); set => SetColorScheme (value); }
 
 
 		/// <summary>
 		/// <summary>
 		/// The color scheme for showing errors.
 		/// The color scheme for showing errors.
 		/// </summary>
 		/// </summary>
-		public static ColorScheme Error { get { return _error; } set { _error = SetColorScheme (value); } }
+		/// <remarks>
+		/// <para>
+		///	This API will be deprecated in the future. Use <see cref="Colors.ColorSchemes"/> instead (e.g. <c>edit.ColorScheme = Colors.ColorSchemes["Error"];</c>
+		/// </para>
+		/// </remarks>
+		public static ColorScheme Error { get => GetColorScheme (); set => SetColorScheme (value);  }
 
 
-		static ColorScheme SetColorScheme (ColorScheme colorScheme, [CallerMemberName] string callerMemberName = null)
+		static ColorScheme GetColorScheme([CallerMemberName] string callerMemberName = null)
 		{
 		{
+			return ColorSchemes [callerMemberName];
+		}
+
+		static void SetColorScheme (ColorScheme colorScheme, [CallerMemberName] string callerMemberName = null)
+		{
+			ColorSchemes [callerMemberName] = colorScheme;
 			colorScheme.caller = callerMemberName;
 			colorScheme.caller = callerMemberName;
-			return colorScheme;
 		}
 		}
+
+		/// <summary>
+		/// Provides the defined <see cref="ColorScheme"/>s.
+		/// </summary>
+		public static Dictionary<string, ColorScheme> ColorSchemes { get; }
 	}
 	}
 
 
 	///// <summary>
 	///// <summary>
@@ -535,7 +576,7 @@ namespace Terminal.Gui {
 		public virtual void DrawWindowTitle (Rect region, ustring title, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom, TextAlignment textAlignment = TextAlignment.Left)
 		public virtual void DrawWindowTitle (Rect region, ustring title, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom, TextAlignment textAlignment = TextAlignment.Left)
 		{
 		{
 			var width = region.Width - (paddingLeft + 2) * 2;
 			var width = region.Width - (paddingLeft + 2) * 2;
-			if (!ustring.IsNullOrEmpty(title) && width > 4 && region.Y + paddingTop <= region.Y + paddingBottom) {
+			if (!ustring.IsNullOrEmpty (title) && width > 4 && region.Y + paddingTop <= region.Y + paddingBottom) {
 				Move (region.X + 1 + paddingLeft, region.Y + paddingTop);
 				Move (region.X + 1 + paddingLeft, region.Y + paddingTop);
 				AddRune (' ');
 				AddRune (' ');
 				var str = title.Length >= width ? title [0, width - 2] : title;
 				var str = title.Length >= width ? title [0, width - 2] : title;
@@ -548,16 +589,16 @@ namespace Terminal.Gui {
 		/// Enables diagnostic funcions
 		/// Enables diagnostic funcions
 		/// </summary>
 		/// </summary>
 		[Flags]
 		[Flags]
-		public enum DiagnosticFlags : uint { 
+		public enum DiagnosticFlags : uint {
 			/// <summary>
 			/// <summary>
 			/// All diagnostics off
 			/// All diagnostics off
 			/// </summary>
 			/// </summary>
-			Off		= 0b_0000_0000,
+			Off = 0b_0000_0000,
 			/// <summary>
 			/// <summary>
 			/// When enabled, <see cref="DrawWindowFrame(Rect, int, int, int, int, bool, bool)"/> will draw a 
 			/// When enabled, <see cref="DrawWindowFrame(Rect, int, int, int, int, bool, bool)"/> will draw a 
 			/// ruler in the frame for any side with a padding value greater than 0.
 			/// ruler in the frame for any side with a padding value greater than 0.
 			/// </summary>
 			/// </summary>
-			FrameRuler	= 0b_0000_0001,
+			FrameRuler = 0b_0000_0001,
 			/// <summary>
 			/// <summary>
 			/// When Enabled, <see cref="DrawWindowFrame(Rect, int, int, int, int, bool, bool)"/> will use
 			/// When Enabled, <see cref="DrawWindowFrame(Rect, int, int, int, int, bool, bool)"/> will use
 			/// 'L', 'R', 'T', and 'B' for padding instead of ' '.
 			/// 'L', 'R', 'T', and 'B' for padding instead of ' '.
@@ -744,7 +785,7 @@ namespace Terminal.Gui {
 		{
 		{
 			// DrawFrame assumes the border is always at least one row/col thick
 			// DrawFrame assumes the border is always at least one row/col thick
 			// DrawWindowFrame assumes a padding of 0 means NO padding and no frame
 			// DrawWindowFrame assumes a padding of 0 means NO padding and no frame
-			DrawWindowFrame (new Rect (region.X, region.Y, region.Width, region.Height), 
+			DrawWindowFrame (new Rect (region.X, region.Y, region.Width, region.Height),
 				padding + 1, padding + 1, padding + 1, padding + 1, border: false, fill: fill);
 				padding + 1, padding + 1, padding + 1, padding + 1, border: false, fill: fill);
 		}
 		}
 
 

+ 3 - 3
UICatalog/Scenario.cs

@@ -225,11 +225,11 @@ namespace UICatalog {
 		/// Returns an instance of each <see cref="Scenario"/> defined in the project. 
 		/// Returns an instance of each <see cref="Scenario"/> defined in the project. 
 		/// https://stackoverflow.com/questions/5411694/get-all-inherited-classes-of-an-abstract-class
 		/// https://stackoverflow.com/questions/5411694/get-all-inherited-classes-of-an-abstract-class
 		/// </summary>
 		/// </summary>
-		internal static List<Type> GetDerivedClassesCollection ()
+		internal static List<Type> GetDerivedClasses<T> ()
 		{
 		{
 			List<Type> objects = new List<Type> ();
 			List<Type> objects = new List<Type> ();
-			foreach (Type type in typeof (Scenario).Assembly.GetTypes ()
-			 .Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (Scenario)))) {
+			foreach (Type type in typeof (T).Assembly.GetTypes ()
+			 .Where (myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf (typeof (T)))) {
 				objects.Add (type);
 				objects.Add (type);
 			}
 			}
 			return objects;
 			return objects;

+ 95 - 66
UICatalog/Scenarios/Buttons.cs

@@ -1,5 +1,8 @@
 using NStack;
 using NStack;
 using System;
 using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
 using Terminal.Gui;
 using Terminal.Gui;
 
 
 namespace UICatalog {
 namespace UICatalog {
@@ -16,7 +19,7 @@ namespace UICatalog {
 			};
 			};
 			Win.Add (editLabel);
 			Win.Add (editLabel);
 			// Add a TextField using Absolute layout. Use buttons to move/grow.
 			// Add a TextField using Absolute layout. Use buttons to move/grow.
-			var edit = new TextField (31, 0, 25, "");
+			var edit = new TextField (31, 0, 15, "");
 			Win.Add (edit);
 			Win.Add (edit);
 
 
 			// This is the default button (IsDefault = true); if user presses ENTER in the TextField
 			// This is the default button (IsDefault = true); if user presses ENTER in the TextField
@@ -30,6 +33,13 @@ namespace UICatalog {
 			};
 			};
 			Win.Add (defaultButton);
 			Win.Add (defaultButton);
 
 
+			var swapButton = new Button (50, 0, "Swap Default (Absolute Layout)");
+			swapButton.Clicked = () => {
+				defaultButton.IsDefault = !defaultButton.IsDefault;
+				swapButton.IsDefault = !swapButton.IsDefault;
+			};
+			Win.Add (swapButton);
+
 			static void DoMessage (Button button, ustring txt)
 			static void DoMessage (Button button, ustring txt)
 			{
 			{
 				button.Clicked = () => {
 				button.Clicked = () => {
@@ -38,79 +48,63 @@ namespace UICatalog {
 				};
 				};
 			}
 			}
 
 
-			var y = 2;
-			var button = new Button (10, y, "Ba_se Color") {
-				ColorScheme = Colors.Base,
+			var colorButtonsLabel = new Label ("Color Buttons:") {
+				X = 0,
+				Y = Pos.Bottom (editLabel) + 1,
 			};
 			};
-			DoMessage (button, button.Text);
-			Win.Add (button);
-
-			y += 2;
-			Win.Add (button = new Button (10, y, "Error Color") {
-				ColorScheme = Colors.Error,
-			});
-			DoMessage (button, button.Text);
-
-			y += 2;
-			Win.Add (button = new Button (10, y, "Dialog Color") {
-				ColorScheme = Colors.Dialog,
-			});
-			DoMessage (button, button.Text);
-
-			y += 2;
-			Win.Add (button = new Button (10, y, "Menu Color") {
-				ColorScheme = Colors.Menu,
-			});
-			DoMessage (button, button.Text);
-
-			y += 2;
-			Win.Add (button = new Button (10, y, "TopLevel Color") {
-				ColorScheme = Colors.TopLevel,
-			});
-			DoMessage (button, button.Text);
+			Win.Add (colorButtonsLabel);
+
+			View prev = colorButtonsLabel;
+			foreach (var colorScheme in Colors.ColorSchemes) {
+				var colorButton = new Button ($"{colorScheme.Key}") {
+					ColorScheme = colorScheme.Value,
+					X = Pos.Right (prev) + 2,
+					Y = Pos.Y (colorButtonsLabel),
+				};
+				DoMessage (colorButton, colorButton.Text);
+				Win.Add (colorButton);
+				prev = colorButton;
+			}
 
 
-			y += 2;
-			Win.Add (button = new Button (10, y, "A super long _Button that will probably expose a bug in clipping or wrapping of text. Will it?") {
+			Button button;
+			Win.Add (button = new Button ("A super long _Button that will probably expose a bug in clipping or wrapping of text. Will it?") {
+				X = 2,
+				Y = Pos.Bottom (colorButtonsLabel) + 1,
 			});
 			});
 			DoMessage (button, button.Text);
 			DoMessage (button, button.Text);
 
 
-			y += 2;
 			// Note the 'N' in 'Newline' will be the hotkey
 			// Note the 'N' in 'Newline' will be the hotkey
-			Win.Add (new Button (10, y, "a Newline\nin the button") {
-				Clicked = () => MessageBox.Query (30, 7, "Message", "Question?", "Yes", "No")
+			Win.Add (button = new Button ("a Newline\nin the button") {
+				X = 2,
+				Y = Pos.Bottom (button) + 1,
+				Clicked = () => MessageBox.Query ("Message", "Question?", "Yes", "No")
 			});
 			});
 
 
-			y += 2;
-			// BUGBUG: Buttons don't support specifying hotkeys with _?!?
-			Win.Add (button = new Button ("Te_xt Changer") {
-				X = 10,
-				Y = y
-			});
-
-			button.Clicked = () => button.Text += "!"; 
-
-			Win.Add (new Button ("Lets see if this will move as \"Text Changer\" grows") {
-				X = Pos.Right (button) + 10,
-				Y = y,
-			});
+			var textChanger = new Button ("Te_xt Changer") {
+				X = 2,
+				Y = Pos.Bottom (button) + 1,
+			};
+			Win.Add (textChanger);
+			textChanger.Clicked = () => textChanger.Text += "!";
 
 
-			y += 2;
-			Win.Add (new Button (10, y, "Delete") {
-				ColorScheme = Colors.Error,
-				Clicked = () => Win.Remove (button)
+			Win.Add (button = new Button ("Lets see if this will move as \"Text Changer\" grows") {
+				X = Pos.Right(textChanger) + 2,
+				Y = Pos.Y (textChanger),
 			});
 			});
 
 
-			y += 2;
-			Win.Add (new Button (10, y, "Change Default") {
-				Clicked = () => {
-					defaultButton.IsDefault = !defaultButton.IsDefault;
-					button.IsDefault = !button.IsDefault;
-				},
-			});
+			var removeButton = new Button ("Remove this button") {
+				X = 2,
+				Y = Pos.Bottom (button) + 1,
+				ColorScheme = Colors.Error
+			};
+			Win.Add (removeButton);
+			// This in intresting test case because `moveBtn` and below are laid out relative to this one!
+			removeButton.Clicked = () => Win.Remove (removeButton);
 
 
 			// Demonstrates how changing the View.Frame property can move Views
 			// Demonstrates how changing the View.Frame property can move Views
-			y += 2;
-			var moveBtn = new Button (10, y, "Move This Button via Frame") {
+			var moveBtn = new Button ("Move This Button via Frame") {
+				X = 2,
+				Y = Pos.Bottom (removeButton) + 1,
 				ColorScheme = Colors.Error,
 				ColorScheme = Colors.Error,
 			};
 			};
 			moveBtn.Clicked = () => {
 			moveBtn.Clicked = () => {
@@ -119,15 +113,49 @@ namespace UICatalog {
 			Win.Add (moveBtn);
 			Win.Add (moveBtn);
 
 
 			// Demonstrates how changing the View.Frame property can SIZE Views (#583)
 			// Demonstrates how changing the View.Frame property can SIZE Views (#583)
-			y += 2;
-			var sizeBtn = new Button (10, y, "Size This Button via Frame") {
+			var sizeBtn = new Button ("Size This Button via Frame") {
+				X = Pos.Right(moveBtn) + 2,
+				Y = Pos.Y (moveBtn),
+				Width = 30,
 				ColorScheme = Colors.Error,
 				ColorScheme = Colors.Error,
 			};
 			};
-			moveBtn.Clicked = () => {
+			sizeBtn.Clicked = () => {
 				sizeBtn.Frame = new Rect (sizeBtn.Frame.X, sizeBtn.Frame.Y, sizeBtn.Frame.Width + 5, sizeBtn.Frame.Height);
 				sizeBtn.Frame = new Rect (sizeBtn.Frame.X, sizeBtn.Frame.Y, sizeBtn.Frame.Width + 5, sizeBtn.Frame.Height);
 			};
 			};
 			Win.Add (sizeBtn);
 			Win.Add (sizeBtn);
 
 
+			var label = new Label ("Text Alignment (changes the two buttons above): ") {
+				X = 2,
+				Y = Pos.Bottom (sizeBtn) + 1,
+			};
+			Win.Add (label);
+
+			var radioGroup = new RadioGroup (new [] { "Left", "Right", "Centered", "Justified" }) {
+				X = 4,
+				Y = Pos.Bottom (label) + 1,
+				//SelectionChanged = (selected) => {
+				//	switch (selected) {
+				//	case 0:
+				//		moveBtn.TextAlignment = TextAlignment.Left;
+				//		sizeBtn.TextAlignment = TextAlignment.Left;
+				//		break;
+				//	case 1:
+				//		moveBtn.TextAlignment = TextAlignment.Right;
+				//		sizeBtn.TextAlignment = TextAlignment.Right;
+				//		break;
+				//	case 2:
+				//		moveBtn.TextAlignment = TextAlignment.Centered;
+				//		sizeBtn.TextAlignment = TextAlignment.Centered;
+				//		break;
+				//	case 3:
+				//		moveBtn.TextAlignment = TextAlignment.Justified;
+				//		sizeBtn.TextAlignment = TextAlignment.Justified;
+				//		break;
+				//	}
+				//}
+			};
+			Win.Add (radioGroup);
+
 			// Demo changing hotkey
 			// Demo changing hotkey
 			ustring MoveHotkey (ustring txt)
 			ustring MoveHotkey (ustring txt)
 			{
 			{
@@ -149,8 +177,9 @@ namespace UICatalog {
 				return txt;
 				return txt;
 			}
 			}
 
 
-			y += 2;
-			var moveHotKeyBtn = new Button (10, y, "Click to Change th_is Button's Hotkey") {
+			var moveHotKeyBtn = new Button ("Click to Change th_is Button's Hotkey") {
+				X = 2,
+				Y = Pos.Bottom (radioGroup) + 1,
 				ColorScheme = Colors.TopLevel,
 				ColorScheme = Colors.TopLevel,
 			};
 			};
 			moveHotKeyBtn.Clicked = () => {
 			moveHotKeyBtn.Clicked = () => {

+ 1 - 1
UICatalog/UICatalog.cs

@@ -65,7 +65,7 @@ namespace UICatalog {
 			if (Debugger.IsAttached)
 			if (Debugger.IsAttached)
 				CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
 				CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US");
 
 
-			_scenarios = Scenario.GetDerivedClassesCollection ().OrderBy (t => Scenario.ScenarioMetadata.GetName (t)).ToList ();
+			_scenarios = Scenario.GetDerivedClasses<Scenario> ().OrderBy (t => Scenario.ScenarioMetadata.GetName (t)).ToList ();
 
 
 			if (args.Length > 0) {
 			if (args.Length > 0) {
 				var item = _scenarios.FindIndex (t => Scenario.ScenarioMetadata.GetName (t).Equals (args [0], StringComparison.OrdinalIgnoreCase));
 				var item = _scenarios.FindIndex (t => Scenario.ScenarioMetadata.GetName (t).Equals (args [0], StringComparison.OrdinalIgnoreCase));