TextboxKeyboard.xaml.cs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. using System.Text;
  2. namespace HistoryView.Controls.Input;
  3. public partial class TextboxKeyboard : UserControl
  4. {
  5. public TextboxKeyboard()
  6. {
  7. InitializeComponent();
  8. }
  9. private void TextBox_GotFocus(object sender, RoutedEventArgs e)
  10. {
  11. //if (TabTipHelper.ShowTaptip())
  12. // return;
  13. if (KeyboardPopStatus.IsDisplayed)
  14. return;
  15. KeyboardPopStatus.IsDisplayed = true;
  16. this.PopKeyboard.IsOpen = true;
  17. this.Display = this.Text?.ToString()!;
  18. }
  19. public bool DirectInput
  20. {
  21. get { return (bool)GetValue(DirectInputProperty); }
  22. set { SetValue(DirectInputProperty, value); }
  23. }
  24. public static readonly DependencyProperty DirectInputProperty =
  25. DependencyProperty.Register("DirectInput", typeof(bool), typeof(TextboxKeyboard), new PropertyMetadata(false, DirectInputChangedCallback));
  26. private static void DirectInputChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  27. {
  28. if (d is not TextboxKeyboard keyboard)
  29. return;
  30. if (e.NewValue is not bool direct)
  31. return;
  32. if (direct)
  33. {
  34. keyboard.Preview.Visibility = Visibility.Collapsed;
  35. keyboard.Selection.Visibility = Visibility.Collapsed;
  36. keyboard.Cancel.IsEnabled = false;
  37. keyboard.Cancel.Background = (Brush)App.Current.Resources["DisableColor"];
  38. }
  39. else
  40. {
  41. keyboard.Preview.Visibility = Visibility.Visible;
  42. keyboard.Selection.Visibility = Visibility.Visible;
  43. keyboard.Cancel.IsEnabled = true;
  44. keyboard.Cancel.Background = (Brush)App.Current.Resources["EmergencyColor"];
  45. }
  46. }
  47. public object DisplayContent
  48. {
  49. get { return (object)GetValue(DisplayContentProperty); }
  50. set { SetValue(DisplayContentProperty, value); }
  51. }
  52. public static readonly DependencyProperty DisplayContentProperty =
  53. DependencyProperty.Register("DisplayContent", typeof(object), typeof(TextboxKeyboard), new PropertyMetadata(default));
  54. public string Text
  55. {
  56. get { return (string)GetValue(TextProperty); }
  57. set { SetValue(TextProperty, value); }
  58. }
  59. public static readonly DependencyProperty TextProperty =
  60. DependencyProperty.Register("Text", typeof(string), typeof(TextboxKeyboard), new PropertyMetadata(default));
  61. public IEnumerable<string> BackWords
  62. {
  63. get { return (IEnumerable<string>)GetValue(BackWordsProperty); }
  64. set { SetValue(BackWordsProperty, value); }
  65. }
  66. // Using a DependencyProperty as the backing store for BackWords. This enables animation, styling, binding, etc...
  67. public static readonly DependencyProperty BackWordsProperty =
  68. DependencyProperty.Register("BackWords", typeof(IEnumerable<string>), typeof(TextboxKeyboard), new PropertyMetadata(default));
  69. #region Private Dependcy Properties
  70. private string Display
  71. {
  72. get { return (string)GetValue(DisplayProperty); }
  73. set { SetValue(DisplayProperty, value); }
  74. }
  75. public static readonly DependencyProperty DisplayProperty =
  76. DependencyProperty.Register("Display", typeof(string), typeof(TextboxKeyboard), new PropertyMetadata(default));
  77. public ObservableCollection<string> Filtered
  78. {
  79. get { return (ObservableCollection<string>)GetValue(FilteredProperty); }
  80. set { SetValue(FilteredProperty, value); }
  81. }
  82. // Using a DependencyProperty as the backing store for Filtered. This enables animation, styling, binding, etc...
  83. public static readonly DependencyProperty FilteredProperty =
  84. DependencyProperty.Register("Filtered", typeof(ObservableCollection<string>), typeof(TextboxKeyboard), new PropertyMetadata(default));
  85. private bool IsCaps
  86. {
  87. get { return (bool)GetValue(IsCapsProperty); }
  88. set { SetValue(IsCapsProperty, value); }
  89. }
  90. public static readonly DependencyProperty IsCapsProperty =
  91. DependencyProperty.Register("IsCaps", typeof(bool), typeof(TextboxKeyboard), new PropertyMetadata(false, PropertyChangedCallback));
  92. private bool IsShift
  93. {
  94. get { return (bool)GetValue(IsShiftProperty); }
  95. set { SetValue(IsShiftProperty, value); }
  96. }
  97. public static readonly DependencyProperty IsShiftProperty =
  98. DependencyProperty.Register("IsShift", typeof(bool), typeof(TextboxKeyboard), new PropertyMetadata(false, PropertyChangedCallback));
  99. static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  100. {
  101. if (d is not TextboxKeyboard keyboard)
  102. return;
  103. if (e.NewValue is not bool b)
  104. return;
  105. List<TextBlock> textBlocks = FindVisualChildren.Find<TextBlock>(keyboard.Line1);
  106. textBlocks.AddRange(FindVisualChildren.Find<TextBlock>(keyboard.Line2));
  107. textBlocks.AddRange(FindVisualChildren.Find<TextBlock>(keyboard.Line3));
  108. foreach (TextBlock textBlock in textBlocks)
  109. {
  110. if (textBlock.Text.Length != 1)
  111. continue;
  112. byte t = Encoding.ASCII.GetBytes(textBlock.Text)[0];
  113. if (b && t >= 97 && t <= 122)
  114. {
  115. textBlock.Text = Encoding.ASCII.GetString([(byte)(t - 32)]);
  116. }
  117. if (!b && t >= 65 && t <= 90)
  118. {
  119. textBlock.Text = Encoding.ASCII.GetString([(byte)(t + 32)]);
  120. }
  121. }
  122. }
  123. #endregion
  124. private void CancelConfirm(object sender, RoutedEventArgs e)
  125. {
  126. if (sender is not Button button)
  127. return;
  128. if (button.CommandParameter is not string input)
  129. return;
  130. if (DirectInput)
  131. {
  132. this.PopKeyboard.IsOpen = false;
  133. KeyboardPopStatus.IsDisplayed = false;
  134. Keyboard.ClearFocus();
  135. return;
  136. }
  137. if (input == "Cancel")
  138. {
  139. this.Display = string.Empty;
  140. this.PopKeyboard.IsOpen = false;
  141. KeyboardPopStatus.IsDisplayed = false;
  142. Keyboard.ClearFocus();
  143. return;
  144. }
  145. this.Text = Display;
  146. this.PopKeyboard.IsOpen = false;
  147. KeyboardPopStatus.IsDisplayed = false;
  148. Keyboard.ClearFocus();
  149. }
  150. private void SendKey(object sender, RoutedEventArgs e)
  151. {
  152. if (sender is not Button button)
  153. return;
  154. if (button.Content is not string input)
  155. return;
  156. if (Text is null)
  157. return;
  158. input = input switch
  159. {
  160. "Space" => " ",
  161. _ => input
  162. };
  163. if (this.IsCaps)
  164. input = input.ToUpper();
  165. if (this.IsShift)
  166. {
  167. this.IsShift = false;
  168. input = input.ToUpper();
  169. }
  170. if (!this.DirectInput)
  171. {
  172. this.Display += input;
  173. if (this.BackWords is null)
  174. return;
  175. this.Filtered ??= [];
  176. this.Filtered.Clear();
  177. IEnumerable<string> filtered = this.BackWords.Where(t => t.Contains(this.Display));
  178. this.Filtered.AddRange(filtered);
  179. }
  180. else
  181. {
  182. this.Text += input;
  183. }
  184. }
  185. private void Delete(object sender, RoutedEventArgs e)
  186. {
  187. if (!this.DirectInput)
  188. {
  189. if (string.IsNullOrEmpty(this.Display))
  190. return;
  191. if (Display.Length == 1)
  192. {
  193. Display = string.Empty;
  194. return;
  195. }
  196. Display = Display[..^1];
  197. }
  198. else
  199. {
  200. if (string.IsNullOrEmpty(this.Text))
  201. return;
  202. if (Text.Length == 1)
  203. {
  204. Text = string.Empty;
  205. return;
  206. }
  207. Text = Text[..^1];
  208. }
  209. }
  210. private void Clear(object sender, RoutedEventArgs e)
  211. {
  212. if (!this.DirectInput)
  213. {
  214. Display = string.Empty;
  215. this.Filtered ??= [];
  216. this.Filtered.Clear();
  217. }
  218. else
  219. {
  220. Text = string.Empty;
  221. }
  222. }
  223. private void Select(object sender, RoutedEventArgs e)
  224. {
  225. if (sender is not Button button)
  226. return;
  227. if (button.Content is not string input)
  228. return;
  229. if (Text is null)
  230. return;
  231. this.Display = input;
  232. this.Filtered ??= [];
  233. this.Filtered.Clear();
  234. }
  235. private void Button_TouchDown(object sender, TouchEventArgs e)
  236. {
  237. if (sender is not Button button)
  238. return;
  239. if (IsShift || IsCaps)
  240. this.HintText.Text = ((string)button.Content).ToUpper();
  241. else
  242. this.HintText.Text = (string)button.Content;
  243. this.Hint.PlacementTarget = button;
  244. this.Hint.IsOpen = true;
  245. }
  246. private void Button_TouchLeave(object sender, TouchEventArgs e)
  247. {
  248. Task.Factory.StartNew(() =>
  249. {
  250. Thread.Sleep(200);
  251. App.Current.Dispatcher.Invoke(() =>
  252. {
  253. this.Hint.IsOpen = false;
  254. });
  255. });
  256. }
  257. }