diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs index 4bd53a68a..813526f5c 100644 --- a/Terminal.Gui/Views/Button.cs +++ b/Terminal.Gui/Views/Button.cs @@ -30,6 +30,7 @@ namespace Terminal.Gui { Rune hot_key; int hot_pos = -1; bool is_default; + TextAlignment textAlignment = TextAlignment.Centered; /// /// Gets or sets whether the is the default action to activate in a dialog. @@ -118,7 +119,6 @@ namespace Terminal.Gui { this.IsDefault = is_default; } - int SetWidthHeight (ustring text, bool is_default) { int w = text.Length + 4 + (is_default ? 2 : 0); @@ -145,6 +145,15 @@ namespace Terminal.Gui { } } + /// + public TextAlignment TextAlignment { + get => textAlignment; + set { + textAlignment = value; + SetNeedsDisplay (); + } + } + internal void Update () { if (IsDefault) @@ -176,24 +185,84 @@ namespace Terminal.Gui { SetNeedsDisplay (); } + int c_hot_pos; + /// public override void Redraw (Rect bounds) { Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal); Move (0, 0); - Driver.AddStr (shown_text); - if (hot_pos != -1) { - Move (hot_pos, 0); + var caption = shown_text; + c_hot_pos = hot_pos; + int start; + + if (Frame.Width > shown_text.Length + 1) { + switch (TextAlignment) { + case TextAlignment.Left: + caption += new string (' ', Frame.Width - caption.Length); + break; + case TextAlignment.Right: + start = Frame.Width - caption.Length; + caption = $"{new string (' ', Frame.Width - caption.Length)}{caption}"; + if (c_hot_pos > -1) { + c_hot_pos += start; + } + break; + case TextAlignment.Centered: + start = Frame.Width / 2 - caption.Length / 2; + caption = $"{new string (' ', start)}{caption}{new string (' ', Frame.Width - caption.Length - start)}"; + if (c_hot_pos > -1) { + c_hot_pos += start; + } + break; + case TextAlignment.Justified: + var words = caption.ToString ().Split (new string [] { " " }, StringSplitOptions.RemoveEmptyEntries); + var wLen = GetWordsLength (words); + var space = (Frame.Width - wLen) / (caption.Length - wLen); + caption = ""; + for (int i = 0; i < words.Length; i++) { + if (i == words.Length - 1) { + caption += new string (' ', Frame.Width - caption.Length - 1); + caption += words [i]; + } else { + caption += words [i]; + } + if (i < words.Length - 1) { + caption += new string (' ', space); + } + } + if (c_hot_pos > -1) { + c_hot_pos += space - 1; + } + break; + } + } + + Driver.AddStr (caption); + + if (c_hot_pos != -1) { + Move (c_hot_pos, 0); Driver.SetAttribute (HasFocus ? ColorScheme.HotFocus : ColorScheme.HotNormal); Driver.AddRune (hot_key); } } + int GetWordsLength (string[] words) + { + int length = 0; + + for (int i = 0; i < words.Length; i++) { + length += words [i].Length; + } + + return length; + } + /// public override void PositionCursor () { - Move (hot_pos == -1 ? 1 : hot_pos, 0); + Move (c_hot_pos == -1 ? 1 : c_hot_pos, 0); } bool CheckKey (KeyEvent key) @@ -219,8 +288,7 @@ namespace Terminal.Gui { public override bool ProcessColdKey (KeyEvent kb) { if (IsDefault && kb.KeyValue == '\n') { - if (Clicked != null) - Clicked (); + Clicked?.Invoke (); return true; } return CheckKey (kb); @@ -231,8 +299,7 @@ namespace Terminal.Gui { { var c = kb.KeyValue; if (c == '\n' || c == ' ' || Rune.ToUpper ((uint)c) == hot_key) { - if (Clicked != null) - Clicked (); + Clicked?.Invoke (); return true; } return base.ProcessKey (kb); @@ -242,11 +309,12 @@ namespace Terminal.Gui { public override bool MouseEvent (MouseEvent me) { if (me.Flags == MouseFlags.Button1Clicked) { - SuperView.SetFocus (this); - SetNeedsDisplay (); + if (!HasFocus) { + SuperView.SetFocus (this); + SetNeedsDisplay (); + } - if (Clicked != null) - Clicked (); + Clicked?.Invoke (); return true; } return false; diff --git a/Terminal.Gui/Views/Label.cs b/Terminal.Gui/Views/Label.cs index f558b13e8..88d81bf6d 100644 --- a/Terminal.Gui/Views/Label.cs +++ b/Terminal.Gui/Views/Label.cs @@ -260,7 +260,7 @@ namespace Terminal.Gui { } /// - /// Computes the the max width of a line or multilines needed to render by the Label control + /// Computes the max width of a line or multilines needed to render by the Label control /// /// Max width of lines. /// Text, may contain newlines. @@ -285,7 +285,7 @@ namespace Terminal.Gui { } /// - /// Controls the text-alignemtn property of the label, changing it will redisplay the . + /// Controls the text-alignment property of the label, changing it will redisplay the . /// /// The text alignment. public TextAlignment TextAlignment { diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs index ebb69639c..ac41cb149 100644 --- a/UICatalog/Scenarios/Buttons.cs +++ b/UICatalog/Scenarios/Buttons.cs @@ -1,5 +1,6 @@ using NStack; using System; +using System.Collections.Generic; using Terminal.Gui; namespace UICatalog { @@ -87,7 +88,7 @@ namespace UICatalog { Y = y }); - button.Clicked = () => button.Text += "!"; + button.Clicked = () => button.Text += "!"; Win.Add (new Button ("Lets see if this will move as \"Text Changer\" grows") { X = Pos.Right (button) + 10, @@ -128,6 +129,45 @@ namespace UICatalog { }; Win.Add (sizeBtn); + Win.Add (new Label ("Size This Button via Frame 'Text Alignment'") { + X = Pos.Right (moveBtn) + 20, + Y = Pos.Top (moveBtn) - 4, + }); + + List txtAligs = new List () { + "Left", + "Right", + "Centered", + "Justified" + }; + + var lvTextAlig = new ListView (txtAligs) { + X = Pos.Right (moveBtn) + 20, + Y = Pos.Top (moveBtn) - 3, + Width = 20, + Height = 4, + ColorScheme = Colors.TopLevel + }; + + lvTextAlig.SelectedChanged += (o, e) => { + switch (e.Value) { + case "Left": + sizeBtn.TextAlignment = TextAlignment.Left; + break; + case "Right": + sizeBtn.TextAlignment = TextAlignment.Right; + break; + case "Centered": + sizeBtn.TextAlignment = TextAlignment.Centered; + break; + case "Justified": + sizeBtn.TextAlignment = TextAlignment.Justified; + break; + } + }; + + Win.Add (lvTextAlig); + // Demo changing hotkey ustring MoveHotkey (ustring txt) {