feat: add closing feature.
This commit is contained in:
46
src/Ursa/Controls/TagInput/ClosableTag.cs
Normal file
46
src/Ursa/Controls/TagInput/ClosableTag.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user