feat: add separator support, fix various issues.

This commit is contained in:
rabbitism
2024-02-23 17:51:05 +08:00
parent 1ccb395ab0
commit 0965f9d1f8
9 changed files with 127 additions and 7 deletions

View File

@@ -9,17 +9,22 @@ namespace Ursa.Demo.Converters;
public class ToolBarItemTemplateSelector: IDataTemplate public class ToolBarItemTemplateSelector: IDataTemplate
{ {
public static ToolBarItemTemplateSelector Instance { get; } = new(); public static ToolBarItemTemplateSelector Instance { get; } = new();
public Control? Build(object? param) public Control? Build(object? param)
{ {
if (param is null) return null; if (param is null) return null;
if (param is ToolBarSeparatorViewModel sep)
{
return new ToolBarSeparator();
}
if (param is ToolBarButtonItemViewModel vm) if (param is ToolBarButtonItemViewModel vm)
{ {
return new Button() return new Button()
{ {
[!ContentControl.ContentProperty] = new Binding() { Path = "Content" }, [!ContentControl.ContentProperty] = new Binding() { Path = "Content" },
[!Button.CommandProperty] = new Binding() { Path = "Command" }, [!Button.CommandProperty] = new Binding() { Path = "Command" },
//[!ToolBar.OverflowModeProperty] = new Binding(){ Path = "OverflowMode" } [!ToolBar.OverflowModeProperty] = new Binding(){Path = nameof(ToolBarItemViewModel.OverflowMode)},
}; };
} }
if (param is ToolBarCheckBoxItemViweModel cb) if (param is ToolBarCheckBoxItemViweModel cb)
@@ -28,7 +33,7 @@ public class ToolBarItemTemplateSelector: IDataTemplate
{ {
[!ContentControl.ContentProperty] = new Binding() { Path = "Content" }, [!ContentControl.ContentProperty] = new Binding() { Path = "Content" },
[!ToggleButton.IsCheckedProperty] = new Binding() { Path = "IsChecked" }, [!ToggleButton.IsCheckedProperty] = new Binding() { Path = "IsChecked" },
//[!ToolBar.OverflowModeProperty] = new Binding(){ Path = "OverflowMode" } [!ToolBar.OverflowModeProperty] = new Binding(){Path = nameof(ToolBarItemViewModel.OverflowMode)},
}; };
} }
if (param is ToolBarComboBoxItemViewModel combo) if (param is ToolBarComboBoxItemViewModel combo)
@@ -38,7 +43,7 @@ public class ToolBarItemTemplateSelector: IDataTemplate
[!ContentControl.ContentProperty] = new Binding() { Path = "Content" }, [!ContentControl.ContentProperty] = new Binding() { Path = "Content" },
[!SelectingItemsControl.SelectedItemProperty] = new Binding() { Path = "SelectedItem" }, [!SelectingItemsControl.SelectedItemProperty] = new Binding() { Path = "SelectedItem" },
[!ItemsControl.ItemsSourceProperty] = new Binding() { Path = "Items" }, [!ItemsControl.ItemsSourceProperty] = new Binding() { Path = "Items" },
[ToolBar.OverflowModeProperty] = OverflowMode.Always, [!ToolBar.OverflowModeProperty] = new Binding(){Path = nameof(ToolBarItemViewModel.OverflowMode)},
}; };
} }
return new Button() { Content = "Undefined Item" }; return new Button() { Content = "Undefined Item" };

View File

@@ -18,8 +18,10 @@
DockPanel.Dock="Top" DockPanel.Dock="Top"
Header="Hello World"> Header="Hello World">
<Button Content="Button 1" u:ToolBar.OverflowMode="Never" /> <Button Content="Button 1" u:ToolBar.OverflowMode="Never" />
<u:ToolBarSeparator/>
<Button u:ToolBar.OverflowMode="AsNeeded" Content="Button 2" /> <Button u:ToolBar.OverflowMode="AsNeeded" Content="Button 2" />
<Button u:ToolBar.OverflowMode="AsNeeded" Content="Button 3" /> <Button u:ToolBar.OverflowMode="AsNeeded" Content="Button 3" />
<ToggleButton Content="Toggle"></ToggleButton>
</u:ToolBar> </u:ToolBar>
<u:ToolBar <u:ToolBar
HorizontalAlignment="Left" HorizontalAlignment="Left"

