diff --git a/Terminal.Gui/Core/View.cs b/Terminal.Gui/Core/View.cs
index 6ac03c572..1909bae31 100644
--- a/Terminal.Gui/Core/View.cs
+++ b/Terminal.Gui/Core/View.cs
@@ -1450,6 +1450,70 @@ 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
+ ///
+ 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 = (char)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 (Rune.IsUpper (c)) {
+ hot_key = (char)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;
+ }
+
///
/// Pretty prints the View
///
@@ -1505,7 +1569,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..bff8d0a44 100644
--- a/Terminal.Gui/Views/Button.cs
+++ b/Terminal.Gui/Views/Button.cs
@@ -168,26 +168,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 ();
}
@@ -207,30 +188,30 @@ namespace Terminal.Gui {
if (Frame.Width > shown_text.Length + 1) {
switch (TextAlignment) {
case TextAlignment.Left:
- caption += new string (' ', Frame.Width - caption.Length);
+ caption += new string (' ', Frame.Width - caption.RuneCount);
break;
case TextAlignment.Right:
- start = Frame.Width - caption.Length;
- caption = $"{new string (' ', Frame.Width - caption.Length)}{caption}";
+ 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.Length / 2;
- caption = $"{new string (' ', start)}{caption}{new string (' ', Frame.Width - caption.Length - start)}";
+ 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.ToString ().Split (new string [] { " " }, StringSplitOptions.RemoveEmptyEntries);
- var wLen = GetWordsLength (words);
- var space = (Frame.Width - wLen) / (caption.Length - wLen);
+ var words = caption.Split (" ");
+ var wLen = GetWordsLength (words, out int runeCount);
+ 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.Length - 1);
+ caption += new string (' ', Frame.Width - caption.RuneCount - 1);
caption += words [i];
} else {
caption += words [i];
@@ -240,7 +221,7 @@ namespace Terminal.Gui {
}
}
if (c_hot_pos > -1) {
- c_hot_pos += space - 1;
+ c_hot_pos += space - 1 + (wLen - runeCount == 0 ? 0 : wLen - runeCount + 1);
}
break;
}
@@ -255,14 +236,15 @@ namespace Terminal.Gui {
}
}
- int GetWordsLength (string[] words)
+ int GetWordsLength (ustring [] words, out int runeCount)
{
int length = 0;
-
+ int rCount = 0;
for (int i = 0; i < words.Length; i++) {
length += words [i].Length;
+ rCount += words [i].RuneCount;
}
-
+ runeCount = rCount;
return length;
}
@@ -274,7 +256,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/UICatalog/Scenarios/Buttons.cs b/UICatalog/Scenarios/Buttons.cs
index 08c219d16..e6e4bff6c 100644
--- a/UICatalog/Scenarios/Buttons.cs
+++ b/UICatalog/Scenarios/Buttons.cs
@@ -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 = () => {
@@ -233,6 +233,16 @@ namespace UICatalog {
moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text);
};
Win.Add (moveHotKeyBtn);
+
+ var moveUnicodeHotKeyBtn = new Button (" ~ s gui.cs master ↑10 = Сохранить") {
+ X = Pos.Right (moveHotKeyBtn) + 6,
+ Y = Pos.Bottom (radioGroup) + 1,
+ ColorScheme = Colors.TopLevel,
+ };
+ moveUnicodeHotKeyBtn.Clicked = () => {
+ moveUnicodeHotKeyBtn.Text = MoveHotkey (moveUnicodeHotKeyBtn.Text);
+ };
+ Win.Add (moveUnicodeHotKeyBtn);
}
}
}