diff --git a/Terminal.Gui/Core/ConsoleDriver.cs b/Terminal.Gui/Core/ConsoleDriver.cs index 7dca1f099..fd6b2c8f5 100644 --- a/Terminal.Gui/Core/ConsoleDriver.cs +++ b/Terminal.Gui/Core/ConsoleDriver.cs @@ -7,6 +7,8 @@ // Define this to enable diagnostics drawing for Window Frames using NStack; using System; +using System.Collections.Generic; +using System.Linq; using System.Runtime.CompilerServices; namespace Terminal.Gui { @@ -317,42 +319,81 @@ namespace Terminal.Gui { /// The default s for the application. /// 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 (p.Name, new ColorScheme())) // (ColorScheme)p.GetValue (p))) + .ToDictionary (t => t.Key, t => t.Value); + } /// /// The application toplevel color scheme, for the default toplevel views. /// - public static ColorScheme TopLevel { get { return _toplevel; } set { _toplevel = SetColorScheme (value); } } + /// + /// + /// This API will be deprecated in the future. Use instead (e.g. edit.ColorScheme = Colors.ColorSchemes["TopLevel"]; + /// + /// + public static ColorScheme TopLevel { get => GetColorScheme (); set => SetColorScheme (value); } /// /// The base color scheme, for the default toplevel views. /// - public static ColorScheme Base { get { return _base; } set { _base = SetColorScheme (value); } } + /// + /// + /// This API will be deprecated in the future. Use instead (e.g. edit.ColorScheme = Colors.ColorSchemes["Base"]; + /// + /// + public static ColorScheme Base { get => GetColorScheme (); set => SetColorScheme (value); } /// /// The dialog color scheme, for standard popup dialog boxes /// - public static ColorScheme Dialog { get { return _dialog; } set { _dialog = SetColorScheme (value); } } + /// + /// + /// This API will be deprecated in the future. Use instead (e.g. edit.ColorScheme = Colors.ColorSchemes["Dialog"]; + /// + /// + public static ColorScheme Dialog { get => GetColorScheme (); set => SetColorScheme (value); } /// /// The menu bar color /// - public static ColorScheme Menu { get { return _menu; } set { _menu = SetColorScheme (value); } } + /// + /// + /// This API will be deprecated in the future. Use instead (e.g. edit.ColorScheme = Colors.ColorSchemes["Menu"]; + /// + /// + public static ColorScheme Menu { get => GetColorScheme (); set => SetColorScheme (value); } /// /// The color scheme for showing errors. /// - public static ColorScheme Error { get { return _error; } set { _error = SetColorScheme (value); } } + /// + /// + /// This API will be deprecated in the future. Use instead (e.g. edit.ColorScheme = Colors.ColorSchemes["Error"]; + /// + /// + 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) { - colorScheme.caller = callerMemberName; - return colorScheme; + return ColorSchemes [callerMemberName]; } + + static void SetColorScheme (ColorScheme colorScheme, [CallerMemberName] string callerMemberName = null) + { + ColorSchemes [callerMemberName] = colorScheme; + colorScheme.caller = callerMemberName; + } + + /// + /// Provides the defined s. + /// + public static Dictionary ColorSchemes { get; } } ///// @@ -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) { 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); AddRune (' '); var str = title.Length >= width ? title [0, width - 2] : title; @@ -548,16 +589,16 @@ namespace Terminal.Gui { /// Enables diagnostic funcions /// [Flags] - public enum DiagnosticFlags : uint { + public enum DiagnosticFlags : uint { /// /// All diagnostics off /// - Off = 0b_0000_0000, + Off = 0b_0000_0000, /// /// When enabled, will draw a /// ruler in the frame for any side with a padding value greater than 0. /// - FrameRuler = 0b_0000_0001, + FrameRuler = 0b_0000_0001, /// /// When Enabled, will use /// '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 // 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); } diff --git a/UICatalog/Scenario.cs b/UICatalog/Scenario.cs index 6df482536..bdfef607b 100644 --- a/UICatalog/Scenario.cs +++ b/UICatalog/Scenario.cs @@ -225,11 +225,11 @@ namespace UICatalog { /// Returns an instance of each defined in the project. /// https://stackoverflow.com/questions/5411694/get-all-inherited-classes-of-an-abstract-class /// - internal static List GetDerivedClassesCollection () + internal static List GetDerivedClasses () { List objects = new List (); - 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); } return objects; diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index ebb69639c..da70b3826 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -1,5 +1,8 @@ using NStack; using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; using Terminal.Gui; namespace UICatalog { @@ -16,7 +19,7 @@ namespace UICatalog { }; Win.Add (editLabel); // 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); // This is the default button (IsDefault = true); if user presses ENTER in the TextField @@ -30,6 +33,13 @@ namespace UICatalog { }; 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) { 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); + Win.Add (colorButtonsLabel); - y += 2; - Win.Add (button = new Button (10, y, "Error Color") { - ColorScheme = Colors.Error, + 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; + } + + 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); - 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); - - 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?") { - }); - DoMessage (button, button.Text); - - y += 2; // 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 + var textChanger = new Button ("Te_xt Changer") { + X = 2, + Y = Pos.Bottom (button) + 1, + }; + Win.Add (textChanger); + textChanger.Clicked = () => textChanger.Text += "!"; + + Win.Add (button = new Button ("Lets see if this will move as \"Text Changer\" grows") { + X = Pos.Right(textChanger) + 2, + Y = Pos.Y (textChanger), }); - 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, - }); - - y += 2; - Win.Add (new Button (10, y, "Delete") { - ColorScheme = Colors.Error, - Clicked = () => Win.Remove (button) - }); - - 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 - 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, }; moveBtn.Clicked = () => { @@ -119,15 +113,49 @@ namespace UICatalog { Win.Add (moveBtn); // 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, }; - moveBtn.Clicked = () => { + sizeBtn.Clicked = () => { sizeBtn.Frame = new Rect (sizeBtn.Frame.X, sizeBtn.Frame.Y, sizeBtn.Frame.Width + 5, sizeBtn.Frame.Height); }; 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 ustring MoveHotkey (ustring txt) { @@ -149,8 +177,9 @@ namespace UICatalog { 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, }; moveHotKeyBtn.Clicked = () => { diff --git a/UICatalog/UICatalog.cs b/UICatalog/UICatalog.cs index 7e7888132..2c27ebd89 100644 --- a/UICatalog/UICatalog.cs +++ b/UICatalog/UICatalog.cs @@ -65,7 +65,7 @@ namespace UICatalog { if (Debugger.IsAttached) CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.GetCultureInfo ("en-US"); - _scenarios = Scenario.GetDerivedClassesCollection ().OrderBy (t => Scenario.ScenarioMetadata.GetName (t)).ToList (); + _scenarios = Scenario.GetDerivedClasses ().OrderBy (t => Scenario.ScenarioMetadata.GetName (t)).ToList (); if (args.Length > 0) { var item = _scenarios.FindIndex (t => Scenario.ScenarioMetadata.GetName (t).Equals (args [0], StringComparison.OrdinalIgnoreCase));