View File

@@ -17,11 +17,13 @@ public partial class ToolBarDemoViewModel: ObservableObject
new ToolBarButtonItemViewModel() { Content = "Open" }, new ToolBarButtonItemViewModel() { Content = "Open" },
new ToolBarButtonItemViewModel() { Content = "Save1" }, new ToolBarButtonItemViewModel() { Content = "Save1" },
new ToolBarButtonItemViewModel() { Content = "Save2" }, new ToolBarButtonItemViewModel() { Content = "Save2" },
new ToolBarSeparatorViewModel(),
new ToolBarButtonItemViewModel() { Content = "Save3" }, new ToolBarButtonItemViewModel() { Content = "Save3" },
new ToolBarButtonItemViewModel() { Content = "Save4" }, new ToolBarButtonItemViewModel() { Content = "Save4" },
new ToolBarButtonItemViewModel() { Content = "Save5" }, new ToolBarButtonItemViewModel() { Content = "Save5" },
new ToolBarButtonItemViewModel() { Content = "Save6" }, new ToolBarButtonItemViewModel() { Content = "Save6" },
new ToolBarButtonItemViewModel() { Content = "Save7" }, new ToolBarButtonItemViewModel() { Content = "Save7" },
new ToolBarSeparatorViewModel(),
new ToolBarButtonItemViewModel() { Content = "Save8" }, new ToolBarButtonItemViewModel() { Content = "Save8" },
new ToolBarCheckBoxItemViweModel() { Content = "Bold" }, new ToolBarCheckBoxItemViweModel() { Content = "Bold" },
new ToolBarCheckBoxItemViweModel() { Content = "Italic", OverflowMode = OverflowMode.Never}, new ToolBarCheckBoxItemViweModel() { Content = "Italic", OverflowMode = OverflowMode.Never},
@@ -73,7 +75,9 @@ public class ToolBarComboBoxItemViewModel: ToolBarItemViewModel
MessageBox.ShowOverlayAsync(value); MessageBox.ShowOverlayAsync(value);
} }
} }
}
public class ToolBarSeparatorViewModel: ToolBarItemViewModel
{
} }

View File

@@ -44,6 +44,7 @@
Margin="8,0" Margin="8,0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VerticalAlignment="Center" VerticalAlignment="Center"
Foreground="{DynamicResource SemiColorText2}"
Content="{TemplateBinding Header}" Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}" ContentTemplate="{TemplateBinding HeaderTemplate}"
DockPanel.Dock="Left" DockPanel.Dock="Left"
@@ -94,6 +95,7 @@
Margin="8,0" Margin="8,0"
HorizontalAlignment="Center" HorizontalAlignment="Center"
VerticalAlignment="Top" VerticalAlignment="Top"
Foreground="{DynamicResource SemiColorText2}"
Content="{TemplateBinding Header}" Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}" ContentTemplate="{TemplateBinding HeaderTemplate}"
DockPanel.Dock="Top" DockPanel.Dock="Top"
@@ -112,7 +114,7 @@
IsOpen="{Binding #button.IsChecked, Mode=TwoWay}" IsOpen="{Binding #button.IsChecked, Mode=TwoWay}"
Placement="{TemplateBinding PopupPlacement}" Placement="{TemplateBinding PopupPlacement}"
PlacementTarget="{Binding #button}"> PlacementTarget="{Binding #button}">
<Border Theme="{DynamicResource CardBorder}"> <Border Theme="{DynamicResource CardBorder}" Padding="2">
<StackPanel Name="{x:Static u:ToolBar.PART_OverflowPanel}" /> <StackPanel Name="{x:Static u:ToolBar.PART_OverflowPanel}" />
</Border> </Border>
</Popup> </Popup>
@@ -130,4 +132,23 @@
<Setter Property="IsVisible" Value="True"></Setter> <Setter Property="IsVisible" Value="True"></Setter>
</Style> </Style>
</ControlTheme> </ControlTheme>
<ControlTheme x:Key="{x:Type u:ToolBarSeparator}" TargetType="u:ToolBarSeparator">
<Setter Property="Template">
<ControlTemplate>
<Rectangle Name="PART_Rect" Margin="4 " Fill="{DynamicResource SemiColorBorder}"></Rectangle>
</ControlTemplate>
</Setter>
<Style Selector="^ /template/ Rectangle#PART_Rect">
<Setter Property="Width" Value="1"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
<Style Selector="^:vertical /template/ Rectangle#PART_Rect">
<Setter Property="Height" Value="1"></Setter>
<Setter Property="Width" Value="{x:Static x:Double.NaN}" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Center"></Setter>
</Style>
</ControlTheme>
</ResourceDictionary> </ResourceDictionary>

