diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index ff11a4fa3..c612d16b8 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -17,6 +17,27 @@ using System.Linq;
using NStack;
namespace Terminal.Gui {
+ ///
+ /// Text alignment enumeration, controls how text is displayed.
+ ///
+ public enum TextAlignment {
+ ///
+ /// Aligns the text to the left of the frame.
+ ///
+ Left,
+ ///
+ /// Aligns the text to the right side of the frame.
+ ///
+ Right,
+ ///
+ /// Centers the text in the frame.
+ ///
+ Centered,
+ ///
+ /// Shows the text as justified text in the frame.
+ ///
+ Justified
+ }
///
/// Determines the LayoutStyle for a view, if Absolute, during LayoutSubviews, the
@@ -299,6 +320,7 @@ namespace Terminal.Gui {
set {
x = value;
SetNeedsLayout ();
+ SetNeedsDisplay (frame);
}
}
@@ -314,6 +336,7 @@ namespace Terminal.Gui {
set {
y = value;
SetNeedsLayout ();
+ SetNeedsDisplay (frame);
}
}
@@ -331,6 +354,7 @@ namespace Terminal.Gui {
set {
width = value;
SetNeedsLayout ();
+ SetNeedsDisplay (frame);
}
}
@@ -344,6 +368,7 @@ namespace Terminal.Gui {
set {
height = value;
SetNeedsLayout ();
+ SetNeedsDisplay (frame);
}
}
@@ -1450,6 +1475,153 @@ namespace Terminal.Gui {
OnLayoutComplete (new LayoutEventArgs () { OldBounds = oldBounds });
}
+ ///
+ /// A generic virtual method at the level of View to manipulate any hot-keys.
+ ///
+ /// The text to manipulate.
+ /// The hot-key to look for.
+ /// The returning hot-key position.
+ /// The character immediately to the right relative to the hot-key position
+ /// It aims to facilitate the preparation for procedures.
+ public virtual ustring GetTextFromHotKey(ustring text, Rune hotKey, out int hotPos, out Rune showHotKey)
+ {
+ Rune hot_key = (Rune)0;
+ int hot_pos = -1;
+ ustring shown_text = text;
+
+ // Use first hot_key char passed into 'hotKey'.
+ int i = 0;
+ foreach (Rune c in shown_text) {
+ if ((char)c != 0xFFFD) {
+ if (c == hotKey) {
+ hot_pos = i;
+ } else if (hot_pos > -1) {
+ hot_key = c;
+ break;
+ }
+ }
+ i++;
+ }
+
+ if (hot_pos == -1) {
+ // Use first upper-case char if there are no hot-key in the text.
+ i = 0;
+ foreach (Rune c in shown_text) {
+ if ((char)c != 0xFFFD) {
+ if (Rune.IsUpper (c)) {
+ hot_key = c;
+ hot_pos = i;
+ break;
+ }
+ }
+ i++;
+ }
+ } else {
+ // Use char after 'hotKey'
+ ustring start = "";
+ i = 0;
+ foreach (Rune c in shown_text) {
+ start += ustring.Make (c);
+ i++;
+ if (i == hot_pos)
+ break;
+ }
+ var st = shown_text;
+ shown_text = start;
+ i = 0;
+ foreach (Rune c in st) {
+ i++;
+ if (i > hot_pos + 1) {
+ shown_text += ustring.Make (c);
+ }
+ }
+ }
+ hotPos = hot_pos;
+ showHotKey = hot_key;
+ return shown_text;
+ }
+
+ ///
+ /// A generic virtual method at the level of View to manipulate any hot-keys with process.
+ ///
+ /// The text to manipulate to align.
+ /// The passed in hot-key position.
+ /// The returning hot-key position.
+ /// The to align to.
+ /// It performs the process to the caller.
+ public virtual ustring GetTextAlignment (ustring shown_text, int hot_pos, out int c_hot_pos, TextAlignment textAlignment)
+ {
+ int start;
+ var caption = shown_text;
+ c_hot_pos = hot_pos;
+
+ if (Frame.Width > shown_text.Length + 1) {
+ switch (textAlignment) {
+ case TextAlignment.Left:
+ caption += new string (' ', Frame.Width - caption.RuneCount);
+ break;
+ case TextAlignment.Right:
+ start = Frame.Width - caption.RuneCount;
+ caption = $"{new string (' ', Frame.Width - caption.RuneCount)}{caption}";
+ if (c_hot_pos > -1) {
+ c_hot_pos += start;
+ }
+ break;
+ case TextAlignment.Centered:
+ start = Frame.Width / 2 - caption.RuneCount / 2;
+ caption = $"{new string (' ', start)}{caption}{new string (' ', Frame.Width - caption.RuneCount - start)}";
+ if (c_hot_pos > -1) {
+ c_hot_pos += start;
+ }
+ break;
+ case TextAlignment.Justified:
+ var words = caption.Split (" ");
+ var wLen = GetWordsLength (words, c_hot_pos, out int runeCount, out int w_hot_pos);
+ var space = (Frame.Width - runeCount) / (caption.Length - wLen);
+ caption = "";
+ for (int i = 0; i < words.Length; i++) {
+ if (i == words.Length - 1) {
+ caption += new string (' ', Frame.Width - caption.RuneCount - 1);
+ caption += words [i];
+ } else {
+ caption += words [i];
+ }
+ if (i < words.Length - 1) {
+ caption += new string (' ', space);
+ }
+ }
+ if (c_hot_pos > -1) {
+ if (wLen - runeCount == 0) {
+ c_hot_pos += (wLen - runeCount == 0 ? w_hot_pos * (space) - space - w_hot_pos + 1 : space + wLen - runeCount);
+ } else {
+ c_hot_pos += space + wLen - runeCount;
+ }
+ }
+ break;
+ }
+ }
+
+ return caption;
+ }
+
+ int GetWordsLength (ustring [] words, int hotPos, out int runeCount, out int wordHotPos)
+ {
+ int length = 0;
+ int rCount = 0;
+ int wHotPos = -1;
+ for (int i = 0; i < words.Length; i++) {
+ if (wHotPos == -1 && rCount + words [i].RuneCount >= hotPos)
+ wHotPos = i;
+ length += words [i].Length;
+ rCount += words [i].RuneCount;
+ }
+ if (wHotPos == -1 && hotPos > -1)
+ wHotPos = words.Length;
+ runeCount = rCount;
+ wordHotPos = wHotPos;
+ return length;
+ }
+
///
/// Pretty prints the View
///
@@ -1505,7 +1677,6 @@ namespace Terminal.Gui {
return false;
}
-
///
/// Method invoked when a mouse event is generated
///
diff --git a/Terminal.Gui/Views/Button.cs b/Terminal.Gui/Views/Button.cs
index db47043d4..b9e475338 100644
--- a/Terminal.Gui/Views/Button.cs
+++ b/Terminal.Gui/Views/Button.cs
@@ -137,9 +137,7 @@ namespace Terminal.Gui {
}
set {
- if (text?.Length != value?.Length) {
- SetWidthHeight (value, is_default);
- }
+ SetWidthHeight (value, is_default);
text = value;
Update ();
}
@@ -152,14 +150,14 @@ namespace Terminal.Gui {
get => textAlignment;
set {
textAlignment = value;
- SetNeedsDisplay ();
+ Update ();
}
}
- Rune _leftBracket = new Rune ('[');
- Rune _rightBracket = new Rune (']');
- Rune _leftDefault = new Rune ('<');
- Rune _rightDefault = new Rune ('>');
+ Rune _leftBracket = new Rune (Driver.LeftBracket);
+ Rune _rightBracket = new Rune (Driver.RightBracket);
+ Rune _leftDefault = new Rune (Driver.LeftDefaultIndicator);
+ Rune _rightDefault = new Rune (Driver.RightDefaultIndicator);
internal void Update ()
{
@@ -168,26 +166,7 @@ namespace Terminal.Gui {
else
shown_text = ustring.Make (_leftBracket) + " " + text + " " + ustring.Make (_rightBracket);
- hot_key = (Rune)0;
- hot_pos = shown_text.IndexOf ('_');
-
- if (hot_pos == -1) {
- // Use first upper-case char
- int i = 0;
- foreach (Rune c in shown_text) {
- if (Rune.IsUpper (c)) {
- hot_key = c;
- hot_pos = i;
- break;
- }
- i++;
- }
- } else {
- // Use char after '_'
- var start = shown_text [0, hot_pos];
- shown_text = start + shown_text [hot_pos + 1, shown_text.Length];
- hot_key = Char.ToUpper((char)shown_text [hot_pos]);
- }
+ shown_text = GetTextFromHotKey (shown_text, '_', out hot_pos, out hot_key);
SetNeedsDisplay ();
}
@@ -200,51 +179,8 @@ namespace Terminal.Gui {
Driver.SetAttribute (HasFocus ? ColorScheme.Focus : ColorScheme.Normal);
Move (0, 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;
- }
- }
+ var caption = GetTextAlignment (shown_text, hot_pos, out int s_hot_pos, TextAlignment);
+ c_hot_pos = s_hot_pos;
Driver.AddStr (caption);
@@ -255,17 +191,6 @@ namespace Terminal.Gui {
}
}
- 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 ()
{
@@ -274,7 +199,7 @@ namespace Terminal.Gui {
bool CheckKey (KeyEvent key)
{
- if (Char.ToUpper ((char)key.KeyValue) == hot_key) {
+ if ((char)key.KeyValue == hot_key) {
this.SuperView.SetFocus (this);
Clicked?.Invoke ();
return true;
diff --git a/Terminal.Gui/Views/Label.cs b/Terminal.Gui/Views/Label.cs
index 88d81bf6d..c387441b3 100644
--- a/Terminal.Gui/Views/Label.cs
+++ b/Terminal.Gui/Views/Label.cs
@@ -11,28 +11,6 @@ using System.Linq;
using NStack;
namespace Terminal.Gui {
- ///
- /// Text alignment enumeration, controls how text is displayed.
- ///
- public enum TextAlignment {
- ///
- /// Aligns the text to the left of the frame.
- ///
- Left,
- ///
- /// Aligns the text to the right side of the frame.
- ///
- Right,
- ///
- /// Centers the text in the frame.
- ///
- Centered,
- ///
- /// Shows the text as justified text in the frame.
- ///
- Justified
- }
-
///
/// The Label displays a string at a given position and supports multiple lines separted by newline characters.
///
diff --git a/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs
index be51b1d79..af56b2982 100644
--- a/UICatalog/Scenarios/Buttons.cs
+++ b/UICatalog/Scenarios/Buttons.cs
@@ -89,7 +89,7 @@ namespace UICatalog {
textChanger.Clicked = () => textChanger.Text += "!";
Win.Add (button = new Button ("Lets see if this will move as \"Text Changer\" grows") {
- X = Pos.Right(textChanger) + 2,
+ X = Pos.Right (textChanger) + 2,
Y = Pos.Y (textChanger),
});
@@ -105,7 +105,7 @@ namespace UICatalog {
var computedFrame = new FrameView ("Computed Layout") {
X = 0,
Y = Pos.Bottom (removeButton) + 1,
- Width = Dim.Percent(50),
+ Width = Dim.Percent (50),
Height = 5
};
Win.Add (computedFrame);
@@ -113,7 +113,7 @@ namespace UICatalog {
// Demonstrates how changing the View.Frame property can move Views
var moveBtn = new Button ("Move This \u263b Button _via Pos") {
X = 0,
- Y = Pos.Center() - 1,
+ Y = Pos.Center () - 1,
Width = 30,
ColorScheme = Colors.Error,
};
@@ -132,14 +132,14 @@ namespace UICatalog {
};
sizeBtn.Clicked = () => {
sizeBtn.Width = sizeBtn.Frame.Width + 5;
- computedFrame.LayoutSubviews (); // BUGBUG: This call should not be needed. View.X is not causing relayout correctly
+ //computedFrame.LayoutSubviews (); // FIXED: This call should not be needed. View.X is not causing relayout correctly
};
computedFrame.Add (sizeBtn);
var absoluteFrame = new FrameView ("Absolute Layout") {
- X = Pos.Right(computedFrame),
+ X = Pos.Right (computedFrame),
Y = Pos.Bottom (removeButton) + 1,
- Width = Dim.Fill(),
+ Width = Dim.Fill (),
Height = 5
};
Win.Add (absoluteFrame);
@@ -154,7 +154,7 @@ namespace UICatalog {
absoluteFrame.Add (moveBtnA);
// Demonstrates how changing the View.Frame property can SIZE Views (#583)
- var sizeBtnA = new Button (0, 2, "Size This Button via Frame") {
+ var sizeBtnA = new Button (0, 2, " ~ s gui.cs master ↑10 = Со_хранить") {
ColorScheme = Colors.Error,
};
sizeBtnA.Clicked = () => {
@@ -172,34 +172,6 @@ namespace UICatalog {
X = 4,
Y = Pos.Bottom (label) + 1,
SelectedItem = 2,
- SelectedItemChanged = (args) => {
- switch (args.SelectedItem) {
- case 0:
- moveBtn.TextAlignment = TextAlignment.Left;
- sizeBtn.TextAlignment = TextAlignment.Left;
- moveBtnA.TextAlignment = TextAlignment.Left;
- sizeBtnA.TextAlignment = TextAlignment.Left;
- break;
- case 1:
- moveBtn.TextAlignment = TextAlignment.Right;
- sizeBtn.TextAlignment = TextAlignment.Right;
- moveBtnA.TextAlignment = TextAlignment.Right;
- sizeBtnA.TextAlignment = TextAlignment.Right;
- break;
- case 2:
- moveBtn.TextAlignment = TextAlignment.Centered;
- sizeBtn.TextAlignment = TextAlignment.Centered;
- moveBtnA.TextAlignment = TextAlignment.Centered;
- sizeBtnA.TextAlignment = TextAlignment.Centered;
- break;
- case 3:
- moveBtn.TextAlignment = TextAlignment.Justified;
- sizeBtn.TextAlignment = TextAlignment.Justified;
- moveBtnA.TextAlignment = TextAlignment.Justified;
- sizeBtnA.TextAlignment = TextAlignment.Justified;
- break;
- }
- }
};
Win.Add (radioGroup);
@@ -208,7 +180,9 @@ namespace UICatalog {
{
// Remove the '_'
var i = txt.IndexOf ('_');
- var start = txt [0, i];
+ ustring start = "";
+ if (i > -1)
+ start = txt [0, i];
txt = start + txt [i + 1, txt.Length];
// Move over one or go to start
@@ -224,15 +198,66 @@ namespace UICatalog {
return txt;
}
- var moveHotKeyBtn = new Button ("Click to Change th_is Button's Hotkey") {
+ var mhkb = "Click to Change th_is Button's Hotkey";
+ var moveHotKeyBtn = new Button (mhkb) {
X = 2,
Y = Pos.Bottom (radioGroup) + 1,
+ Width = mhkb.Length + 10,
ColorScheme = Colors.TopLevel,
};
moveHotKeyBtn.Clicked = () => {
moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text);
};
Win.Add (moveHotKeyBtn);
+
+ var muhkb = " ~ s gui.cs master ↑10 = Сохранить";
+ var moveUnicodeHotKeyBtn = new Button (muhkb) {
+ X = Pos.Right (moveHotKeyBtn) + 6,
+ Y = Pos.Bottom (radioGroup) + 1,
+ Width = muhkb.Length + 30,
+ ColorScheme = Colors.TopLevel,
+ };
+ moveUnicodeHotKeyBtn.Clicked = () => {
+ moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text);
+ };
+ Win.Add (moveUnicodeHotKeyBtn);
+
+ radioGroup.SelectedItemChanged += (args) => {
+ switch (args.SelectedItem) {
+ case 0:
+ moveBtn.TextAlignment = TextAlignment.Left;
+ sizeBtn.TextAlignment = TextAlignment.Left;
+ moveBtnA.TextAlignment = TextAlignment.Left;
+ sizeBtnA.TextAlignment = TextAlignment.Left;
+ moveHotKeyBtn.TextAlignment = TextAlignment.Left;
+ moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Left;
+ break;
+ case 1:
+ moveBtn.TextAlignment = TextAlignment.Right;
+ sizeBtn.TextAlignment = TextAlignment.Right;
+ moveBtnA.TextAlignment = TextAlignment.Right;
+ sizeBtnA.TextAlignment = TextAlignment.Right;
+ moveHotKeyBtn.TextAlignment = TextAlignment.Right;
+ moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Right;
+ break;
+ case 2:
+ moveBtn.TextAlignment = TextAlignment.Centered;
+ sizeBtn.TextAlignment = TextAlignment.Centered;
+ moveBtnA.TextAlignment = TextAlignment.Centered;
+ sizeBtnA.TextAlignment = TextAlignment.Centered;
+ moveHotKeyBtn.TextAlignment = TextAlignment.Centered;
+ moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Centered;
+ break;
+ case 3:
+ moveBtn.TextAlignment = TextAlignment.Justified;
+ sizeBtn.TextAlignment = TextAlignment.Justified;
+ moveBtnA.TextAlignment = TextAlignment.Justified;
+ sizeBtnA.TextAlignment = TextAlignment.Justified;
+ moveHotKeyBtn.TextAlignment = TextAlignment.Justified;
+ moveUnicodeHotKeyBtn.TextAlignment = TextAlignment.Justified;
+ break;
+ }
+ };
}
}
-}
+}
\ No newline at end of file