using System.Text; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Presenters; using Avalonia.Interactivity; namespace GSS2.Views; public partial class TextKeyboardView : UserControl { public static readonly StyledProperty ValueProperty = AvaloniaProperty.Register(nameof(Value)); public string? Value { get => GetValue(ValueProperty); set => SetValue(ValueProperty, value); } public static readonly StyledProperty IsMultilineProperty = AvaloniaProperty.Register(nameof(IsMultiline), defaultValue: false); public bool IsMultiline { get => GetValue(IsMultilineProperty); set => SetValue(IsMultilineProperty, value); } public static readonly RoutedEvent ClosedEvent = RoutedEvent.Register(nameof(KeyboardClosed), RoutingStrategies.Bubble); public event EventHandler KeyboardClosed { add => AddHandler(ClosedEvent, value); remove => RemoveHandler(ClosedEvent, value); } private readonly TextPresenter? _presenter; private StringBuilder _text = new(); private bool _changingValue = false; private int _cursor = 0; private bool _isUppercase = false; private bool _isEnglish = false; public TextKeyboardView(string? value = null) { InitializeComponent(); ValueProperty.Changed.AddClassHandler((sender, value) => { if (sender != this) return; if (_changingValue) return; if (value.NewValue is not string strValue) { _changingValue = true; _text = new(); _cursor = _text.Length; _changingValue = false; UpdateDisplay(); return; } _changingValue = true; _text.Clear(); _text.Insert(0, strValue); _cursor = _text.Length; _changingValue = false; UpdateDisplay(); }); IsMultilineProperty.Changed.AddClassHandler((sender, value) => { if (sender != this) return; if (value.NewValue is not bool boolValue) return; EnterRussianLowercase.IsVisible = boolValue; EnterRussianUppercase.IsVisible = boolValue; EnterEnglishLowercase.IsVisible = boolValue; EnterEnglishUppercase.IsVisible = boolValue; }); _presenter = this.FindControl("Text"); if (!string.IsNullOrEmpty(value)) _text.Append(value); _cursor = _text.Length; _presenter?.ShowCaret(); UpdateDisplay(); RussianLowercase.IsVisible = !_isUppercase && !_isEnglish; RussianUppercase.IsVisible = _isUppercase && !_isEnglish; EnglishLowercase.IsVisible = !_isUppercase && _isEnglish; EnglishUppercase.IsVisible = _isUppercase && _isEnglish; EnterRussianLowercase.IsVisible = IsMultiline; EnterRussianUppercase.IsVisible = IsMultiline; EnterEnglishLowercase.IsVisible = IsMultiline; EnterEnglishUppercase.IsVisible = IsMultiline; } private void KeyPressed(object? sender, RoutedEventArgs e) { if (sender is not Button btn || btn.Content is not string symbol) return; _text.Insert(_cursor, symbol); _cursor++; UpdateDisplay(); } private void EnterKeyPressed(object? sender, RoutedEventArgs e) { _text.Insert(_cursor, "\n"); _cursor++; UpdateDisplay(); } private void Backspace(object? sender, RoutedEventArgs e) { if (_cursor > 0) { _cursor--; _text.Remove(_cursor, 1); UpdateDisplay(); } } private void SwitchCase(object? sender, RoutedEventArgs e) { _isUppercase = !_isUppercase; RussianLowercase.IsVisible = !_isUppercase && !_isEnglish; RussianUppercase.IsVisible = _isUppercase && !_isEnglish; EnglishLowercase.IsVisible = !_isUppercase && _isEnglish; EnglishUppercase.IsVisible = _isUppercase && _isEnglish; } private void SwitchLagnuage(object? sender, RoutedEventArgs e) { _isEnglish = !_isEnglish; RussianLowercase.IsVisible = !_isUppercase && !_isEnglish; RussianUppercase.IsVisible = _isUppercase && !_isEnglish; EnglishLowercase.IsVisible = !_isUppercase && _isEnglish; EnglishUppercase.IsVisible = _isUppercase && _isEnglish; } private void MoveCursorLeft(object? sender, RoutedEventArgs e) { _cursor = Math.Max(0, _cursor - 1); UpdateDisplay(); } private void MoveCursorRight(object? sender, RoutedEventArgs e) { _cursor = Math.Min(_text.Length, _cursor + 1); UpdateDisplay(); } private void Accept(object? sender, RoutedEventArgs e) { Value = _text.ToString(); } private void Cancel(object? sender, RoutedEventArgs e) => Value = null; private void UpdateDisplay() { if (_presenter is null) return; _presenter.Text = _text.ToString(); _presenter.CaretIndex = _cursor; _presenter.InvalidateVisual(); Value = _text.ToString(); } }