Merge pull request #119 from irihitech/issue/116
feat: update dependency, simplify code, remove navigation control.
This commit is contained in:
@@ -20,7 +20,6 @@ public static class MenuKeys
|
||||
public const string MenuKeyKeyGestureInput = "KeyGestureInput";
|
||||
public const string MenuKeyLoading = "Loading";
|
||||
public const string MenuKeyMessageBox = "MessageBox";
|
||||
public const string MenuKeyNavigation = "Navigation";
|
||||
public const string MenuKeyNavMenu = "NavMenu";
|
||||
public const string MenuKeyNumberDisplayer = "NumberDisplayer";
|
||||
public const string MenuKeyNumericUpDown = "NumericUpDown";
|
||||
|
||||
@@ -43,51 +43,6 @@
|
||||
Content="Aesthetic revolution of productivity. "
|
||||
Header="Welcome to IRIHI Technology!"
|
||||
Type="Information" />
|
||||
<u:NavigationMenu Grid.Column="0" Grid.Row="1" ItemsSource="{Binding MenuItems}">
|
||||
<u:NavigationMenu.Resources>
|
||||
<converters:IconNameConverter x:Key="IconNameConverter">
|
||||
<PathGeometry x:Key="User">M12 16C13.9818 16 15.7453 14.3394 16.7142 11.8589C17.3163 11.6122 17.8892 10.8644 18.1508 9.88823C18.4909 8.61881 18.4234 7.48536 17.4964 7.13266C17.4064 2.7111 15.6617 1 12 1C8.33858 1 6.59387 2.71088 6.50372 7.13179C5.57454 7.48354 5.50668 8.61777 5.84709 9.8882C6.10904 10.8658 6.68318 11.6143 7.28626 11.8599C8.2552 14.3398 10.0186 16 12 16Z M19.6049 22C20.8385 22 21.7171 20.8487 20.867 19.9547C19.1971 18.1985 15.853 17 12 17C8.14699 17 4.80292 18.1985 3.133 19.9547C2.2829 20.8487 3.16148 22 4.39513 22H19.6049Z</PathGeometry>
|
||||
<PathGeometry x:Key="Star">M10.7525 1.90411C11.1451 0.698628 12.8549 0.698631 13.2475 1.90411L15.2395 8.01946H21.6858C22.9565 8.01946 23.4848 9.64143 22.4568 10.3865L17.2417 14.1659L19.2337 20.2813C19.6263 21.4868 18.2431 22.4892 17.2151 21.7442L12 17.9647L6.78489 21.7442C5.75687 22.4892 4.37368 21.4868 4.76635 20.2813L6.75834 14.1659L1.54323 10.3865C0.515206 9.64142 1.04354 8.01946 2.31425 8.01946H8.76048L10.7525 1.90411Z</PathGeometry>
|
||||
<PathGeometry x:Key="Gear">M7.99973 5.07197C7.19713 5.53535 6.20729 5.53113 5.40866 5.06092L5.1637 4.91669C4.55751 4.55978 3.77662 4.65563 3.34264 5.20927C2.69567 6.03462 2.17585 6.94251 1.79166 7.90124C1.53027 8.55354 1.83733 9.27693 2.449 9.62286L2.69407 9.76145C3.50107 10.2178 4.00002 11.0732 4.00002 12.0003C4.00002 12.9271 3.50145 13.7822 2.69492 14.2387L2.44842 14.3783C1.83596 14.725 1.52888 15.4497 1.79213 16.1024C1.98358 16.577 2.21048 17.044 2.47374 17.5C2.73723 17.9564 3.0285 18.3868 3.34416 18.7902C3.77773 19.3443 4.5588 19.4406 5.16498 19.0834L5.40839 18.9399C6.20714 18.4692 7.19739 18.4648 8.0003 18.9284C8.80291 19.3918 9.29417 20.2511 9.28627 21.1778L9.28386 21.4601C9.27787 22.1629 9.75107 22.7906 10.4468 22.8903C11.4692 23.0368 12.5154 23.0404 13.5537 22.8927C14.2499 22.7936 14.7231 22.1653 14.7169 21.462L14.7143 21.1785C14.7061 20.2514 15.1974 19.3916 16.0003 18.928C16.8029 18.4647 17.7927 18.4689 18.5914 18.9391L18.8363 19.0833C19.4425 19.4402 20.2234 19.3444 20.6574 18.7907C21.3044 17.9654 21.8242 17.0575 22.2084 16.0988C22.4698 15.4465 22.1627 14.7231 21.551 14.3772L21.306 14.2386C20.499 13.7822 20 12.9268 20 11.9997C20 11.0729 20.4986 10.2178 21.3051 9.76126L21.5516 9.62174C22.1641 9.27506 22.4712 8.55029 22.2079 7.89761C22.0165 7.42297 21.7896 6.95598 21.5263 6.50001C21.2628 6.04362 20.9715 5.61325 20.6559 5.20982C20.2223 4.65568 19.4412 4.55944 18.8351 4.91665L18.5916 5.06009C17.7929 5.53078 16.8026 5.53519 15.9997 5.07163C15.1971 4.60825 14.7059 3.74891 14.7138 2.82218L14.7162 2.53994C14.7222 1.83708 14.249 1.20945 13.5532 1.10973C12.5308 0.963214 11.4846 0.959581 10.4464 1.10733C9.75011 1.20641 9.27691 1.83473 9.28317 2.53798L9.28569 2.82154C9.29395 3.74862 8.80264 4.60841 7.99973 5.07197ZM14 15.4641C15.9132 14.3595 16.5687 11.9132 15.4641 9.99999C14.3595 8.08682 11.9132 7.43132 10 8.53589C8.08684 9.64046 7.43134 12.0868 8.53591 14C9.64048 15.9132 12.0868 16.5687 14 15.4641Z</PathGeometry>
|
||||
</converters:IconNameConverter>
|
||||
</u:NavigationMenu.Resources>
|
||||
<u:NavigationMenu.Header>
|
||||
<TextBlock
|
||||
Classes="H5"
|
||||
Text="Ursa"
|
||||
Theme="{DynamicResource TitleTextBlock}" />
|
||||
</u:NavigationMenu.Header>
|
||||
<u:NavigationMenu.Icon>
|
||||
<Image
|
||||
Width="48"
|
||||
Height="48"
|
||||
RenderOptions.BitmapInterpolationMode="HighQuality"
|
||||
Source="../Assets/Ursa.ico" />
|
||||
</u:NavigationMenu.Icon>
|
||||
<u:NavigationMenu.ItemTemplate>
|
||||
<converters:MenuDataTemplateSelector>
|
||||
<converters:MenuDataTemplateSelector.MenuTemplate>
|
||||
<DataTemplate DataType="vm:MenuItemViewModel">
|
||||
<u:NavigationMenuItem Header="{Binding MenuHeader}"
|
||||
ItemsSource="{Binding Children}">
|
||||
<u:NavigationMenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{Binding MenuIconName, Converter={StaticResource IconNameConverter}}" />
|
||||
</u:NavigationMenuItem.Icon>
|
||||
</u:NavigationMenuItem>
|
||||
</DataTemplate>
|
||||
</converters:MenuDataTemplateSelector.MenuTemplate>
|
||||
<converters:MenuDataTemplateSelector.SeparatorTemplate>
|
||||
<DataTemplate DataType="vm:MenuItemViewModel">
|
||||
<u:NavigationMenuSeparator Header="{Binding MenuHeader}" />
|
||||
</DataTemplate>
|
||||
</converters:MenuDataTemplateSelector.SeparatorTemplate>
|
||||
</converters:MenuDataTemplateSelector>
|
||||
</u:NavigationMenu.ItemTemplate>
|
||||
</u:NavigationMenu>
|
||||
|
||||
<StackPanel Grid.Column="1" Grid.Row="1" Spacing="20" Margin="8">
|
||||
<u:ImageViewer
|
||||
Name="viewer"
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
<UserControl
|
||||
x:Class="Ursa.Demo.Pages.NavigationMenuDemo"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Ursa.Demo.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:u="https://irihi.tech/ursa"
|
||||
xmlns:vm="clr-namespace:Ursa.Demo.ViewModels"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
x:CompileBindings="True"
|
||||
x:DataType="vm:NavigationMenuDemoViewModel"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<converters:IconNameConverter x:Key="IconNameConverter">
|
||||
<PathGeometry x:Key="User">M12 16C13.9818 16 15.7453 14.3394 16.7142 11.8589C17.3163 11.6122 17.8892 10.8644 18.1508 9.88823C18.4909 8.61881 18.4234 7.48536 17.4964 7.13266C17.4064 2.7111 15.6617 1 12 1C8.33858 1 6.59387 2.71088 6.50372 7.13179C5.57454 7.48354 5.50668 8.61777 5.84709 9.8882C6.10904 10.8658 6.68318 11.6143 7.28626 11.8599C8.2552 14.3398 10.0186 16 12 16Z M19.6049 22C20.8385 22 21.7171 20.8487 20.867 19.9547C19.1971 18.1985 15.853 17 12 17C8.14699 17 4.80292 18.1985 3.133 19.9547C2.2829 20.8487 3.16148 22 4.39513 22H19.6049Z</PathGeometry>
|
||||
<PathGeometry x:Key="Star">M10.7525 1.90411C11.1451 0.698628 12.8549 0.698631 13.2475 1.90411L15.2395 8.01946H21.6858C22.9565 8.01946 23.4848 9.64143 22.4568 10.3865L17.2417 14.1659L19.2337 20.2813C19.6263 21.4868 18.2431 22.4892 17.2151 21.7442L12 17.9647L6.78489 21.7442C5.75687 22.4892 4.37368 21.4868 4.76635 20.2813L6.75834 14.1659L1.54323 10.3865C0.515206 9.64142 1.04354 8.01946 2.31425 8.01946H8.76048L10.7525 1.90411Z</PathGeometry>
|
||||
<PathGeometry x:Key="Gear">M7.99973 5.07197C7.19713 5.53535 6.20729 5.53113 5.40866 5.06092L5.1637 4.91669C4.55751 4.55978 3.77662 4.65563 3.34264 5.20927C2.69567 6.03462 2.17585 6.94251 1.79166 7.90124C1.53027 8.55354 1.83733 9.27693 2.449 9.62286L2.69407 9.76145C3.50107 10.2178 4.00002 11.0732 4.00002 12.0003C4.00002 12.9271 3.50145 13.7822 2.69492 14.2387L2.44842 14.3783C1.83596 14.725 1.52888 15.4497 1.79213 16.1024C1.98358 16.577 2.21048 17.044 2.47374 17.5C2.73723 17.9564 3.0285 18.3868 3.34416 18.7902C3.77773 19.3443 4.5588 19.4406 5.16498 19.0834L5.40839 18.9399C6.20714 18.4692 7.19739 18.4648 8.0003 18.9284C8.80291 19.3918 9.29417 20.2511 9.28627 21.1778L9.28386 21.4601C9.27787 22.1629 9.75107 22.7906 10.4468 22.8903C11.4692 23.0368 12.5154 23.0404 13.5537 22.8927C14.2499 22.7936 14.7231 22.1653 14.7169 21.462L14.7143 21.1785C14.7061 20.2514 15.1974 19.3916 16.0003 18.928C16.8029 18.4647 17.7927 18.4689 18.5914 18.9391L18.8363 19.0833C19.4425 19.4402 20.2234 19.3444 20.6574 18.7907C21.3044 17.9654 21.8242 17.0575 22.2084 16.0988C22.4698 15.4465 22.1627 14.7231 21.551 14.3772L21.306 14.2386C20.499 13.7822 20 12.9268 20 11.9997C20 11.0729 20.4986 10.2178 21.3051 9.76126L21.5516 9.62174C22.1641 9.27506 22.4712 8.55029 22.2079 7.89761C22.0165 7.42297 21.7896 6.95598 21.5263 6.50001C21.2628 6.04362 20.9715 5.61325 20.6559 5.20982C20.2223 4.65568 19.4412 4.55944 18.8351 4.91665L18.5916 5.06009C17.7929 5.53078 16.8026 5.53519 15.9997 5.07163C15.1971 4.60825 14.7059 3.74891 14.7138 2.82218L14.7162 2.53994C14.7222 1.83708 14.249 1.20945 13.5532 1.10973C12.5308 0.963214 11.4846 0.959581 10.4464 1.10733C9.75011 1.20641 9.27691 1.83473 9.28317 2.53798L9.28569 2.82154C9.29395 3.74862 8.80264 4.60841 7.99973 5.07197ZM14 15.4641C15.9132 14.3595 16.5687 11.9132 15.4641 9.99999C14.3595 8.08682 11.9132 7.43132 10 8.53589C8.08684 9.64046 7.43134 12.0868 8.53591 14C9.64048 15.9132 12.0868 16.5687 14 15.4641Z</PathGeometry>
|
||||
|
||||
</converters:IconNameConverter>
|
||||
</UserControl.Resources>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Border Padding="4" Theme="{DynamicResource CardBorder}">
|
||||
<u:NavigationMenu
|
||||
Name="menu"
|
||||
HorizontalAlignment="Left"
|
||||
ItemsSource="{Binding MenuItems}"
|
||||
ShowCollapseButton="True">
|
||||
<u:NavigationMenu.Header>
|
||||
<TextBlock
|
||||
Classes="H5"
|
||||
Text="Semi Avalonia"
|
||||
Theme="{DynamicResource TitleTextBlock}" />
|
||||
</u:NavigationMenu.Header>
|
||||
<u:NavigationMenu.Icon>
|
||||
<PathIcon
|
||||
Width="32"
|
||||
Height="32"
|
||||
Data="M10.6201 17.5C6.06377 17.5 2.37012 13.8063 2.37012 9.25C2.37012 4.69365 6.06377 1 10.6201 1V17.5ZM13.3701 6.5C17.9265 6.5 21.6201 10.1936 21.6201 14.75C21.6201 19.3063 17.9265 23 13.3701 23V6.5Z" />
|
||||
</u:NavigationMenu.Icon>
|
||||
<u:NavigationMenu.ItemTemplate>
|
||||
<converters:MenuDataTemplateSelector>
|
||||
<converters:MenuDataTemplateSelector.MenuTemplate>
|
||||
<DataTemplate DataType="vm:MenuItemViewModel">
|
||||
<u:NavigationMenuItem Header="{Binding MenuHeader}" ItemsSource="{Binding Children}">
|
||||
<u:NavigationMenuItem.Icon>
|
||||
<PathIcon
|
||||
Width="16"
|
||||
Height="16"
|
||||
Data="{Binding MenuIconName, Converter={StaticResource IconNameConverter}}" />
|
||||
</u:NavigationMenuItem.Icon>
|
||||
</u:NavigationMenuItem>
|
||||
</DataTemplate>
|
||||
</converters:MenuDataTemplateSelector.MenuTemplate>
|
||||
<converters:MenuDataTemplateSelector.SeparatorTemplate>
|
||||
<DataTemplate DataType="vm:MenuItemViewModel">
|
||||
<u:NavigationMenuSeparator Header="{Binding MenuHeader}" />
|
||||
</DataTemplate>
|
||||
</converters:MenuDataTemplateSelector.SeparatorTemplate>
|
||||
</converters:MenuDataTemplateSelector>
|
||||
</u:NavigationMenu.ItemTemplate>
|
||||
</u:NavigationMenu>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -1,15 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Ursa.Demo.ViewModels;
|
||||
|
||||
namespace Ursa.Demo.Pages;
|
||||
|
||||
public partial class NavigationMenuDemo : UserControl
|
||||
{
|
||||
public NavigationMenuDemo()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.DataContext = new NavigationMenuDemoViewModel();
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,6 @@ public class MainViewViewModel : ViewModelBase
|
||||
MenuKeys.MenuKeyKeyGestureInput => new KeyGestureInputDemoViewModel(),
|
||||
MenuKeys.MenuKeyLoading => new LoadingDemoViewModel(),
|
||||
MenuKeys.MenuKeyMessageBox => new MessageBoxDemoViewModel(),
|
||||
MenuKeys.MenuKeyNavigation => new NavigationMenuDemoViewModel(),
|
||||
MenuKeys.MenuKeyNavMenu => new NavMenuDemoViewModel(),
|
||||
MenuKeys.MenuKeyNumberDisplayer => new NumberDisplayerDemoViewModel(),
|
||||
MenuKeys.MenuKeyNumericUpDown => new NumericUpDownDemoViewModel(),
|
||||
|
||||
@@ -24,12 +24,11 @@ public class MenuViewModel: ViewModelBase
|
||||
new() { MenuHeader = "Enum Selector", Key = MenuKeys.MenuKeyEnumSelector },
|
||||
new() { MenuHeader = "Form", Key = MenuKeys.MenuKeyForm },
|
||||
new() { MenuHeader = "Icon Button", Key = MenuKeys.MenuKeyIconButton },
|
||||
new() { MenuHeader = "ImageViewer", Key = MenuKeys.MenuKeyImageViewer },
|
||||
new() { MenuHeader = "ImageViewer", Key = MenuKeys.MenuKeyImageViewer, Status = "WIP" },
|
||||
new() { MenuHeader = "IPv4Box", Key = MenuKeys.MenuKeyIpBox },
|
||||
new() { MenuHeader = "KeyGestureInput", Key = MenuKeys.MenuKeyKeyGestureInput },
|
||||
new() { MenuHeader = "Loading", Key = MenuKeys.MenuKeyLoading },
|
||||
new() { MenuHeader = "Message Box", Key = MenuKeys.MenuKeyMessageBox, Status = "New" },
|
||||
new() { MenuHeader = "Navigation", Key = MenuKeys.MenuKeyNavigation, Status = "WIP" },
|
||||
new() { MenuHeader = "Nav Menu", Key = MenuKeys.MenuKeyNavMenu, Status = "WIP"},
|
||||
new() { MenuHeader = "Number Displayer", Key = MenuKeys.MenuKeyNumberDisplayer, Status = "New" },
|
||||
new() { MenuHeader = "Numeric UpDown", Key = MenuKeys.MenuKeyNumericUpDown, Status = "New" },
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Ursa.Demo.ViewModels;
|
||||
|
||||
public class NavigationMenuDemoViewModel: ObservableObject
|
||||
{
|
||||
public ObservableCollection<MenuItemViewModel> MenuItems { get; set; } = new()
|
||||
{
|
||||
new MenuItemViewModel()
|
||||
{
|
||||
MenuHeader = "任务管理",
|
||||
MenuIconName = "User",
|
||||
Children = new ObservableCollection<MenuItemViewModel>()
|
||||
{
|
||||
new (){
|
||||
MenuHeader = "公告管理" ,
|
||||
MenuIconName = "Star",
|
||||
Children = new ObservableCollection<MenuItemViewModel>()
|
||||
{
|
||||
new () {MenuHeader = "公告设置"},
|
||||
new () {MenuHeader = "公告处理"}
|
||||
}},
|
||||
new (){MenuHeader = "任务查询"}
|
||||
}
|
||||
},
|
||||
new MenuItemViewModel()
|
||||
{
|
||||
MenuHeader = "附加功能",
|
||||
IsSeparator = true,
|
||||
},
|
||||
new MenuItemViewModel()
|
||||
{
|
||||
MenuHeader = "任务平台",
|
||||
MenuIconName = "Gear",
|
||||
Children = new ObservableCollection<MenuItemViewModel>()
|
||||
{
|
||||
new (){MenuHeader = "任务管理"},
|
||||
new (){MenuHeader = "用户任务查询"}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,338 +0,0 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Ursa.Themes.Semi.Converters"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<!-- Add Resources Here -->
|
||||
|
||||
<converters:NavigationMenuItemLevelToMarginConverter x:Key="MarginConverter" Indent="8" />
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:NavigationMenu}" TargetType="u:NavigationMenu">
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenu">
|
||||
<Border
|
||||
Name="PART_RootBorder"
|
||||
Width="{DynamicResource NavigationMenuExpandWidth}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Border.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Width" Duration="0:0:0.1" />
|
||||
</Transitions>
|
||||
</Border.Transitions>
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||
<Grid
|
||||
Name="PART_RootGrid"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{TemplateBinding Background}"
|
||||
RowDefinitions="Auto, *, Auto, Auto">
|
||||
<StackPanel
|
||||
Margin="{DynamicResource NavigationMenuHeaderMargin}"
|
||||
HorizontalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<ContentPresenter
|
||||
Name="PART_IconPresenter"
|
||||
Margin="{DynamicResource NavigationMenuIconMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Icon}" />
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}" />
|
||||
|
||||
</StackPanel>
|
||||
<ItemsPresenter Grid.Row="1" ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
<ContentPresenter
|
||||
Name="PART_FooterPresenter"
|
||||
Grid.Row="2"
|
||||
Content="{TemplateBinding Footer}"
|
||||
ContentTemplate="{TemplateBinding FooterTemplate}" />
|
||||
<ToggleSwitch
|
||||
Name="{x:Static u:NavigationMenu.PART_CloseButton}"
|
||||
Grid.Row="3"
|
||||
Content="Open"
|
||||
IsChecked="{TemplateBinding IsClosed,
|
||||
Mode=TwoWay}"
|
||||
IsVisible="{TemplateBinding ShowCollapseButton}"
|
||||
Theme="{DynamicResource ButtonToggleSwitch}">
|
||||
<ToggleSwitch.OnContent>
|
||||
<PathIcon
|
||||
Width="{DynamicResource NavigationMenuExpandIconWidth}"
|
||||
Height="{DynamicResource NavigationMenuExpandIconHeight}"
|
||||
Data="{DynamicResource NavigationMenuExpandIconGlyph}"
|
||||
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
|
||||
</ToggleSwitch.OnContent>
|
||||
<ToggleSwitch.OffContent>
|
||||
<PathIcon
|
||||
Width="{DynamicResource NavigationMenuExpandIconWidth}"
|
||||
Height="{DynamicResource NavigationMenuExpandIconHeight}"
|
||||
Data="{DynamicResource NavigationMenuExpandIconGlyph}"
|
||||
Foreground="{DynamicResource ButtonDefaultTertiaryForeground}" />
|
||||
</ToggleSwitch.OffContent>
|
||||
</ToggleSwitch>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:closed">
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_HeaderPresenter">
|
||||
<Setter Property="ContentPresenter.IsVisible" Value="False" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_RootBorder">
|
||||
<Setter Property="Border.Width" Value="{DynamicResource NavigationMenuClosedWidth}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_IconPresenter">
|
||||
<Setter Property="Grid.HorizontalAlignment" Value="Center" />
|
||||
</Style>
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:NavigationMenuItem}" TargetType="u:NavigationMenuItem">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenuItem">
|
||||
<Border>
|
||||
<StackPanel>
|
||||
<Border
|
||||
Name="PART_HeaderBorder"
|
||||
Margin="{DynamicResource NavigationMenuItemDefaultMargin}"
|
||||
Padding="{DynamicResource NavigationMenuItemDefaultPadding}"
|
||||
Background="{DynamicResource NavigationMenuItemDefaultBackground}"
|
||||
CornerRadius="{DynamicResource NavigationMenuItemDefaultCornerRadius}">
|
||||
<Grid
|
||||
Name="PART_RootStackPanel"
|
||||
HorizontalAlignment="Stretch"
|
||||
ColumnDefinitions="Auto, Auto, *, Auto">
|
||||
<ContentPresenter
|
||||
Name="PART_IconPresenter"
|
||||
Grid.Column="1"
|
||||
MinWidth="{DynamicResource NavigationMenuItemIconMinWidth}"
|
||||
Content="{TemplateBinding Icon}"
|
||||
ContentTemplate="{TemplateBinding IconTemplate}">
|
||||
<ContentPresenter.Margin>
|
||||
<MultiBinding Converter="{StaticResource MarginConverter}">
|
||||
<Binding Path="Level" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="IsClosed" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
</MultiBinding>
|
||||
</ContentPresenter.Margin>
|
||||
</ContentPresenter>
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
Grid.Column="2"
|
||||
Margin="{DynamicResource NavigationMenuItemHeaderMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Background="{TemplateBinding Background}"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}">
|
||||
<ContentPresenter.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity" Duration="0:0:0.15" />
|
||||
</Transitions>
|
||||
</ContentPresenter.Transitions>
|
||||
</ContentPresenter>
|
||||
<PathIcon
|
||||
Name="PART_ExpandIcon"
|
||||
Grid.Column="3"
|
||||
Width="{DynamicResource NavigationMenuItemExpandIconWidth}"
|
||||
Height="{DynamicResource NavigationMenuItemExpandIconHeight}"
|
||||
Data="{DynamicResource NavigationMenuItemExpandIconGlyph}"
|
||||
Foreground="{DynamicResource NavigationMenuItemExpandIconForeground}">
|
||||
<PathIcon.Transitions>
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Property="RenderTransform" Duration="0.1" />
|
||||
</Transitions>
|
||||
</PathIcon.Transitions>
|
||||
</PathIcon>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ItemsPresenter Name="PART_ItemsPresenter" ItemsPanel="{TemplateBinding ItemsPanel}">
|
||||
<ItemsPresenter.Transitions>
|
||||
<Transitions>
|
||||
<DoubleTransition Property="Opacity" Duration="0:0:0.15" />
|
||||
</Transitions>
|
||||
</ItemsPresenter.Transitions>
|
||||
</ItemsPresenter>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pointerover">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pressed">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPressedBackground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:highlighted /template/ ContentPresenter#PART_IconPresenter">
|
||||
<Setter Property="u:NavigationMenuItem.Foreground" Value="{DynamicResource NavigationMenuItemHighlightForeground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:selected /template/ Border#PART_HeaderBorder">
|
||||
<Setter Property="u:NavigationMenuItem.Background" Value="{DynamicResource NavigationMenuItemSelectedBackground}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:empty:closed:top-level">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenuItem">
|
||||
<Border
|
||||
Name="PART_HeaderBorder"
|
||||
Margin="{DynamicResource NavigationMenuItemDefaultMargin}"
|
||||
Padding="{DynamicResource NavigationMenuItemDefaultPadding}"
|
||||
HorizontalAlignment="Center"
|
||||
Background="{DynamicResource NavigationMenuItemDefaultBackground}"
|
||||
CornerRadius="{DynamicResource NavigationMenuItemDefaultCornerRadius}"
|
||||
ToolTip.ShowDelay="0"
|
||||
ToolTip.Tip="{TemplateBinding Header}">
|
||||
<ContentPresenter
|
||||
Name="PART_IconPresenter"
|
||||
Grid.Column="1"
|
||||
MinWidth="{DynamicResource NavigationMenuItemIconMinWidth}"
|
||||
Margin="{DynamicResource NavigationMenuItemIconMargin}"
|
||||
Content="{TemplateBinding Icon}"
|
||||
ContentTemplate="{TemplateBinding IconTemplate}" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pointerover">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pressed">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPressedBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:not(:empty):closed">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenuItem">
|
||||
<Panel>
|
||||
<Border
|
||||
Name="PART_HeaderBorder"
|
||||
Margin="{DynamicResource NavigationMenuItemDefaultMargin}"
|
||||
Padding="{DynamicResource NavigationMenuItemDefaultPadding}"
|
||||
HorizontalAlignment="Center"
|
||||
Background="{DynamicResource NavigationMenuItemDefaultBackground}"
|
||||
CornerRadius="{DynamicResource NavigationMenuItemDefaultCornerRadius}">
|
||||
<Grid HorizontalAlignment="Stretch" ColumnDefinitions="Auto, *, Auto">
|
||||
<ContentPresenter
|
||||
Name="PART_IconPresenter"
|
||||
Grid.Column="0"
|
||||
MinWidth="{DynamicResource NavigationMenuItemIconMinWidth}"
|
||||
Content="{TemplateBinding Icon}"
|
||||
ContentTemplate="{TemplateBinding IconTemplate}" />
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
Grid.Column="1"
|
||||
Margin="{DynamicResource NavigationMenuItemHeaderMargin}"
|
||||
VerticalAlignment="Center"
|
||||
Background="{TemplateBinding Background}"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
IsVisible="{TemplateBinding IsTopLevelMenuItem,
|
||||
Converter={x:Static BoolConverters.Not}}" />
|
||||
<PathIcon
|
||||
Grid.Column="2"
|
||||
Width="{DynamicResource NavigationMenuItemExpandIconWidth}"
|
||||
Height="{DynamicResource NavigationMenuItemExpandIconHeight}"
|
||||
Margin="{DynamicResource NavigationMenuItemExpandIconMargin}"
|
||||
Data="{DynamicResource NavigationMenuItemExpandIconGlyph}"
|
||||
Foreground="{DynamicResource NavigationMenuItemExpandIconForeground}"
|
||||
IsVisible="{TemplateBinding IsTopLevelMenuItem,
|
||||
Converter={x:Static BoolConverters.Not}}"
|
||||
RenderTransform="rotate(-90deg)" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<Popup
|
||||
Name="{x:Static u:NavigationMenuItem.PART_Popup}"
|
||||
IsLightDismissEnabled="True"
|
||||
IsOpen="{TemplateBinding IsPopupOpen,
|
||||
Mode=TwoWay}"
|
||||
Placement="RightEdgeAlignedTop"
|
||||
PlacementTarget="PART_HeaderBorder"
|
||||
WindowManagerAddShadowHint="False">
|
||||
<Border
|
||||
MinWidth="{DynamicResource MenuFlyoutMinWidth}"
|
||||
MinHeight="{DynamicResource MenuFlyoutMinHeight}"
|
||||
MaxWidth="{DynamicResource MenuFlyoutMaxWidth}"
|
||||
MaxHeight="{DynamicResource MenuFlyoutMaxHeight}"
|
||||
Margin="{DynamicResource NavigationMenuItemFlyoutMargin}"
|
||||
Padding="{DynamicResource MenuFlyoutPadding}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="{DynamicResource MenuFlyoutBackground}"
|
||||
BorderBrush="{DynamicResource MenuFlyoutBorderBrush}"
|
||||
BorderThickness="{DynamicResource MenuFlyoutBorderThickness}"
|
||||
BoxShadow="{DynamicResource MenuFlyoutBorderBoxShadow}"
|
||||
CornerRadius="{DynamicResource MenuFlyoutCornerRadius}">
|
||||
<ScrollViewer Theme="{DynamicResource MenuScrollViewer}">
|
||||
<ItemsPresenter
|
||||
Name="PART_ItemsPresenter"
|
||||
Grid.IsSharedSizeScope="True"
|
||||
ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pointerover">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPointeroverBackground}" />
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Border#PART_HeaderBorder:pressed">
|
||||
<Setter Property="Border.Background" Value="{DynamicResource NavigationMenuItemPressedBackground}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^:not(:closed):collapsed /template/ ItemsPresenter#PART_ItemsPresenter">
|
||||
<Setter Property="ItemsPresenter.Height" Value="{DynamicResource NavigationMenuItemCollapsedHeight}" />
|
||||
<Setter Property="ItemsPresenter.Opacity" Value="{DynamicResource NavigationMenuItemCollapsedOpacity}" />
|
||||
</Style>
|
||||
<Style Selector="^:not(:empty):not(:collapsed) /template/ PathIcon#PART_ExpandIcon">
|
||||
<Setter Property="PathIcon.RenderTransform" Value="rotate(-180deg)" />
|
||||
</Style>
|
||||
<Style Selector="^:empty /template/ PathIcon#PART_ExpandIcon">
|
||||
<Setter Property="PathIcon.IsVisible" Value="False" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:NavigationMenuSeparator}" TargetType="u:NavigationMenuSeparator">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:NavigationMenuSeparator">
|
||||
<StackPanel Name="PART_RootPanel" Margin="{DynamicResource NavigationMenuSeparatorMargin}">
|
||||
<ContentPresenter
|
||||
Name="PART_HeaderPresenter"
|
||||
Margin="{DynamicResource NavigationMenuSeparatorHeaderMargin}"
|
||||
HorizontalAlignment="Left"
|
||||
Content="{TemplateBinding Header}"
|
||||
ContentTemplate="{TemplateBinding HeaderTemplate}"
|
||||
Foreground="{DynamicResource TextBlockQuaternaryForeground}"
|
||||
IsVisible="{TemplateBinding Header,
|
||||
Converter={x:Static ObjectConverters.IsNotNull}}">
|
||||
<ContentPresenter.Styles>
|
||||
<Style Selector="TextBlock">
|
||||
<Setter Property="FontSize" Value="{DynamicResource NavigationMenuSeparatorHeaderFontSize}" />
|
||||
</Style>
|
||||
</ContentPresenter.Styles>
|
||||
</ContentPresenter>
|
||||
<Rectangle
|
||||
Height="{DynamicResource NavigationMenuSeparatorBorderHeight}"
|
||||
Margin="{DynamicResource NavigationMenuSeparatorBorderMargin}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Fill="{DynamicResource SemiColorBorder}" />
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:closed /template/ StackPanel#PART_RootPanel">
|
||||
<Setter Property="StackPanel.HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="StackPanel.Width" Value="{DynamicResource NavigationMenuSeparatorClosedWidth}" />
|
||||
</Style>
|
||||
<Style Selector="^:closed /template/ ContentPresenter#PART_HeaderPresenter">
|
||||
<Setter Property="ContentPresenter.IsVisible" Value="False" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -19,7 +19,6 @@
|
||||
<ResourceInclude Source="KeyGestureInput.axaml" />
|
||||
<ResourceInclude Source="Loading.axaml" />
|
||||
<ResourceInclude Source="MessageBox.axaml" />
|
||||
<ResourceInclude Source="Navigation.axaml" />
|
||||
<ResourceInclude Source="NavMenu.axaml" />
|
||||
<ResourceInclude Source="NumericUpDown.axaml" />
|
||||
<ResourceInclude Source="NumberDisplayer.axaml" />
|
||||
|
||||
@@ -6,6 +6,7 @@ using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Metadata;
|
||||
using Irihi.Avalonia.Shared.Helpers;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
@@ -61,22 +62,10 @@ public class ButtonGroup: ItemsControl
|
||||
base.PrepareContainerForItemOverride(container, item, index);
|
||||
if(container is Button button)
|
||||
{
|
||||
if ( CommandBinding is not null)
|
||||
{
|
||||
button[!Button.CommandProperty] = CommandBinding;
|
||||
}
|
||||
if ( CommandParameterBinding is not null)
|
||||
{
|
||||
button[!Button.CommandParameterProperty] = CommandParameterBinding;
|
||||
}
|
||||
if ( ContentBinding is not null)
|
||||
{
|
||||
button[!Button.ContentProperty] = ContentBinding;
|
||||
}
|
||||
if (ItemTemplate is not null)
|
||||
{
|
||||
button.ContentTemplate = ItemTemplate;
|
||||
}
|
||||
button.TryBind(Button.CommandProperty, CommandBinding);
|
||||
button.TryBind(Button.CommandParameterProperty, CommandParameterBinding);
|
||||
button.TryBind(ContentControl.ContentProperty, ContentBinding);
|
||||
button.TryBind(ContentControl.ContentTemplateProperty, this[!ItemTemplateProperty]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ public class EnumSelector: TemplatedControl
|
||||
if (o is not EnumSelector selector) return null;
|
||||
if (value is null) return null;
|
||||
if (value.GetType() != selector.EnumType) return null;
|
||||
var first = selector.Values.FirstOrDefault(a => Equals(a.Value, value));
|
||||
var first = selector.Values?.FirstOrDefault(a => Equals(a.Value, value));
|
||||
if (first is null) return null;
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class FormItem: ContentControl
|
||||
|
||||
static FormItem()
|
||||
{
|
||||
PropertyToPseudoClassMixin.Attach<FormItem>(NoLabelProperty, PC_NoLabel);
|
||||
NoLabelProperty.AffectsPseudoClass<FormItem>(PC_NoLabel);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
|
||||
@@ -76,7 +76,7 @@ public class TwoTonePathIcon: TemplatedControl
|
||||
ForegroundProperty,
|
||||
ActiveForegroundProperty,
|
||||
ActiveStrokeBrushProperty);
|
||||
PropertyToPseudoClassMixin.Attach<TwoTonePathIcon>(IsActiveProperty, PC_Active);
|
||||
IsActiveProperty.AffectsPseudoClass<TwoTonePathIcon>(PC_Active);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
|
||||
@@ -146,7 +146,7 @@ public class NavMenu: ItemsControl
|
||||
static NavMenu()
|
||||
{
|
||||
SelectedItemProperty.Changed.AddClassHandler<NavMenu, object?>((o, e) => o.OnSelectedItemChange(e));
|
||||
PropertyToPseudoClassMixin.Attach<NavMenu>(IsHorizontalCollapsedProperty, PC_HorizontalCollapsed);
|
||||
IsHorizontalCollapsedProperty.AffectsPseudoClass<NavMenu>(PC_HorizontalCollapsed);
|
||||
CanToggleProperty.Changed.AddClassHandler<InputElement, bool>(OnInputRegisteredAsToggle);
|
||||
}
|
||||
|
||||
|
||||
@@ -140,10 +140,10 @@ public class NavMenuItem: HeaderedItemsControl
|
||||
// SelectableMixin.Attach<NavMenuItem>(IsSelectedProperty);
|
||||
PressedMixin.Attach<NavMenuItem>();
|
||||
LevelProperty.Changed.AddClassHandler<NavMenuItem, int>((item, args) => item.OnLevelChange(args));
|
||||
PropertyToPseudoClassMixin.Attach<NavMenuItem>(IsHighlightedProperty, PC_Highlighted);
|
||||
PropertyToPseudoClassMixin.Attach<NavMenuItem>(IsHorizontalCollapsedProperty, PC_HorizontalCollapsed);
|
||||
PropertyToPseudoClassMixin.Attach<NavMenuItem>(IsVerticalCollapsedProperty, PC_VerticalCollapsed);
|
||||
PropertyToPseudoClassMixin.Attach<NavMenuItem>(IsSelectedProperty, ":selected", IsSelectedChangedEvent);
|
||||
IsHighlightedProperty.AffectsPseudoClass<NavMenuItem>(PC_Highlighted);
|
||||
IsHorizontalCollapsedProperty.AffectsPseudoClass<NavMenuItem>(PC_HorizontalCollapsed);
|
||||
IsVerticalCollapsedProperty.AffectsPseudoClass<NavMenuItem>(PC_VerticalCollapsed);
|
||||
IsSelectedProperty.AffectsPseudoClass<NavMenuItem>(":selected", IsSelectedChangedEvent);
|
||||
IsHorizontalCollapsedProperty.Changed.AddClassHandler<NavMenuItem, bool>((item, args) =>
|
||||
item.OnIsHorizontalCollapsedChanged(args));
|
||||
}
|
||||
@@ -195,22 +195,10 @@ public class NavMenuItem: HeaderedItemsControl
|
||||
_overflowPanel = e.NameScope.Find<Panel>("PART_OverflowPanel");
|
||||
if (_rootMenu is not null)
|
||||
{
|
||||
if (_rootMenu.IconBinding is not null)
|
||||
{
|
||||
this[!IconProperty] = _rootMenu.IconBinding;
|
||||
}
|
||||
if (_rootMenu.HeaderBinding is not null)
|
||||
{
|
||||
this[!HeaderProperty] = _rootMenu.HeaderBinding;
|
||||
}
|
||||
if (_rootMenu.SubMenuBinding is not null)
|
||||
{
|
||||
this[!ItemsSourceProperty] = _rootMenu.SubMenuBinding;
|
||||
}
|
||||
if (_rootMenu.CommandBinding is not null)
|
||||
{
|
||||
this[!CommandProperty] = _rootMenu.CommandBinding;
|
||||
}
|
||||
this.TryBind(IconProperty, _rootMenu.IconBinding);
|
||||
this.TryBind(HeaderProperty, _rootMenu.HeaderBinding);
|
||||
this.TryBind(ItemsSourceProperty, _rootMenu.SubMenuBinding);
|
||||
this.TryBind(CommandProperty, _rootMenu.CommandBinding);
|
||||
this[!IconTemplateProperty] = _rootMenu[!NavMenu.IconTemplateProperty];
|
||||
this[!HeaderTemplateProperty] = _rootMenu[!NavMenu.HeaderTemplateProperty];
|
||||
this[!SubMenuIndentProperty] = _rootMenu[!NavMenu.SubMenuIndentProperty];
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
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.Markup.Xaml.Templates;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[PseudoClasses(PC_Closed)]
|
||||
[TemplatePart(Name = PART_CloseButton, Type = typeof(ToggleButton))]
|
||||
|
||||
public class NavigationMenu: HeaderedItemsControl
|
||||
{
|
||||
public const string PC_Closed = ":closed";
|
||||
public const string PART_CloseButton = "PART_CloseButton";
|
||||
|
||||
public static readonly StyledProperty<object?> FooterProperty = AvaloniaProperty.Register<NavigationMenu, object?>(
|
||||
nameof(Footer));
|
||||
|
||||
public object? Footer
|
||||
{
|
||||
get => GetValue(FooterProperty);
|
||||
set => SetValue(FooterProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IDataTemplate> FooterTemplateProperty = AvaloniaProperty.Register<NavigationMenu, IDataTemplate>(
|
||||
nameof(FooterTemplate));
|
||||
|
||||
public IDataTemplate FooterTemplate
|
||||
{
|
||||
get => GetValue(FooterTemplateProperty);
|
||||
set => SetValue(FooterTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> IconProperty = AvaloniaProperty.Register<NavigationMenu, object?>(
|
||||
nameof(Icon));
|
||||
|
||||
public object? Icon
|
||||
{
|
||||
get => GetValue(IconProperty);
|
||||
set => SetValue(IconProperty, value);
|
||||
}
|
||||
|
||||
|
||||
public static readonly StyledProperty<object?> SelectedItemProperty = AvaloniaProperty.Register<NavigationMenu, object?>(
|
||||
nameof(SelectedItem));
|
||||
|
||||
public object? SelectedItem
|
||||
{
|
||||
get => GetValue(SelectedItemProperty);
|
||||
set => SetValue(SelectedItemProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> ShowCollapseButtonProperty = AvaloniaProperty.Register<NavigationMenu, bool>(
|
||||
nameof(ShowCollapseButton));
|
||||
|
||||
public bool ShowCollapseButton
|
||||
{
|
||||
get => GetValue(ShowCollapseButtonProperty);
|
||||
set => SetValue(ShowCollapseButtonProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsClosedProperty = AvaloniaProperty.Register<NavigationMenu, bool>(
|
||||
nameof(IsClosed));
|
||||
|
||||
public bool IsClosed
|
||||
{
|
||||
get => GetValue(IsClosedProperty);
|
||||
set => SetValue(IsClosedProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<double> OpenedWidthProperty = AvaloniaProperty.Register<NavigationMenu, double>(
|
||||
nameof(OpenedWidth));
|
||||
|
||||
public double OpenedWidth
|
||||
{
|
||||
get => GetValue(OpenedWidthProperty);
|
||||
set => SetValue(OpenedWidthProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<double> ClosedWidthProperty = AvaloniaProperty.Register<NavigationMenu, double>(
|
||||
nameof(ClosedWidth));
|
||||
|
||||
public double ClosedWidth
|
||||
{
|
||||
get => GetValue(ClosedWidthProperty);
|
||||
set => SetValue(ClosedWidthProperty, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static NavigationMenu()
|
||||
{
|
||||
SelectedItemProperty.Changed.AddClassHandler<NavigationMenu>((o, e) => o.OnSelectionItemChanged(e));
|
||||
IsClosedProperty.Changed.AddClassHandler<NavigationMenu>((o,e)=>o.OnIsClosedChanged(e));
|
||||
}
|
||||
|
||||
private void OnSelectionItemChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
var newItem = args.GetNewValue<object?>();
|
||||
if (newItem is not null)
|
||||
{
|
||||
UpdateSelectionFromSelectedItem(newItem);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnIsClosedChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
bool newValue = args.GetNewValue<bool>();
|
||||
PseudoClasses.Set(PC_Closed, newValue);
|
||||
}
|
||||
|
||||
internal void UpdateSelection(NavigationMenuItem source)
|
||||
{
|
||||
var children = this.ItemsPanelRoot?.Children;
|
||||
if (children is not null)
|
||||
{
|
||||
foreach (var child in children)
|
||||
{
|
||||
NavigationMenuItem? item = NavigationMenuItem.GetMenuItemFromControl(child);
|
||||
if (item != null)
|
||||
{
|
||||
if(Equals(item, source)) continue;
|
||||
item.SetSelection(null, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateSelectionFromSelectedItem(object? o)
|
||||
{
|
||||
var children = this.ItemsPanelRoot?.Children;
|
||||
if (children is not null)
|
||||
{
|
||||
foreach (var child in children)
|
||||
{
|
||||
NavigationMenuItem? item = NavigationMenuItem.GetMenuItemFromControl(child);
|
||||
if(item is null) continue;
|
||||
item.UpdateSelectionFromSelectedItem(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,282 +0,0 @@
|
||||
using System.Windows.Input;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Markup.Xaml.Templates;
|
||||
using Avalonia.Reactive;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[PseudoClasses(PC_Closed, PC_Selected, PC_Highlighted, PC_Collapsed, PC_TopLevel)]
|
||||
[TemplatePart(PART_Popup, typeof(Popup))]
|
||||
public class NavigationMenuItem: HeaderedSelectingItemsControl
|
||||
{
|
||||
public const string PC_Closed = ":closed";
|
||||
public const string PC_Selected = ":selected";
|
||||
public const string PC_Highlighted= ":highlighted";
|
||||
public const string PC_Collapsed = ":collapsed";
|
||||
public const string PC_TopLevel = ":top-level";
|
||||
public const string PART_Popup = "PART_Popup";
|
||||
|
||||
private NavigationMenu? _rootMenu;
|
||||
private IDisposable? _ownerSubscription;
|
||||
private IDisposable? _itemsBinding;
|
||||
private bool _isCollapsed;
|
||||
private Popup? _popup;
|
||||
|
||||
public static readonly StyledProperty<bool> IsClosedProperty = AvaloniaProperty.Register<NavigationMenuItem, bool>(
|
||||
nameof(IsClosed));
|
||||
|
||||
public bool IsClosed
|
||||
{
|
||||
get => GetValue(IsClosedProperty);
|
||||
set => SetValue(IsClosedProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> IconProperty = AvaloniaProperty.Register<NavigationMenuItem, object?>(
|
||||
nameof(Icon));
|
||||
|
||||
public object? Icon
|
||||
{
|
||||
get => GetValue(IconProperty);
|
||||
set => SetValue(IconProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IDataTemplate> IconTemplateProperty = AvaloniaProperty.Register<NavigationMenuItem, IDataTemplate>(
|
||||
nameof(IconTemplate));
|
||||
|
||||
public IDataTemplate IconTemplate
|
||||
{
|
||||
get => GetValue(IconTemplateProperty);
|
||||
set => SetValue(IconTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DirectProperty<NavigationMenuItem, int> LevelProperty = AvaloniaProperty.RegisterDirect<NavigationMenuItem, int>(
|
||||
nameof(Level), o => o.Level);
|
||||
private int _level;
|
||||
public int Level
|
||||
{
|
||||
get => _level;
|
||||
private set => SetAndRaise(LevelProperty, ref _level, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<ICommand> CommandProperty = AvaloniaProperty.Register<NavigationMenuItem, ICommand>(
|
||||
nameof(Command));
|
||||
|
||||
public ICommand Command
|
||||
{
|
||||
get => GetValue(CommandProperty);
|
||||
set => SetValue(CommandProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<object?> CommandParameterProperty = AvaloniaProperty.Register<NavigationMenuItem, object?>(
|
||||
nameof(CommandParameter));
|
||||
|
||||
public object? CommandParameter
|
||||
{
|
||||
get => GetValue(CommandParameterProperty);
|
||||
set => SetValue(CommandParameterProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DirectProperty<NavigationMenuItem, bool> IsTopLevelMenuItemProperty = AvaloniaProperty.RegisterDirect<NavigationMenuItem, bool>(
|
||||
nameof(IsTopLevelMenuItem), o => o.IsTopLevelMenuItem, (o, v) => o.IsTopLevelMenuItem = v);
|
||||
private bool _isTopLevelMenuItem;
|
||||
public bool IsTopLevelMenuItem
|
||||
{
|
||||
get => _isTopLevelMenuItem;
|
||||
set => SetAndRaise(IsTopLevelMenuItemProperty, ref _isTopLevelMenuItem, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> IsPopupOpenProperty = AvaloniaProperty.Register<NavigationMenuItem, bool>(
|
||||
nameof(IsPopupOpen));
|
||||
|
||||
public bool IsPopupOpen
|
||||
{
|
||||
get => GetValue(IsPopupOpenProperty);
|
||||
set => SetValue(IsPopupOpenProperty, value);
|
||||
}
|
||||
|
||||
static NavigationMenuItem()
|
||||
{
|
||||
IsClosedProperty.Changed.AddClassHandler<NavigationMenuItem>((o, e) => o.OnIsClosedChanged(e));
|
||||
PressedMixin.Attach<NavigationMenuItem>();
|
||||
}
|
||||
|
||||
private void OnIsClosedChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
bool newValue = args.GetNewValue<bool>();
|
||||
PseudoClasses.Set(PC_Closed, newValue);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
GetRootMenu();
|
||||
if (ItemTemplate == null && _rootMenu?.ItemTemplate != null)
|
||||
{
|
||||
SetCurrentValue(ItemTemplateProperty, _rootMenu.ItemTemplate);
|
||||
}
|
||||
if (ItemContainerTheme == null && _rootMenu?.ItemContainerTheme != null)
|
||||
{
|
||||
SetCurrentValue(ItemContainerThemeProperty, _rootMenu.ItemContainerTheme);
|
||||
}
|
||||
|
||||
if (_rootMenu is not null)
|
||||
{
|
||||
// IsClosed = _rootMenu.IsClosed;
|
||||
}
|
||||
|
||||
_rootMenu?.GetObservable(NavigationMenu.IsClosedProperty)
|
||||
.Subscribe(new AnonymousObserver<bool>(a => this.IsClosed = a));
|
||||
_rootMenu?.UpdateSelectionFromSelectedItem(_rootMenu.SelectedItem);
|
||||
_popup = e.NameScope.Find<Popup>(PART_Popup);
|
||||
Level = CalculateDistanceFromLogicalParent<NavigationMenu>(this) - 1;
|
||||
bool isTopLevel = Level == 0;
|
||||
IsTopLevelMenuItem = isTopLevel;
|
||||
PseudoClasses.Set(PC_TopLevel, isTopLevel);
|
||||
}
|
||||
|
||||
private void GetRootMenu()
|
||||
{
|
||||
_rootMenu = this.FindAncestorOfType<NavigationMenu>();
|
||||
if (_rootMenu is null)
|
||||
{
|
||||
var parents = this.FindLogicalAncestorOfType<NavigationMenu>();
|
||||
if (parents is not null)
|
||||
{
|
||||
_rootMenu = parents;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
// Leaf menu node, can be selected.
|
||||
if (this.ItemCount == 0)
|
||||
{
|
||||
if (_rootMenu is not null )
|
||||
{
|
||||
object? o = this.DataContext == _rootMenu.DataContext ? this : this.DataContext ?? this;
|
||||
_rootMenu.SelectedItem = o;
|
||||
}
|
||||
SetSelection(this, true, true);
|
||||
}
|
||||
// Non-leaf node, act as a toggle button.
|
||||
else
|
||||
{
|
||||
_isCollapsed = !_isCollapsed;
|
||||
this.PseudoClasses.Set(PC_Collapsed, _isCollapsed);
|
||||
if (_popup is not null)
|
||||
{
|
||||
_popup.IsOpen = !_popup.IsOpen;
|
||||
}
|
||||
}
|
||||
e.Handled = true;
|
||||
Command?.Execute(CommandParameter);
|
||||
}
|
||||
|
||||
internal void SetSelection(NavigationMenuItem? source, bool selected, bool propagateToParent = false)
|
||||
{
|
||||
if (Equals(this, source) && this.ItemCount == 0)
|
||||
{
|
||||
this.PseudoClasses.Set(PC_Highlighted, selected);
|
||||
this.PseudoClasses.Set(PC_Selected, selected);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.PseudoClasses.Set(PC_Selected, false);
|
||||
this.PseudoClasses.Set(PC_Highlighted, selected);
|
||||
}
|
||||
var children = this.ItemsPanelRoot?.Children;
|
||||
if (children is not null)
|
||||
{
|
||||
foreach (var child in children)
|
||||
{
|
||||
NavigationMenuItem? item = GetMenuItemFromControl(child);
|
||||
if (item != null)
|
||||
{
|
||||
if(Equals(item, source)) continue;
|
||||
item.SetSelection(this, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (propagateToParent)
|
||||
{
|
||||
var parent = this.FindLogicalAncestorOfType<NavigationMenuItem>();
|
||||
if (parent != null)
|
||||
{
|
||||
parent.SetSelection(this, selected, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selected && source!=null)
|
||||
{
|
||||
_rootMenu?.UpdateSelection(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateSelectionFromSelectedItem(object? o)
|
||||
{
|
||||
if (o is null)
|
||||
{
|
||||
this.SetSelection(this, false, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Equals(this, o) || Equals(this.DataContext, o))
|
||||
{
|
||||
this.SetSelection(this, true, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
var children = this.ItemsPanelRoot?.Children;
|
||||
if (children is not null)
|
||||
{
|
||||
foreach (var child in children)
|
||||
{
|
||||
NavigationMenuItem? item = GetMenuItemFromControl(child);
|
||||
if (item != null)
|
||||
{
|
||||
item.UpdateSelectionFromSelectedItem(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int CalculateDistanceFromLogicalParent<T>(ILogical? logical, int @default = -1) where T : class
|
||||
{
|
||||
var result = 0;
|
||||
|
||||
while (logical != null && !(logical is T))
|
||||
{
|
||||
if (logical is NavigationMenuItem)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
logical = logical.LogicalParent;
|
||||
}
|
||||
|
||||
return logical != null ? result : @default;
|
||||
}
|
||||
|
||||
public static NavigationMenuItem? GetMenuItemFromControl(Control? control)
|
||||
{
|
||||
if (control is null) return null;
|
||||
if (control is NavigationMenuItem item) return item;
|
||||
if (control is ContentPresenter { Child: NavigationMenuItem item2 }) return item2;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class NavigationMenuSeparator: NavigationMenuItem
|
||||
{
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="$(AvaloniaVersion)" />
|
||||
<PackageReference Include="Irihi.Avalonia.Shared" Version="0.1.2" />
|
||||
<PackageReference Include="Irihi.Avalonia.Shared" Version="0.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user