View File

@@ -0,0 +1,26 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:u="https://irihi.tech/ursa">
<Design.PreviewWith>
<Border Padding="20">
<!-- Add Controls for Previewer Here -->
</Border>
</Design.PreviewWith>
<Style Selector="u|ToolBar Button">
<Setter Property="Theme" Value="{DynamicResource BorderlessButton}"></Setter>
<Setter Property="FontWeight" Value="Regular" />
<Setter Property="Foreground" Value="{DynamicResource SemiColorText0}"></Setter>
</Style>
<Style Selector="u|ToolBar CheckBox">
<Setter Property="Margin" Value="8 0" />
</Style>
<Style Selector="u|ToolBar ToggleButton">
<Setter Property="FontWeight" Value="Regular" />
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{DynamicResource SemiColorText0}"/>
</Style>
<Style Selector="u|ToolBar ComboBox">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
</Style>
<!-- Add Styles Here -->
</Styles>

View File

@@ -5,5 +5,6 @@
</Border> </Border>
</Design.PreviewWith> </Design.PreviewWith>
<StyleInclude Source="ButtonGroup.axaml" /> <StyleInclude Source="ButtonGroup.axaml" />
<StyleInclude Source="ToolBar.axaml"/>
<!-- Add Styles Here --> <!-- Add Styles Here -->
</Styles> </Styles>

View File

@@ -86,7 +86,11 @@ public class ToolBar: HeaderedItemsControl
{ {
return c; return c;
} }
return ItemTemplate?.Build(item) ?? new ContentPresenter(); if(ItemTemplate is not null && ItemTemplate.Match(item))
{
return ItemTemplate.Build(item)?? new ContentPresenter();
}
return new ContentPresenter();
} }
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)

View File

@@ -116,8 +116,24 @@ public class ToolBarPanel: StackPanel
{ {
Children.Add(child); Children.Add(child);
} }
if (child is ToolBarSeparator s)
{
s.IsVisible = true;
}
} }
var thisLast = this.Children.LastOrDefault();
if (thisLast is ToolBarSeparator s2)
{
s2.IsVisible = false;
}
var thatFirst = OverflowPanel?.Children.FirstOrDefault();
if (thatFirst is ToolBarSeparator s3)
{
s3.IsVisible = false;
}
if (_parent != null) _parent.HasOverflowItems = overflow; if (_parent != null) _parent.HasOverflowItems = overflow;
return base.ArrangeOverride(finalSize); return base.ArrangeOverride(finalSize);
} }

View File

@@ -0,0 +1,41 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Irihi.Avalonia.Shared.Helpers;
namespace Ursa.Controls;
[PseudoClasses(PC_Vertical)]
public class ToolBarSeparator: TemplatedControl
{
public const string PC_Vertical = ":vertical";
public static readonly StyledProperty<Orientation> OrientationProperty =
ToolBar.OrientationProperty.AddOwner<ToolBarSeparator>();
public Orientation Orientation
{
get => GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}
static ToolBarSeparator()
{
OrientationProperty.OverrideDefaultValue<ToolBarSeparator>(Orientation.Horizontal);
OrientationProperty.Changed.AddClassHandler<ToolBarSeparator, Orientation>((separator, args) =>
{
separator.PseudoClasses.Set(PC_Vertical, args.NewValue.Value == Orientation.Vertical);
});
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
var ancestor = this.GetLogicalAncestors().OfType<ToolBar>().FirstOrDefault();
if (ancestor is null) return;
this[!OrientationProperty] = ancestor[!ToolBar.OrientationProperty];
}
}