From 2d353ad9e068b687a5138c1c643bf4fe457eebcc Mon Sep 17 00:00:00 2001 From: rabbitism Date: Thu, 29 Jun 2023 02:25:31 +0800 Subject: [PATCH] feat: add closing feature. --- demo/Ursa.Demo/Pages/TagInputDemo.axaml | 5 +- src/Ursa.Themes.Semi/Controls/TagInput.axaml | 36 ++++++++++-- src/Ursa/Controls/TagInput/ClosableTag.cs | 46 +++++++++++++++ src/Ursa/Controls/TagInput/TagInput.cs | 60 +++++++++++++++----- src/Ursa/Controls/TagInput/TagInputPanel.cs | 2 +- 5 files changed, 129 insertions(+), 20 deletions(-) create mode 100644 src/Ursa/Controls/TagInput/ClosableTag.cs diff --git a/demo/Ursa.Demo/Pages/TagInputDemo.axaml b/demo/Ursa.Demo/Pages/TagInputDemo.axaml index 4cc5c4a..d73fcb3 100644 --- a/demo/Ursa.Demo/Pages/TagInputDemo.axaml +++ b/demo/Ursa.Demo/Pages/TagInputDemo.axaml @@ -8,5 +8,8 @@ d:DesignHeight="450" d:DesignWidth="800" mc:Ignorable="d"> - + + + + diff --git a/src/Ursa.Themes.Semi/Controls/TagInput.axaml b/src/Ursa.Themes.Semi/Controls/TagInput.axaml index 9539c85..4443f32 100644 --- a/src/Ursa.Themes.Semi/Controls/TagInput.axaml +++ b/src/Ursa.Themes.Semi/Controls/TagInput.axaml @@ -9,10 +9,7 @@ - @@ -24,6 +21,7 @@ CornerRadius="3"> + + + + + + + + + + + + + + + diff --git a/src/Ursa/Controls/TagInput/ClosableTag.cs b/src/Ursa/Controls/TagInput/ClosableTag.cs new file mode 100644 index 0000000..de609f2 --- /dev/null +++ b/src/Ursa/Controls/TagInput/ClosableTag.cs @@ -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 CommandProperty = AvaloniaProperty.Register( + 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(PART_CloseButton); + if (_icon != null) + { + _icon.PointerPressed += OnPointerPressed; + } + + } + + private void OnPointerPressed(object? sender, PointerPressedEventArgs args) + { + if (Command != null && Command.CanExecute(null)) + { + Command.Execute(this); + } + } +} \ No newline at end of file diff --git a/src/Ursa/Controls/TagInput/TagInput.cs b/src/Ursa/Controls/TagInput/TagInput.cs index 21bde20..c2115ee 100644 --- a/src/Ursa/Controls/TagInput/TagInput.cs +++ b/src/Ursa/Controls/TagInput/TagInput.cs @@ -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> TagsProperty = AvaloniaProperty.Register>( nameof(Tags)); - - private TextBox _textBox; - public IList Tags { get => GetValue(TagsProperty); @@ -24,7 +32,6 @@ public class TagInput: TemplatedControl public static readonly StyledProperty ItemsProperty = AvaloniaProperty.Register( 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(); + Tags = new ObservableCollection(); } public static readonly StyledProperty InputThemeProperty = AvaloniaProperty.Register( @@ -57,20 +67,42 @@ public class TagInput: TemplatedControl protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); - Items = new AvaloniaList(); + _itemsControl = e.NameScope.Find(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); + } + } + } + } } \ No newline at end of file diff --git a/src/Ursa/Controls/TagInput/TagInputPanel.cs b/src/Ursa/Controls/TagInput/TagInputPanel.cs index afd19f4..9efd6d4 100644 --- a/src/Ursa/Controls/TagInput/TagInputPanel.cs +++ b/src/Ursa/Controls/TagInput/TagInputPanel.cs @@ -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; }