using System.Text; namespace HistoryView.Controls.Input; public partial class TextboxKeyboard : UserControl { public TextboxKeyboard() { InitializeComponent(); } private void TextBox_GotFocus(object sender, RoutedEventArgs e) { //if (TabTipHelper.ShowTaptip()) // return; if (KeyboardPopStatus.IsDisplayed) return; KeyboardPopStatus.IsDisplayed = true; this.PopKeyboard.IsOpen = true; this.Display = this.Text?.ToString()!; } public bool DirectInput { get { return (bool)GetValue(DirectInputProperty); } set { SetValue(DirectInputProperty, value); } } public static readonly DependencyProperty DirectInputProperty = DependencyProperty.Register("DirectInput", typeof(bool), typeof(TextboxKeyboard), new PropertyMetadata(false, DirectInputChangedCallback)); private static void DirectInputChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is not TextboxKeyboard keyboard) return; if (e.NewValue is not bool direct) return; if (direct) { keyboard.Preview.Visibility = Visibility.Collapsed; keyboard.Selection.Visibility = Visibility.Collapsed; keyboard.Cancel.IsEnabled = false; keyboard.Cancel.Background = (Brush)App.Current.Resources["DisableColor"]; } else { keyboard.Preview.Visibility = Visibility.Visible; keyboard.Selection.Visibility = Visibility.Visible; keyboard.Cancel.IsEnabled = true; keyboard.Cancel.Background = (Brush)App.Current.Resources["EmergencyColor"]; } } public object DisplayContent { get { return (object)GetValue(DisplayContentProperty); } set { SetValue(DisplayContentProperty, value); } } public static readonly DependencyProperty DisplayContentProperty = DependencyProperty.Register("DisplayContent", typeof(object), typeof(TextboxKeyboard), new PropertyMetadata(default)); public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(TextboxKeyboard), new PropertyMetadata(default)); public IEnumerable BackWords { get { return (IEnumerable)GetValue(BackWordsProperty); } set { SetValue(BackWordsProperty, value); } } // Using a DependencyProperty as the backing store for BackWords. This enables animation, styling, binding, etc... public static readonly DependencyProperty BackWordsProperty = DependencyProperty.Register("BackWords", typeof(IEnumerable), typeof(TextboxKeyboard), new PropertyMetadata(default)); #region Private Dependcy Properties private string Display { get { return (string)GetValue(DisplayProperty); } set { SetValue(DisplayProperty, value); } } public static readonly DependencyProperty DisplayProperty = DependencyProperty.Register("Display", typeof(string), typeof(TextboxKeyboard), new PropertyMetadata(default)); public ObservableCollection Filtered { get { return (ObservableCollection)GetValue(FilteredProperty); } set { SetValue(FilteredProperty, value); } } // Using a DependencyProperty as the backing store for Filtered. This enables animation, styling, binding, etc... public static readonly DependencyProperty FilteredProperty = DependencyProperty.Register("Filtered", typeof(ObservableCollection), typeof(TextboxKeyboard), new PropertyMetadata(default)); private bool IsCaps { get { return (bool)GetValue(IsCapsProperty); } set { SetValue(IsCapsProperty, value); } } public static readonly DependencyProperty IsCapsProperty = DependencyProperty.Register("IsCaps", typeof(bool), typeof(TextboxKeyboard), new PropertyMetadata(false, PropertyChangedCallback)); private bool IsShift { get { return (bool)GetValue(IsShiftProperty); } set { SetValue(IsShiftProperty, value); } } public static readonly DependencyProperty IsShiftProperty = DependencyProperty.Register("IsShift", typeof(bool), typeof(TextboxKeyboard), new PropertyMetadata(false, PropertyChangedCallback)); static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is not TextboxKeyboard keyboard) return; if (e.NewValue is not bool b) return; List textBlocks = FindVisualChildren.Find(keyboard.Line1); textBlocks.AddRange(FindVisualChildren.Find(keyboard.Line2)); textBlocks.AddRange(FindVisualChildren.Find(keyboard.Line3)); foreach (TextBlock textBlock in textBlocks) { if (textBlock.Text.Length != 1) continue; byte t = Encoding.ASCII.GetBytes(textBlock.Text)[0]; if (b && t >= 97 && t <= 122) { textBlock.Text = Encoding.ASCII.GetString([(byte)(t - 32)]); } if (!b && t >= 65 && t <= 90) { textBlock.Text = Encoding.ASCII.GetString([(byte)(t + 32)]); } } } #endregion private void CancelConfirm(object sender, RoutedEventArgs e) { if (sender is not Button button) return; if (button.CommandParameter is not string input) return; if (DirectInput) { this.PopKeyboard.IsOpen = false; KeyboardPopStatus.IsDisplayed = false; Keyboard.ClearFocus(); return; } if (input == "Cancel") { this.Display = string.Empty; this.PopKeyboard.IsOpen = false; KeyboardPopStatus.IsDisplayed = false; Keyboard.ClearFocus(); return; } this.Text = Display; this.PopKeyboard.IsOpen = false; KeyboardPopStatus.IsDisplayed = false; Keyboard.ClearFocus(); } private void SendKey(object sender, RoutedEventArgs e) { if (sender is not Button button) return; if (button.Content is not string input) return; if (Text is null) return; input = input switch { "Space" => " ", _ => input }; if (this.IsCaps) input = input.ToUpper(); if (this.IsShift) { this.IsShift = false; input = input.ToUpper(); } if (!this.DirectInput) { this.Display += input; if (this.BackWords is null) return; this.Filtered ??= []; this.Filtered.Clear(); IEnumerable filtered = this.BackWords.Where(t => t.Contains(this.Display)); this.Filtered.AddRange(filtered); } else { this.Text += input; } } private void Delete(object sender, RoutedEventArgs e) { if (!this.DirectInput) { if (string.IsNullOrEmpty(this.Display)) return; if (Display.Length == 1) { Display = string.Empty; return; } Display = Display[..^1]; } else { if (string.IsNullOrEmpty(this.Text)) return; if (Text.Length == 1) { Text = string.Empty; return; } Text = Text[..^1]; } } private void Clear(object sender, RoutedEventArgs e) { if (!this.DirectInput) { Display = string.Empty; this.Filtered ??= []; this.Filtered.Clear(); } else { Text = string.Empty; } } private void Select(object sender, RoutedEventArgs e) { if (sender is not Button button) return; if (button.Content is not string input) return; if (Text is null) return; this.Display = input; this.Filtered ??= []; this.Filtered.Clear(); } private void Button_TouchDown(object sender, TouchEventArgs e) { if (sender is not Button button) return; if (IsShift || IsCaps) this.HintText.Text = ((string)button.Content).ToUpper(); else this.HintText.Text = (string)button.Content; this.Hint.PlacementTarget = button; this.Hint.IsOpen = true; } private void Button_TouchLeave(object sender, TouchEventArgs e) { Task.Factory.StartNew(() => { Thread.Sleep(200); App.Current.Dispatcher.Invoke(() => { this.Hint.IsOpen = false; }); }); } }