diff --git a/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs b/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs
index f48b834..76e669b 100644
--- a/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs
+++ b/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs
@@ -28,7 +28,6 @@ public class ToolBarItemTemplateSelector: IDataTemplate
{
[!ContentControl.ContentProperty] = new Binding() { Path = "Content" },
[!ToggleButton.IsCheckedProperty] = new Binding() { Path = "IsChecked" },
- [!Button.CommandProperty] = new Binding() { Path = "Command" },
[!ToolBar.OverflowModeProperty] = new Binding(){ Path = "OverflowMode" }
};
}
@@ -39,7 +38,7 @@ public class ToolBarItemTemplateSelector: IDataTemplate
[!ContentControl.ContentProperty] = new Binding() { Path = "Content" },
[!SelectingItemsControl.SelectedItemProperty] = new Binding() { Path = "SelectedItem" },
[!ItemsControl.ItemsSourceProperty] = new Binding() { Path = "Items" },
- [!ToolBar.OverflowModeProperty] = new Binding(){ Path = "OverflowMode" }
+ [ToolBar.OverflowModeProperty] = OverflowMode.Always,
};
}
return new Button() { Content = "Undefined Item" };
diff --git a/demo/Ursa.Demo/Pages/ToolBarDemo.axaml b/demo/Ursa.Demo/Pages/ToolBarDemo.axaml
index 61af50f..743ae82 100644
--- a/demo/Ursa.Demo/Pages/ToolBarDemo.axaml
+++ b/demo/Ursa.Demo/Pages/ToolBarDemo.axaml
@@ -10,15 +10,16 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Ursa.Demo.Pages.ToolBarDemo">
-
+
-
+
-
+
+
diff --git a/demo/Ursa.Demo/Views/MainWindow.axaml.cs b/demo/Ursa.Demo/Views/MainWindow.axaml.cs
index 45aa4b8..73e4f8a 100644
--- a/demo/Ursa.Demo/Views/MainWindow.axaml.cs
+++ b/demo/Ursa.Demo/Views/MainWindow.axaml.cs
@@ -1,4 +1,5 @@
using Avalonia.Controls;
+using Avalonia.Interactivity;
namespace Ursa.Demo.Views;
diff --git a/src/Ursa.Themes.Semi/Controls/ToolBar.axaml b/src/Ursa.Themes.Semi/Controls/ToolBar.axaml
index ab349f5..bafdee8 100644
--- a/src/Ursa.Themes.Semi/Controls/ToolBar.axaml
+++ b/src/Ursa.Themes.Semi/Controls/ToolBar.axaml
@@ -6,30 +6,43 @@
-
+
-
+ CornerRadius="4"
+ Theme="{DynamicResource CardBorder}">
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Ursa/Controls/ToolBar/ToolBar.cs b/src/Ursa/Controls/ToolBar/ToolBar.cs
index eefc2bb..f09437d 100644
--- a/src/Ursa/Controls/ToolBar/ToolBar.cs
+++ b/src/Ursa/Controls/ToolBar/ToolBar.cs
@@ -5,6 +5,7 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Layout;
+using Avalonia.Markup.Xaml.Templates;
namespace Ursa.Controls;
@@ -59,6 +60,27 @@ public class ToolBar: HeaderedItemsControl
return new ContentPresenter();
}
+ protected override void ContainerForItemPreparedOverride(Control container, object? item, int index)
+ {
+ base.ContainerForItemPreparedOverride(container, item, index);
+ if (item is Control s)
+ {
+ container[!ToolBar.OverflowModeProperty] = s[!ToolBar.OverflowModeProperty];
+ }
+ else
+ {
+ if (container is ContentPresenter p)
+ {
+ p.ApplyTemplate();
+ var c = p.Child;
+ if (c != null)
+ {
+ container[!ToolBar.OverflowModeProperty] = c[!ToolBar.OverflowModeProperty];
+ }
+ }
+ }
+ }
+
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
diff --git a/src/Ursa/Controls/ToolBar/ToolBarPanel.cs b/src/Ursa/Controls/ToolBar/ToolBarPanel.cs
index c71558e..0fd6235 100644
--- a/src/Ursa/Controls/ToolBar/ToolBarPanel.cs
+++ b/src/Ursa/Controls/ToolBar/ToolBarPanel.cs
@@ -2,6 +2,7 @@
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.LogicalTree;
+using Avalonia.VisualTree;
namespace Ursa.Controls;
@@ -13,6 +14,15 @@ public class ToolBarPanel: StackPanel
internal Panel? OverflowPanel => _overflowPanel ??= _parent?.OverflowPanel;
internal ToolBar? ParentToolBar => _parent ??= this.TemplatedParent as ToolBar;
+ public static readonly StyledProperty OrientationProperty =
+ StackPanel.OrientationProperty.AddOwner();
+
+ public Orientation Orientation
+ {
+ get => GetValue(OrientationProperty);
+ set => SetValue(OrientationProperty, value);
+ }
+
static ToolBarPanel()
{
OrientationProperty.OverrideDefaultValue(Orientation.Horizontal);
@@ -25,27 +35,113 @@ public class ToolBarPanel: StackPanel
if (_parent is null) return;
this[!OrientationProperty] = _parent[!OrientationProperty];
}
-
+
protected override Size MeasureOverride(Size availableSize)
{
- var size = base.MeasureOverride(availableSize);
- var children = this.Children;
- var children2 = this.OverflowPanel?.Children;
- var all = children.ToList();
- if (children2 != null)
+ var logicalChildren = _parent?.GetLogicalChildren().OfType().ToList();
+ var parent = this.GetLogicalParent();
+ Size size = new Size();
+ double spacing = 0;
+ Size measureSize = availableSize;
+ bool horizontal = Orientation == Orientation.Horizontal;
+ bool hasVisibleChildren = false;
+ measureSize = horizontal
+ ? measureSize.WithWidth(double.PositiveInfinity)
+ : measureSize.WithHeight(double.PositiveInfinity);
+ int index = 0;
+ if (logicalChildren is null) return size;
+ for (int count = logicalChildren.Count; index < count; ++index)
{
- all.AddRange(children2);
+ Control control = logicalChildren[index];
+ var mode = ToolBar.GetOverflowMode(control);
+ if(mode == OverflowMode.Always) continue;
+ bool isVisible = control.IsVisible;
+ if (isVisible)
+ {
+ hasVisibleChildren = true;
+ }
+ control.Measure(measureSize);
+ Size desiredSize = control.DesiredSize;
+ if (horizontal)
+ {
+ size = size.WithWidth(size.Width + desiredSize.Width + (isVisible ? spacing : 0));
+ size = size.WithHeight(Math.Max(size.Height, desiredSize.Height));
+ }
+ else
+ {
+ size = size.WithHeight(size.Height + desiredSize.Height + (isVisible ? spacing : 0));
+ size = size.WithWidth(Math.Max(size.Width, desiredSize.Width));
+ }
}
- this.Children.Clear();
- OverflowPanel?.Children.Clear();
- for (int i = 0; i < all.Count - 1; i++)
+
+ if (hasVisibleChildren)
{
- this.Children.Add(all[i]);
- }
- if (all.Count > 0)
- {
- OverflowPanel?.Children.Add(all.Last());
+ size = horizontal ? size.WithWidth(size.Width - spacing) : size.WithHeight(size.Height - spacing);
}
return size;
}
+
+ protected override Size ArrangeOverride(Size finalSize)
+ {
+ if (_parent is null)
+ {
+ return finalSize;
+ }
+ var all = _parent.GetLogicalChildren().OfType().ToList();
+ Children.Clear();
+ OverflowPanel?.Children.Clear();
+ Size currentSize = new Size();
+ bool horizontal = Orientation == Orientation.Horizontal;
+ double spacing = 0;
+ Rect arrangeRect = new Rect(finalSize);
+ double previousChildSize = 0.0;
+ for (var i = 0; i < all.Count; i++)
+ {
+ var control = all[i];
+ if (!control.IsVisible) continue;
+ var desiredSize = control.DesiredSize;
+ var mode = ToolBar.GetOverflowMode(control);
+ if (mode == OverflowMode.Always)
+ {
+ OverflowPanel?.Children.Add(control);
+ }
+ else
+ {
+ Children.Add(control);
+ if (horizontal)
+ {
+ arrangeRect = arrangeRect.WithX(arrangeRect.X + previousChildSize);
+ previousChildSize = control.DesiredSize.Width;
+ arrangeRect = arrangeRect.WithWidth(previousChildSize);
+ arrangeRect = arrangeRect.WithHeight(Math.Max(finalSize.Height, control.DesiredSize.Height));
+ previousChildSize += spacing;
+ currentSize = currentSize.WithWidth(currentSize.Width + desiredSize.Width + spacing);
+ currentSize = currentSize.WithHeight(Math.Max(currentSize.Height, desiredSize.Height));
+ }
+ else
+ {
+ arrangeRect = arrangeRect.WithY(arrangeRect.Y + previousChildSize);
+ previousChildSize = control.DesiredSize.Height;
+ arrangeRect = arrangeRect.WithHeight(previousChildSize);
+ arrangeRect = arrangeRect.WithWidth(Math.Max(finalSize.Width, control.DesiredSize.Width));
+ previousChildSize += spacing;
+ currentSize = currentSize.WithHeight(currentSize.Height + desiredSize.Height + spacing);
+ currentSize = currentSize.WithWidth(Math.Max(currentSize.Width, desiredSize.Width));
+ }
+ control.Arrange(arrangeRect);
+ }
+ }
+ return currentSize;
+ }
+
+ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ var list = OverflowPanel?.Children?.ToList();
+ if (list is not null)
+ {
+ OverflowPanel?.Children?.Clear();
+ this.Children.AddRange(list);
+ }
+ base.OnDetachedFromVisualTree(e);
+ }
}
\ No newline at end of file