Files
Minint/Minint/Controls/EditableTextBlock.cs
2026-03-29 16:51:43 +03:00

130 lines
3.4 KiB
C#

using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Media;
namespace Minint.Controls;
/// <summary>
/// Shows a TextBlock by default; switches to an inline TextBox on double-click.
/// Commits on Enter or focus loss, cancels on Escape.
/// </summary>
public class EditableTextBlock : Control
{
public static readonly StyledProperty<string> TextProperty =
AvaloniaProperty.Register<EditableTextBlock, string>(nameof(Text), defaultBindingMode: Avalonia.Data.BindingMode.TwoWay);
public string Text
{
get => GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
private readonly TextBlock _display;
private readonly TextBox _editor;
private bool _isEditing;
public EditableTextBlock()
{
_display = new TextBlock
{
VerticalAlignment = VerticalAlignment.Center,
TextTrimming = TextTrimming.CharacterEllipsis,
};
_editor = new TextBox
{
VerticalAlignment = VerticalAlignment.Center,
Padding = new Thickness(2, 0),
BorderThickness = new Thickness(1),
MinWidth = 40,
IsVisible = false,
};
LogicalChildren.Add(_display);
LogicalChildren.Add(_editor);
VisualChildren.Add(_display);
VisualChildren.Add(_editor);
_display.Bind(TextBlock.TextProperty, this.GetObservable(TextProperty).ToBinding());
_editor.Bind(TextBox.TextProperty, this.GetObservable(TextProperty).ToBinding());
_editor.KeyDown += OnEditorKeyDown;
_editor.LostFocus += OnEditorLostFocus;
}
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
if (e.ClickCount == 2 && !_isEditing)
{
BeginEdit();
e.Handled = true;
}
}
private void BeginEdit()
{
_isEditing = true;
_editor.Text = Text;
_display.IsVisible = false;
_editor.IsVisible = true;
_editor.Focus();
_editor.SelectAll();
}
private void CommitEdit()
{
if (!_isEditing) return;
_isEditing = false;
Text = _editor.Text ?? string.Empty;
_editor.IsVisible = false;
_display.IsVisible = true;
}
private void CancelEdit()
{
if (!_isEditing) return;
_isEditing = false;
_editor.Text = Text;
_editor.IsVisible = false;
_display.IsVisible = true;
}
private void OnEditorKeyDown(object? sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
CommitEdit();
e.Handled = true;
}
else if (e.Key == Key.Escape)
{
CancelEdit();
e.Handled = true;
}
}
private void OnEditorLostFocus(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
CommitEdit();
}
protected override Size MeasureOverride(Size availableSize)
{
_display.Measure(availableSize);
_editor.Measure(availableSize);
return _isEditing ? _editor.DesiredSize : _display.DesiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
var rect = new Rect(finalSize);
_display.Arrange(rect);
_editor.Arrange(rect);
return finalSize;
}
}