diff --git a/demo/Ursa.Demo/Converters/MenuDataTemplateSelector.cs b/demo/Ursa.Demo/DataTemplates/MenuDataTemplateSelector.cs similarity index 100% rename from demo/Ursa.Demo/Converters/MenuDataTemplateSelector.cs rename to demo/Ursa.Demo/DataTemplates/MenuDataTemplateSelector.cs diff --git a/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs b/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs new file mode 100644 index 0000000..9caceef --- /dev/null +++ b/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs @@ -0,0 +1,48 @@ +using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Controls.Templates; +using Avalonia.Data; +using Ursa.Demo.ViewModels; + +namespace Ursa.Demo.Converters; + +public class ToolBarItemTemplateSelector: IDataTemplate +{ + public static ToolBarItemTemplateSelector Instance { get; } = new(); + public Control? Build(object? param) + { + if (param is null) return null; + if (param is ToolBarButtonItemViewModel vm) + { + return new Button() + { + [!ContentControl.ContentProperty] = new Binding() { Path = "Content" }, + [!Button.CommandProperty] = new Binding() { Path = "Command" }, + }; + } + if (param is ToolBarCheckBoxItemViweModel cb) + { + return new CheckBox() + { + [!ContentControl.ContentProperty] = new Binding() { Path = "Content" }, + [!ToggleButton.IsCheckedProperty] = new Binding() { Path = "IsChecked" }, + [!Button.CommandProperty] = new Binding() { Path = "Command" }, + }; + } + if (param is ToolBarComboBoxItemViewModel combo) + { + return new ComboBox() + { + [!ContentControl.ContentProperty] = new Binding() { Path = "Content" }, + [!SelectingItemsControl.SelectedItemProperty] = new Binding() { Path = "SelectedItem" }, + [!ItemsControl.ItemsSourceProperty] = new Binding() { Path = "Items" }, + }; + } + return new Button() { Content = "Undefined Item" }; + } + + public bool Match(object? data) + { + return data is ToolBarItemViewModel; + } +} \ No newline at end of file diff --git a/demo/Ursa.Demo/Converters/ViewLocator.cs b/demo/Ursa.Demo/DataTemplates/ViewLocator.cs similarity index 100% rename from demo/Ursa.Demo/Converters/ViewLocator.cs rename to demo/Ursa.Demo/DataTemplates/ViewLocator.cs diff --git a/demo/Ursa.Demo/Models/MenuKeys.cs b/demo/Ursa.Demo/Models/MenuKeys.cs index 4c707a6..1351630 100644 --- a/demo/Ursa.Demo/Models/MenuKeys.cs +++ b/demo/Ursa.Demo/Models/MenuKeys.cs @@ -31,5 +31,6 @@ public static class MenuKeys public const string MenuKeyTimeline = "Timeline"; public const string MenuKeyTwoTonePathIcon = "TwoTonePathIcon"; public const string MenuKeyThemeToggler = "ThemeToggler"; + public const string MenuKeyToolBar = "ToolBar"; } \ No newline at end of file diff --git a/demo/Ursa.Demo/Pages/ToolBarDemo.axaml b/demo/Ursa.Demo/Pages/ToolBarDemo.axaml new file mode 100644 index 0000000..61af50f --- /dev/null +++ b/demo/Ursa.Demo/Pages/ToolBarDemo.axaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + diff --git a/src/Ursa.Themes.Semi/Controls/_index.axaml b/src/Ursa.Themes.Semi/Controls/_index.axaml index 848b1b9..fdbbda4 100644 --- a/src/Ursa.Themes.Semi/Controls/_index.axaml +++ b/src/Ursa.Themes.Semi/Controls/_index.axaml @@ -30,5 +30,6 @@ + diff --git a/src/Ursa/Controls/ToolBar/OverflowMode.cs b/src/Ursa/Controls/ToolBar/OverflowMode.cs new file mode 100644 index 0000000..975c7e5 --- /dev/null +++ b/src/Ursa/Controls/ToolBar/OverflowMode.cs @@ -0,0 +1,8 @@ +namespace Ursa.Controls; + +public enum OverflowMode +{ + AsNeeded, + Always, + Never +} \ No newline at end of file diff --git a/src/Ursa/Controls/ToolBar/ToolBar.cs b/src/Ursa/Controls/ToolBar/ToolBar.cs new file mode 100644 index 0000000..0582c65 --- /dev/null +++ b/src/Ursa/Controls/ToolBar/ToolBar.cs @@ -0,0 +1,61 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Metadata; +using Avalonia.Controls.Presenters; +using Avalonia.Controls.Primitives; +using Avalonia.Controls.Templates; +using Avalonia.Layout; + +namespace Ursa.Controls; + +[TemplatePart(PART_OverflowPanel, typeof(Panel))] +public class ToolBar: HeaderedItemsControl +{ + public const string PART_OverflowPanel = "PART_OverflowPanel"; + + internal Panel? OverflowPanel { get; private set; } + + private static readonly ITemplate DefaultTemplate = + new FuncTemplate(() => new ToolBarPanel() { Orientation = Orientation.Horizontal }); + + public static readonly StyledProperty OrientationProperty = + StackPanel.OrientationProperty.AddOwner(); + + public Orientation Orientation + { + get => GetValue(OrientationProperty); + set => SetValue(OrientationProperty, value); + } + + public static readonly StyledProperty BandProperty = AvaloniaProperty.Register( + nameof(Band)); + + public int Band + { + get => GetValue(BandProperty); + set => SetValue(BandProperty, value); + } + + static ToolBar() + { + IsTabStopProperty.OverrideDefaultValue(false); + ItemsPanelProperty.OverrideDefaultValue(DefaultTemplate); + OrientationProperty.OverrideDefaultValue(Orientation.Horizontal); + } + + protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey) + { + return NeedsContainer(item, out recycleKey); + } + + protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey) + { + return new ContentPresenter(); + } + + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + OverflowPanel = e.NameScope.Find(PART_OverflowPanel); + } +} \ No newline at end of file diff --git a/src/Ursa/Controls/ToolBar/ToolBarOverflowPanel.cs b/src/Ursa/Controls/ToolBar/ToolBarOverflowPanel.cs new file mode 100644 index 0000000..be52346 --- /dev/null +++ b/src/Ursa/Controls/ToolBar/ToolBarOverflowPanel.cs @@ -0,0 +1,8 @@ +using Avalonia.Controls; + +namespace Ursa.Controls; + +public class ToolBarOverflowPanel: StackPanel +{ + +} \ No newline at end of file diff --git a/src/Ursa/Controls/ToolBar/ToolBarPanel.cs b/src/Ursa/Controls/ToolBar/ToolBarPanel.cs new file mode 100644 index 0000000..288d0e4 --- /dev/null +++ b/src/Ursa/Controls/ToolBar/ToolBarPanel.cs @@ -0,0 +1,34 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Layout; +using Avalonia.LogicalTree; + +namespace Ursa.Controls; + +public class ToolBarPanel: StackPanel +{ + private ToolBar? _parent; + private Panel? _overflowPanel; + + internal Panel? OverflowPanel => _overflowPanel ??= _parent?.OverflowPanel; + internal ToolBar? ParentToolBar => _parent ??= this.TemplatedParent as ToolBar; + + static ToolBarPanel() + { + OrientationProperty.OverrideDefaultValue(Orientation.Horizontal); + } + + protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e) + { + base.OnAttachedToLogicalTree(e); + _parent = this.TemplatedParent as ToolBar; + if (_parent is null) return; + this[!OrientationProperty] = _parent[!OrientationProperty]; + } + + protected override Size MeasureOverride(Size availableSize) + { + return base.MeasureOverride(availableSize); + + } +} \ No newline at end of file diff --git a/src/Ursa/Ursa.csproj b/src/Ursa/Ursa.csproj index ec98fe6..2bd6329 100644 --- a/src/Ursa/Ursa.csproj +++ b/src/Ursa/Ursa.csproj @@ -17,4 +17,8 @@ + + + +