浏览代码

Resolves Button Text Alignment with Unicode chars.

BDisp 5 年之前
父节点
当前提交
43c958842e
共有 3 个文件被更改,包括 91 次插入36 次删除
  1. 64 1
      Terminal.Gui/Core/View.cs
  2. 16 34
      Terminal.Gui/Views/Button.cs
  3. 11 1
      UICatalog/Scenarios/Buttons.cs

+ 64 - 1
Terminal.Gui/Core/View.cs

@@ -1450,6 +1450,70 @@ namespace Terminal.Gui {
 			OnLayoutComplete (new LayoutEventArgs () { OldBounds = oldBounds });
 			OnLayoutComplete (new LayoutEventArgs () { OldBounds = oldBounds });
 		}
 		}
 
 
+		/// <summary>
+		/// A generic virtual method at the level of View to manipulate any hot-keys.
+		/// </summary>
+		/// <param name="text">The text to manipulate.</param>
+		/// <param name="hotKey">The hot-key to look for.</param>
+		/// <param name="hotPos">The returning hot-key position.</param>
+		/// <param name="showHotKey">The character immediately to the right relative to the hot-key position</param>
+		/// <returns></returns>
+		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;
+		}
+
 		/// <summary>
 		/// <summary>
 		/// Pretty prints the View
 		/// Pretty prints the View
 		/// </summary>
 		/// </summary>
@@ -1505,7 +1569,6 @@ namespace Terminal.Gui {
 			return false;
 			return false;
 		}
 		}
 
 
-
 		/// <summary>
 		/// <summary>
 		/// Method invoked when a mouse event is generated
 		/// Method invoked when a mouse event is generated
 		/// </summary>
 		/// </summary>

+ 16 - 34
Terminal.Gui/Views/Button.cs

@@ -168,26 +168,7 @@ namespace Terminal.Gui {
 			else
 			else
 				shown_text = ustring.Make (_leftBracket) + " " + text + " " + ustring.Make (_rightBracket);
 				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 ();
 			SetNeedsDisplay ();
 		}
 		}
@@ -207,30 +188,30 @@ namespace Terminal.Gui {
 			if (Frame.Width > shown_text.Length + 1) {
 			if (Frame.Width > shown_text.Length + 1) {
 				switch (TextAlignment) {
 				switch (TextAlignment) {
 				case TextAlignment.Left:
 				case TextAlignment.Left:
-					caption += new string (' ', Frame.Width - caption.Length);
+					caption += new string (' ', Frame.Width - caption.RuneCount);
 					break;
 					break;
 				case TextAlignment.Right:
 				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) {
 					if (c_hot_pos > -1) {
 						c_hot_pos += start;
 						c_hot_pos += start;
 					}
 					}
 					break;
 					break;
 				case TextAlignment.Centered:
 				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) {
 					if (c_hot_pos > -1) {
 						c_hot_pos += start;
 						c_hot_pos += start;
 					}
 					}
 					break;
 					break;
 				case TextAlignment.Justified:
 				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 = "";
 					caption = "";
 					for (int i = 0; i < words.Length; i++) {
 					for (int i = 0; i < words.Length; i++) {
 						if (i == words.Length - 1) {
 						if (i == words.Length - 1) {
-							caption += new string (' ', Frame.Width - caption.Length - 1);
+							caption += new string (' ', Frame.Width - caption.RuneCount - 1);
 							caption += words [i];
 							caption += words [i];
 						} else {
 						} else {
 							caption += words [i];
 							caption += words [i];
@@ -240,7 +221,7 @@ namespace Terminal.Gui {
 						}
 						}
 					}
 					}
 					if (c_hot_pos > -1) {
 					if (c_hot_pos > -1) {
-						c_hot_pos += space - 1;
+						c_hot_pos += space - 1 + (wLen - runeCount == 0 ? 0 : wLen - runeCount + 1);
 					}
 					}
 					break;
 					break;
 				}
 				}
@@ -255,14 +236,15 @@ namespace Terminal.Gui {
 			}
 			}
 		}
 		}
 
 
-		int GetWordsLength (string[] words)
+		int GetWordsLength (ustring [] words, out int runeCount)
 		{
 		{
 			int length = 0;
 			int length = 0;
-
+			int rCount = 0;
 			for (int i = 0; i < words.Length; i++) {
 			for (int i = 0; i < words.Length; i++) {
 				length += words [i].Length;
 				length += words [i].Length;
+				rCount += words [i].RuneCount;
 			}
 			}
-
+			runeCount = rCount;
 			return length;
 			return length;
 		}
 		}
 
 
@@ -274,7 +256,7 @@ namespace Terminal.Gui {
 
 
 		bool CheckKey (KeyEvent key)
 		bool CheckKey (KeyEvent key)
 		{
 		{
-			if (Char.ToUpper ((char)key.KeyValue) == hot_key) {
+			if ((char)key.KeyValue == hot_key) {
 				this.SuperView.SetFocus (this);
 				this.SuperView.SetFocus (this);
 				Clicked?.Invoke ();
 				Clicked?.Invoke ();
 				return true;
 				return true;

+ 11 - 1
UICatalog/Scenarios/Buttons.cs

@@ -154,7 +154,7 @@ namespace UICatalog {
 			absoluteFrame.Add (moveBtnA);
 			absoluteFrame.Add (moveBtnA);
 
 
 			// Demonstrates how changing the View.Frame property can SIZE Views (#583)
 			// 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,
 				ColorScheme = Colors.Error,
 			};
 			};
 			sizeBtnA.Clicked = () => {
 			sizeBtnA.Clicked = () => {
@@ -233,6 +233,16 @@ namespace UICatalog {
 				moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text);
 				moveHotKeyBtn.Text = MoveHotkey (moveHotKeyBtn.Text);
 			};
 			};
 			Win.Add (moveHotKeyBtn);
 			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);
 		}
 		}
 	}
 	}
 }
 }