feat: add closing feature.

This commit is contained in:
rabbitism
2023-06-29 02:25:31 +08:00
parent 9d249b01cd
commit 2d353ad9e0
5 changed files with 129 additions and 20 deletions

View File

@@ -0,0 +1,46 @@
using System.Windows.Input;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
namespace Ursa.Controls;
[TemplatePart(PART_CloseButton, typeof(PathIcon))]
public class ClosableTag: ContentControl
{
public const string PART_CloseButton = "PART_CloseButton";
private PathIcon? _icon;
public static readonly StyledProperty<ICommand?> CommandProperty = AvaloniaProperty.Register<ClosableTag, ICommand?>(
nameof(Command));
public ICommand? Command
{
get => GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
if (_icon != null)
{
_icon.PointerPressed -= OnPointerPressed;
}
_icon = e.NameScope.Find<PathIcon>(PART_CloseButton);
if (_icon != null)
{
_icon.PointerPressed += OnPointerPressed;
}
}
private void OnPointerPressed(object? sender, PointerPressedEventArgs args)
{
if (Command != null && Command.CanExecute(null))
{
Command.Execute(this);
}
}
}

View File

@@ -1,21 +1,29 @@
using System.Collections;
using System.Collections.ObjectModel;
using Avalonia;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Styling;
namespace Ursa.Controls;
[TemplatePart (PART_ItemsControl, typeof (ItemsControl))]
public class TagInput: TemplatedControl
{
public const string PART_ItemsControl = "PART_ItemsControl";
private readonly TextBox _textBox;
private ItemsControl? _itemsControl;
public static readonly StyledProperty<IList<string>> TagsProperty = AvaloniaProperty.Register<TagInput, IList<string>>(
nameof(Tags));
private TextBox _textBox;
public IList<string> Tags
{
get => GetValue(TagsProperty);
@@ -24,7 +32,6 @@ public class TagInput: TemplatedControl
public static readonly StyledProperty<IList> ItemsProperty = AvaloniaProperty.Register<TagInput, IList>(
nameof(Items));
public IList Items
{
get => GetValue(ItemsProperty);
@@ -34,6 +41,9 @@ public class TagInput: TemplatedControl
public TagInput()
{
_textBox = new TextBox();
_textBox.KeyDown += OnTextBoxKeyDown;
Items = new AvaloniaList<object>();
Tags = new ObservableCollection<string>();
}
public static readonly StyledProperty<ControlTheme> InputThemeProperty = AvaloniaProperty.Register<TagInput, ControlTheme>(
@@ -57,20 +67,42 @@ public class TagInput: TemplatedControl
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
Items = new AvaloniaList<object>();
_itemsControl = e.NameScope.Find<ItemsControl>(PART_ItemsControl);
if (IsSet(InputThemeProperty) && InputTheme.TargetType == typeof(TextBox))
{
_textBox.Theme = InputTheme;
}
_textBox.KeyDown += (sender, args) =>
{
if (args.Key == Avalonia.Input.Key.Enter)
{
Items.Insert(Items.Count - 1, _textBox.Text);
// Tags.Insert(Items.Count - 1, _textBox.Text ?? string.Empty);
_textBox.Text = "";
}
};
Items.Add(_textBox);
}
private void OnTextBoxKeyDown(object? sender, KeyEventArgs args)
{
if (args.Key == Avalonia.Input.Key.Enter)
{
if (_textBox.Text?.Length > 0)
{
Items.Insert(Items.Count - 1, _textBox.Text);
Tags.Insert(Items.Count - 2, _textBox.Text ?? string.Empty);
_textBox.Text = "";
}
}
}
public void Close(object o)
{
if (o is ClosableTag t)
{
var presenter = t.Parent as ContentPresenter;
if (presenter != null)
{
int? index = _itemsControl?.IndexFromContainer(presenter);
if (index is >= 0 && index < Items.Count - 1)
{
Items.RemoveAt(index.Value);
Tags.RemoveAt(index.Value);
}
}
}
}
}

View File

@@ -82,7 +82,7 @@ public class TagInputPanel: Panel
else
{
totalHeight += currentLineHeight;
child.Arrange(new Rect(0, totalHeight, finalSize.Width, child.DesiredSize.Height));
child.Arrange(new Rect(0, totalHeight, Math.Min(child.DesiredSize.Width, finalSize.Width), child.DesiredSize.Height));
currentLineX = child.DesiredSize.Width;
currentLineHeight = child.DesiredSize.Height;
}