mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-28 23:08:36 +08:00
Complete the expansion and closing of the inline navigation menu
This commit is contained in:
@@ -229,6 +229,27 @@
|
||||
<atom:NavMenuItem Header="Navigation Four"/>
|
||||
</atom:NavMenu>
|
||||
</desktop:ShowCaseItem>
|
||||
|
||||
<desktop:ShowCaseItem
|
||||
Title="Inline menu"
|
||||
Description="Vertical menu with inline submenus.">
|
||||
<atom:NavMenu Mode="Inline" Width="256" Margin="0, 0, 0, 20">
|
||||
<atom:NavMenuItem Header="Navigation One" Icon="{atom:IconProvider Kind=MailOutlined}" />
|
||||
<atom:NavMenuItem Header="Navigation Two" Icon="{atom:IconProvider Kind=AppstoreOutlined}" IsEnabled="False"/>
|
||||
<atom:NavMenuItem Header="Navigation Three - Submenu" Icon="{atom:IconProvider Kind=SettingOutlined}">
|
||||
<atom:NavMenuItem Header="Item 1">
|
||||
<atom:NavMenuItem Header="Option 1" />
|
||||
<atom:NavMenuItem Header="Option 2" />
|
||||
</atom:NavMenuItem>
|
||||
|
||||
<atom:NavMenuItem Header="Item 2">
|
||||
<atom:NavMenuItem Header="Option 3" />
|
||||
<atom:NavMenuItem Header="Option 4" />
|
||||
</atom:NavMenuItem>
|
||||
</atom:NavMenuItem>
|
||||
<atom:NavMenuItem Header="Navigation Four"/>
|
||||
</atom:NavMenu>
|
||||
</desktop:ShowCaseItem>
|
||||
|
||||
</desktop:ShowCasePanel>
|
||||
</UserControl>
|
||||
+1
@@ -405,6 +405,7 @@ namespace AtomUI.Theme.Styling
|
||||
public static readonly TokenResourceKey ActiveBarHeight = new TokenResourceKey("NavMenu.ActiveBarHeight", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey ItemContentMargin = new TokenResourceKey("NavMenu.ItemContentMargin", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey ItemContentPadding = new TokenResourceKey("NavMenu.ItemContentPadding", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey VerticalItemsPanelSpacing = new TokenResourceKey("NavMenu.VerticalItemsPanelSpacing", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey ItemMargin = new TokenResourceKey("NavMenu.ItemMargin", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey HorizontalItemMargin = new TokenResourceKey("NavMenu.HorizontalItemMargin", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey HorizontalItemHoverBg = new TokenResourceKey("NavMenu.HorizontalItemHoverBg", "AtomUI.Token");
|
||||
|
||||
@@ -38,109 +38,114 @@ internal class BaseNavMenuItemTheme : BaseControlTheme
|
||||
BuildInstanceStyles(item);
|
||||
// 仅仅为了把 Popup 包进来,没有其他什么作用
|
||||
var layoutWrapper = new Panel();
|
||||
var container = new Border
|
||||
{
|
||||
Name = ItemDecoratorPart
|
||||
};
|
||||
|
||||
var transitions = new Transitions();
|
||||
transitions.Add(AnimationUtils.CreateTransition<SolidColorBrushTransition>(Border.BackgroundProperty));
|
||||
container.Transitions = transitions;
|
||||
|
||||
var layout = new Grid
|
||||
{
|
||||
Name = MainContainerPart,
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition(GridLength.Auto)
|
||||
{
|
||||
SharedSizeGroup = ThemeConstants.IconPresenterSizeGroup
|
||||
},
|
||||
new ColumnDefinition(GridLength.Star),
|
||||
new ColumnDefinition(GridLength.Auto)
|
||||
{
|
||||
SharedSizeGroup = ThemeConstants.InputGestureTextSizeGroup
|
||||
},
|
||||
new ColumnDefinition(GridLength.Auto)
|
||||
{
|
||||
SharedSizeGroup = ThemeConstants.MenuIndicatorIconSizeGroup
|
||||
}
|
||||
}
|
||||
};
|
||||
layout.RegisterInNameScope(scope);
|
||||
|
||||
var iconPresenter = new Viewbox
|
||||
{
|
||||
Name = ItemIconPresenterPart,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Stretch = Stretch.Uniform
|
||||
};
|
||||
|
||||
Grid.SetColumn(iconPresenter, 0);
|
||||
iconPresenter.RegisterInNameScope(scope);
|
||||
CreateTemplateParentBinding(iconPresenter, Viewbox.ChildProperty, NavMenuItem.IconProperty);
|
||||
TokenResourceBinder.CreateTokenBinding(iconPresenter, Layoutable.MarginProperty,
|
||||
NavMenuTokenResourceKey.ItemMargin);
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(iconPresenter, Layoutable.WidthProperty,
|
||||
NavMenuTokenResourceKey.ItemIconSize);
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(iconPresenter, Layoutable.HeightProperty,
|
||||
NavMenuTokenResourceKey.ItemIconSize);
|
||||
|
||||
var itemTextPresenter = new ContentPresenter
|
||||
{
|
||||
Name = ItemTextPresenterPart,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
RecognizesAccessKey = true,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
Grid.SetColumn(itemTextPresenter, 1);
|
||||
TokenResourceBinder.CreateTokenBinding(itemTextPresenter, Layoutable.MarginProperty,
|
||||
NavMenuTokenResourceKey.ItemMargin);
|
||||
CreateTemplateParentBinding(itemTextPresenter, ContentPresenter.ContentProperty,
|
||||
HeaderedSelectingItemsControl.HeaderProperty);
|
||||
CreateTemplateParentBinding(itemTextPresenter, ContentPresenter.ContentTemplateProperty,
|
||||
HeaderedSelectingItemsControl.HeaderTemplateProperty);
|
||||
|
||||
itemTextPresenter.RegisterInNameScope(scope);
|
||||
|
||||
var inputGestureText = new TextBlock
|
||||
{
|
||||
Name = InputGestureTextPart,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
TextAlignment = TextAlignment.Right,
|
||||
VerticalAlignment = VerticalAlignment.Center
|
||||
};
|
||||
Grid.SetColumn(inputGestureText, 2);
|
||||
TokenResourceBinder.CreateTokenBinding(inputGestureText, Layoutable.MarginProperty,
|
||||
NavMenuTokenResourceKey.ItemMargin);
|
||||
CreateTemplateParentBinding(inputGestureText,
|
||||
TextBlock.TextProperty,
|
||||
NavMenuItem.InputGestureProperty,
|
||||
BindingMode.Default,
|
||||
NavMenuItem.KeyGestureConverter);
|
||||
|
||||
inputGestureText.RegisterInNameScope(scope);
|
||||
|
||||
var menuIndicatorIcon = BuildMenuIndicatorIcon();
|
||||
Grid.SetColumn(menuIndicatorIcon, 3);
|
||||
menuIndicatorIcon.RegisterInNameScope(scope);
|
||||
|
||||
layout.Children.Add(iconPresenter);
|
||||
layout.Children.Add(itemTextPresenter);
|
||||
layout.Children.Add(inputGestureText);
|
||||
layout.Children.Add(menuIndicatorIcon);
|
||||
|
||||
BuildExtraItem(layout, scope);
|
||||
|
||||
container.Child = layout;
|
||||
layoutWrapper.Children.Add(container);
|
||||
var header = BuildMenuItemContent(scope);
|
||||
BuildExtraItem(layoutWrapper, scope);
|
||||
layoutWrapper.Children.Add(header);
|
||||
return layoutWrapper;
|
||||
});
|
||||
}
|
||||
|
||||
protected virtual void BuildExtraItem(Grid containerLayout, INameScope scope)
|
||||
protected virtual Control BuildMenuItemContent(INameScope scope)
|
||||
{
|
||||
var headerFrame = new Border
|
||||
{
|
||||
Name = ItemDecoratorPart
|
||||
};
|
||||
|
||||
var transitions = new Transitions();
|
||||
transitions.Add(AnimationUtils.CreateTransition<SolidColorBrushTransition>(Border.BackgroundProperty));
|
||||
headerFrame.Transitions = transitions;
|
||||
|
||||
var layout = new Grid
|
||||
{
|
||||
Name = MainContainerPart,
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition(GridLength.Auto)
|
||||
{
|
||||
SharedSizeGroup = ThemeConstants.IconPresenterSizeGroup
|
||||
},
|
||||
new ColumnDefinition(GridLength.Star),
|
||||
new ColumnDefinition(GridLength.Auto)
|
||||
{
|
||||
SharedSizeGroup = ThemeConstants.InputGestureTextSizeGroup
|
||||
},
|
||||
new ColumnDefinition(GridLength.Auto)
|
||||
{
|
||||
SharedSizeGroup = ThemeConstants.MenuIndicatorIconSizeGroup
|
||||
}
|
||||
}
|
||||
};
|
||||
layout.RegisterInNameScope(scope);
|
||||
|
||||
var iconPresenter = new Viewbox
|
||||
{
|
||||
Name = ItemIconPresenterPart,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Stretch = Stretch.Uniform
|
||||
};
|
||||
|
||||
Grid.SetColumn(iconPresenter, 0);
|
||||
iconPresenter.RegisterInNameScope(scope);
|
||||
CreateTemplateParentBinding(iconPresenter, Viewbox.ChildProperty, NavMenuItem.IconProperty);
|
||||
TokenResourceBinder.CreateTokenBinding(iconPresenter, Layoutable.MarginProperty,
|
||||
NavMenuTokenResourceKey.ItemMargin);
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(iconPresenter, Layoutable.WidthProperty,
|
||||
NavMenuTokenResourceKey.ItemIconSize);
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(iconPresenter, Layoutable.HeightProperty,
|
||||
NavMenuTokenResourceKey.ItemIconSize);
|
||||
|
||||
var itemTextPresenter = new ContentPresenter
|
||||
{
|
||||
Name = ItemTextPresenterPart,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
RecognizesAccessKey = true,
|
||||
IsHitTestVisible = false
|
||||
};
|
||||
Grid.SetColumn(itemTextPresenter, 1);
|
||||
TokenResourceBinder.CreateTokenBinding(itemTextPresenter, Layoutable.MarginProperty,
|
||||
NavMenuTokenResourceKey.ItemMargin);
|
||||
CreateTemplateParentBinding(itemTextPresenter, ContentPresenter.ContentProperty,
|
||||
HeaderedSelectingItemsControl.HeaderProperty);
|
||||
CreateTemplateParentBinding(itemTextPresenter, ContentPresenter.ContentTemplateProperty,
|
||||
HeaderedSelectingItemsControl.HeaderTemplateProperty);
|
||||
|
||||
itemTextPresenter.RegisterInNameScope(scope);
|
||||
|
||||
var inputGestureText = new TextBlock
|
||||
{
|
||||
Name = InputGestureTextPart,
|
||||
HorizontalAlignment = HorizontalAlignment.Right,
|
||||
TextAlignment = TextAlignment.Right,
|
||||
VerticalAlignment = VerticalAlignment.Center
|
||||
};
|
||||
Grid.SetColumn(inputGestureText, 2);
|
||||
TokenResourceBinder.CreateTokenBinding(inputGestureText, Layoutable.MarginProperty,
|
||||
NavMenuTokenResourceKey.ItemMargin);
|
||||
CreateTemplateParentBinding(inputGestureText,
|
||||
TextBlock.TextProperty,
|
||||
NavMenuItem.InputGestureProperty,
|
||||
BindingMode.Default,
|
||||
NavMenuItem.KeyGestureConverter);
|
||||
|
||||
inputGestureText.RegisterInNameScope(scope);
|
||||
|
||||
var menuIndicatorIcon = BuildMenuIndicatorIcon();
|
||||
Grid.SetColumn(menuIndicatorIcon, 3);
|
||||
menuIndicatorIcon.RegisterInNameScope(scope);
|
||||
|
||||
layout.Children.Add(iconPresenter);
|
||||
layout.Children.Add(itemTextPresenter);
|
||||
layout.Children.Add(inputGestureText);
|
||||
layout.Children.Add(menuIndicatorIcon);
|
||||
|
||||
headerFrame.Child = layout;
|
||||
return headerFrame;
|
||||
}
|
||||
|
||||
protected virtual void BuildExtraItem(Panel layout, INameScope scope)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -11,25 +11,22 @@ using Avalonia.VisualTree;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
internal class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
{
|
||||
private readonly bool _isContextMenu;
|
||||
private IDisposable? _inputManagerSubscription;
|
||||
private IRenderRoot? _root;
|
||||
|
||||
public DefaultNavMenuInteractionHandler(bool isContextMenu)
|
||||
: this(isContextMenu, AvaloniaLocator.Current.GetService<IInputManager>(), DefaultDelayRun)
|
||||
public DefaultNavMenuInteractionHandler()
|
||||
: this(AvaloniaLocator.Current.GetService<IInputManager>(), DefaultDelayRun)
|
||||
{
|
||||
}
|
||||
|
||||
public DefaultNavMenuInteractionHandler(
|
||||
bool isContextMenu,
|
||||
IInputManager? inputManager,
|
||||
Action<Action, TimeSpan> delayRun)
|
||||
{
|
||||
delayRun = delayRun ?? throw new ArgumentNullException(nameof(delayRun));
|
||||
|
||||
_isContextMenu = isContextMenu;
|
||||
|
||||
InputManager = inputManager;
|
||||
DelayRun = delayRun;
|
||||
}
|
||||
@@ -45,7 +42,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
|
||||
public static TimeSpan MenuShowDelay { get; set; } = TimeSpan.FromMilliseconds(400);
|
||||
|
||||
protected internal virtual void GotFocus(object? sender, GotFocusEventArgs e)
|
||||
protected virtual void GotFocus(object? sender, GotFocusEventArgs e)
|
||||
{
|
||||
var item = GetMenuItemCore(e.Source as Control);
|
||||
|
||||
@@ -55,7 +52,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void LostFocus(object? sender, RoutedEventArgs e)
|
||||
protected virtual void LostFocus(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = GetMenuItemCore(e.Source as Control);
|
||||
|
||||
@@ -65,36 +62,14 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void KeyDown(object? sender, KeyEventArgs e)
|
||||
protected virtual void KeyDown(object? sender, KeyEventArgs e)
|
||||
{
|
||||
KeyDown(GetMenuItemCore(e.Source as Control), e);
|
||||
}
|
||||
|
||||
protected internal virtual void AccessKeyPressed(object? sender, RoutedEventArgs e)
|
||||
protected virtual void PointerEntered(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = GetMenuItemCore(e.Source as Control);
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.HasSubMenu && item.IsEffectivelyEnabled)
|
||||
{
|
||||
Open(item, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Click(item);
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
protected internal virtual void PointerEntered(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = GetMenuItemCore(e.Source as Control);
|
||||
|
||||
if (item?.Parent == null)
|
||||
{
|
||||
return;
|
||||
@@ -136,7 +111,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void PointerMoved(object? sender, PointerEventArgs e)
|
||||
protected virtual void PointerMoved(object? sender, PointerEventArgs e)
|
||||
{
|
||||
// HACK: #8179 needs to be addressed to correctly implement it in the PointerPressed method.
|
||||
var item = GetMenuItemCore(e.Source as Control) as NavMenuItem;
|
||||
@@ -157,7 +132,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void PointerExited(object? sender, RoutedEventArgs e)
|
||||
protected virtual void PointerExited(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
var item = GetMenuItemCore(e.Source as Control);
|
||||
|
||||
@@ -192,7 +167,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void PointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
protected virtual void PointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
var item = GetMenuItemCore(e.Source as Control);
|
||||
|
||||
@@ -211,11 +186,6 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
else
|
||||
{
|
||||
// if (item.IsTopLevel && item.Parent is IMainMenu mainMenu)
|
||||
// {
|
||||
// mainNavMenu.Open();
|
||||
// }
|
||||
|
||||
Open(item, false);
|
||||
}
|
||||
|
||||
@@ -223,7 +193,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void PointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
protected virtual void PointerReleased(object? sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
var item = GetMenuItemCore(e.Source as Control);
|
||||
|
||||
@@ -234,7 +204,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void MenuOpened(object? sender, RoutedEventArgs e)
|
||||
protected virtual void MenuOpened(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (e.Source is NavMenu)
|
||||
{
|
||||
@@ -242,7 +212,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void RawInput(RawInputEventArgs e)
|
||||
protected virtual void RawInput(RawInputEventArgs e)
|
||||
{
|
||||
var mouse = e as RawPointerEventArgs;
|
||||
|
||||
@@ -252,7 +222,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void RootPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
protected virtual void RootPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (NavMenu?.IsOpen == true)
|
||||
{
|
||||
@@ -263,7 +233,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
}
|
||||
|
||||
protected internal virtual void WindowDeactivated(object? sender, EventArgs e)
|
||||
protected virtual void WindowDeactivated(object? sender, EventArgs e)
|
||||
{
|
||||
NavMenu?.Close();
|
||||
}
|
||||
@@ -283,10 +253,9 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
NavMenu.KeyDown += KeyDown;
|
||||
NavMenu.PointerPressed += PointerPressed;
|
||||
NavMenu.PointerReleased += PointerReleased;
|
||||
// NavMenu.AddHandler(AccessKeyHandler.AccessKeyPressedEvent, AccessKeyPressed);
|
||||
NavMenu.AddHandler(MenuBase.OpenedEvent, MenuOpened);
|
||||
NavMenu.AddHandler(MenuItem.PointerEnteredItemEvent, PointerEntered);
|
||||
NavMenu.AddHandler(MenuItem.PointerExitedItemEvent, PointerExited);
|
||||
NavMenu.AddHandler(NavMenuBase.OpenedEvent, MenuOpened);
|
||||
NavMenu.AddHandler(NavMenuItem.PointerEnteredItemEvent, PointerEntered);
|
||||
NavMenu.AddHandler(NavMenuItem.PointerExitedItemEvent, PointerExited);
|
||||
NavMenu.AddHandler(InputElement.PointerMovedEvent, PointerMoved);
|
||||
|
||||
_root = NavMenu.VisualRoot;
|
||||
@@ -302,7 +271,9 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
}
|
||||
|
||||
if (_root is TopLevel tl && tl.PlatformImpl is ITopLevelImpl pimpl)
|
||||
{
|
||||
pimpl.LostFocus += TopLevelLostPlatformFocus;
|
||||
}
|
||||
|
||||
_inputManagerSubscription = InputManager?.Process.Subscribe(RawInput);
|
||||
}
|
||||
@@ -319,10 +290,9 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
NavMenu.KeyDown -= KeyDown;
|
||||
NavMenu.PointerPressed -= PointerPressed;
|
||||
NavMenu.PointerReleased -= PointerReleased;
|
||||
// NavMenu.RemoveHandler(AccessKeyHandler.AccessKeyPressedEvent, AccessKeyPressed);
|
||||
NavMenu.RemoveHandler(MenuBase.OpenedEvent, MenuOpened);
|
||||
NavMenu.RemoveHandler(MenuItem.PointerEnteredItemEvent, PointerEntered);
|
||||
NavMenu.RemoveHandler(MenuItem.PointerExitedItemEvent, PointerExited);
|
||||
NavMenu.RemoveHandler(NavMenuBase.OpenedEvent, MenuOpened);
|
||||
NavMenu.RemoveHandler(NavMenuItem.PointerEnteredItemEvent, PointerEntered);
|
||||
NavMenu.RemoveHandler(NavMenuItem.PointerExitedItemEvent, PointerExited);
|
||||
NavMenu.RemoveHandler(InputElement.PointerMovedEvent, PointerMoved);
|
||||
|
||||
if (_root is InputElement inputRoot)
|
||||
@@ -483,14 +453,7 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
|
||||
if (direction?.IsDirectional() == true)
|
||||
{
|
||||
if (item == null && _isContextMenu)
|
||||
{
|
||||
if (NavMenu!.MoveSelection(direction.Value, true) == true)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
else if (item?.Parent?.MoveSelection(direction.Value, true) == true)
|
||||
if (item?.Parent?.MoveSelection(direction.Value, true) == true)
|
||||
{
|
||||
// If the the parent is an IMenu which successfully moved its selection,
|
||||
// and the current navMenu is open then close the current navMenu and open the
|
||||
@@ -557,9 +520,15 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
while (true)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (item is INavMenuItem menuItem)
|
||||
{
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
item = item.Parent;
|
||||
}
|
||||
}
|
||||
@@ -573,5 +542,4 @@ public class DefaultNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
{
|
||||
DispatcherTimer.RunOnce(action, timeSpan);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ internal interface INavMenu : INavMenuElement, IInputElement
|
||||
/// <summary>
|
||||
/// Gets the menu interaction handler.
|
||||
/// </summary>
|
||||
INavMenuInteractionHandler InteractionHandler { get; }
|
||||
INavMenuInteractionHandler? InteractionHandler { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the menu is open.
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
internal class InlineNavMenuInteractionHandler : INavMenuInteractionHandler
|
||||
{
|
||||
internal INavMenu? NavMenu { get; private set; }
|
||||
|
||||
public void Attach(NavMenuBase navMenu) => AttachCore(navMenu);
|
||||
public void Detach(NavMenuBase navMenu) => DetachCore(navMenu);
|
||||
|
||||
internal void AttachCore(INavMenu navMenu)
|
||||
{
|
||||
if (NavMenu != null)
|
||||
{
|
||||
throw new NotSupportedException("InlineNavMenuInteractionHandler is already attached.");
|
||||
}
|
||||
NavMenu = navMenu;
|
||||
NavMenu.PointerPressed += PointerPressed;
|
||||
}
|
||||
|
||||
internal void DetachCore(INavMenu navMenu)
|
||||
{
|
||||
if (NavMenu != navMenu)
|
||||
{
|
||||
throw new NotSupportedException("InlineNavMenuInteractionHandler is not attached to the navMenu.");
|
||||
}
|
||||
NavMenu.PointerPressed -= PointerPressed;
|
||||
NavMenu = null;
|
||||
}
|
||||
|
||||
protected virtual void PointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
var item = GetMenuItemCore(e.Source as Control);
|
||||
|
||||
if (sender is Visual visual &&
|
||||
e.GetCurrentPoint(visual).Properties.IsLeftButtonPressed)
|
||||
{
|
||||
if (item?.HasSubMenu == true)
|
||||
{
|
||||
if (item.IsSubMenuOpen)
|
||||
{
|
||||
item.Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Open(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NavMenu is NavMenu navMenu)
|
||||
{
|
||||
navMenu.UpdateSelectionFromItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Open(INavMenuItem item)
|
||||
{
|
||||
item.Open();
|
||||
}
|
||||
|
||||
internal static INavMenuItem? GetMenuItemCore(StyledElement? item)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (item is INavMenuItem menuItem)
|
||||
{
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
item = item.Parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,29 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Transformation;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlThemeProvider]
|
||||
internal class InlineNavMenuItemTheme : VerticalNavMenuItemTheme
|
||||
internal class InlineNavMenuItemTheme : BaseNavMenuItemTheme
|
||||
{
|
||||
public new const string ID = "InlineNavMenuItem";
|
||||
public const string MenuIndicatorIconLayoutPart = "PART_MenuIndicatorIconLayout";
|
||||
public const string ChildItemsPresenterPart = "PART_ChildItemsPresenter";
|
||||
public const string ChildItemsLayoutTransformPart = "PART_ChildItemsLayoutTransform";
|
||||
|
||||
public InlineNavMenuItemTheme() : base(typeof(NavMenuItem))
|
||||
{
|
||||
@@ -21,11 +37,128 @@ internal class InlineNavMenuItemTheme : VerticalNavMenuItemTheme
|
||||
protected override Control BuildMenuIndicatorIcon()
|
||||
{
|
||||
var indicatorIcon = base.BuildMenuIndicatorIcon();
|
||||
var layoutTransformControl = new LayoutTransformControl()
|
||||
var menuIndicatorIconPresenter = new ContentPresenter()
|
||||
{
|
||||
Name = MenuIndicatorIconLayoutPart
|
||||
Name = MenuIndicatorIconLayoutPart,
|
||||
Transitions = new Transitions()
|
||||
{
|
||||
AnimationUtils.CreateTransition<TransformOperationsTransition>(ContentPresenter.RenderTransformProperty)
|
||||
}
|
||||
};
|
||||
layoutTransformControl.Child = indicatorIcon;
|
||||
return layoutTransformControl;
|
||||
menuIndicatorIconPresenter.Content = indicatorIcon;
|
||||
return menuIndicatorIconPresenter;
|
||||
}
|
||||
|
||||
protected override Control BuildMenuItemContent(INameScope scope)
|
||||
{
|
||||
var rootLayout = new StackPanel()
|
||||
{
|
||||
Orientation = Orientation.Vertical
|
||||
};
|
||||
var headerContent = base.BuildMenuItemContent(scope);
|
||||
|
||||
TokenResourceBinder.CreateTokenBinding(headerContent, Control.MarginProperty, NavMenuTokenResourceKey.VerticalItemsPanelSpacing, BindingPriority.Template,
|
||||
(v) =>
|
||||
{
|
||||
if (v is double dval)
|
||||
{
|
||||
return new Thickness(0, 0, 0, dval);
|
||||
}
|
||||
|
||||
return new Thickness();
|
||||
});
|
||||
var childItemsLayoutTransform = new LayoutTransformControl()
|
||||
{
|
||||
Name = ChildItemsLayoutTransformPart,
|
||||
};
|
||||
|
||||
var itemsPresenter = new ItemsPresenter
|
||||
{
|
||||
Name = ChildItemsPresenterPart,
|
||||
Focusable = false,
|
||||
};
|
||||
itemsPresenter.RegisterInNameScope(scope);
|
||||
CreateTemplateParentBinding(itemsPresenter, ItemsPresenter.ItemsPanelProperty, NavMenuItem.ItemsPanelProperty);
|
||||
|
||||
childItemsLayoutTransform.Child = itemsPresenter;
|
||||
CreateTemplateParentBinding(itemsPresenter, Visual.IsVisibleProperty, NavMenuItem.IsSubMenuOpenProperty);
|
||||
|
||||
rootLayout.Children.Add(headerContent);
|
||||
rootLayout.Children.Add(childItemsLayoutTransform);
|
||||
return rootLayout;
|
||||
}
|
||||
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
base.BuildStyles();
|
||||
var childItemsPanelStyle = new Style(selector => selector.Nesting().Template().Name(ChildItemsPresenterPart).Child().OfType<StackPanel>());
|
||||
childItemsPanelStyle.Add(StackPanel.SpacingProperty, NavMenuTokenResourceKey.VerticalItemsPanelSpacing);
|
||||
Add(childItemsPanelStyle);
|
||||
|
||||
BuildMenuIndicatorStyle();
|
||||
}
|
||||
|
||||
private void BuildMenuIndicatorStyle()
|
||||
{
|
||||
{
|
||||
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconLayoutPart));
|
||||
var transformOptions = new TransformOperations.Builder(1);
|
||||
transformOptions.AppendRotate(MathUtils.Deg2Rad(90));
|
||||
menuIndicatorStyle.Add(ContentPresenter.RenderTransformProperty, transformOptions.Build());
|
||||
menuIndicatorStyle.Add(Visual.IsVisibleProperty, true);
|
||||
Add(menuIndicatorStyle);
|
||||
}
|
||||
var openSubMenuStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Open));
|
||||
{
|
||||
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconLayoutPart));
|
||||
var transformOptions = new TransformOperations.Builder(1);
|
||||
transformOptions.AppendRotate(MathUtils.Deg2Rad(-90));
|
||||
menuIndicatorStyle.Add(ContentPresenter.RenderTransformProperty, transformOptions.Build());
|
||||
openSubMenuStyle.Add(menuIndicatorStyle);
|
||||
}
|
||||
Add(openSubMenuStyle);
|
||||
var emptySubMenuStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Empty));
|
||||
{
|
||||
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconLayoutPart));
|
||||
menuIndicatorStyle.Add(Visual.IsVisibleProperty, false);
|
||||
emptySubMenuStyle.Add(menuIndicatorStyle);
|
||||
}
|
||||
Add(emptySubMenuStyle);
|
||||
}
|
||||
|
||||
// private void BuildAnimationStyle()
|
||||
// {
|
||||
// var closeSubMenuStyle = new Style(selector => selector.Nesting().Not(selector.Nesting().Class(StdPseudoClass.Open)));
|
||||
// {
|
||||
// var layoutTransformStyle =
|
||||
// new Style(selector => selector.Nesting().Template().Name(ChildItemsLayoutTransformPart));
|
||||
// var slideDownInMotionConfig = MotionFactory.BuildSlideUpOutMotion(TimeSpan.FromMilliseconds(300), new QuadraticEaseIn(),
|
||||
// FillMode.Forward);
|
||||
// foreach (var animation in slideDownInMotionConfig.Animations)
|
||||
// {
|
||||
// layoutTransformStyle.Animations.Add(animation);
|
||||
// }
|
||||
// layoutTransformStyle.Add(LayoutTransformControl.RenderTransformOriginProperty, slideDownInMotionConfig.RenderTransformOrigin);
|
||||
// layoutTransformStyle.Add(LayoutTransformControl.IsVisibleProperty, false);
|
||||
// closeSubMenuStyle.Add(layoutTransformStyle);
|
||||
// }
|
||||
// Add(closeSubMenuStyle);
|
||||
//
|
||||
// var openSubMenuStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Open));
|
||||
// {
|
||||
// var layoutTransformStyle =
|
||||
// new Style(selector => selector.Nesting().Template().Name(ChildItemsLayoutTransformPart));
|
||||
// var slideDownInMotionConfig = MotionFactory.BuildSlideUpInMotion(TimeSpan.FromMilliseconds(300), new QuadraticEaseIn(),
|
||||
// FillMode.Forward);
|
||||
// foreach (var animation in slideDownInMotionConfig.Animations)
|
||||
// {
|
||||
// layoutTransformStyle.Animations.Add(animation);
|
||||
// }
|
||||
//
|
||||
// layoutTransformStyle.Add(LayoutTransformControl.RenderTransformOriginProperty, slideDownInMotionConfig.RenderTransformOrigin);
|
||||
// layoutTransformStyle.Add(LayoutTransformControl.IsVisibleProperty, true);
|
||||
// openSubMenuStyle.Add(layoutTransformStyle);
|
||||
// }
|
||||
// Add(openSubMenuStyle);
|
||||
// }
|
||||
}
|
||||
@@ -101,16 +101,6 @@ public class NavMenu : NavMenuBase
|
||||
UpdatePseudoClasses();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NavMenu"/> class.
|
||||
/// </summary>
|
||||
/// <param name="interactionHandler">The menu interaction handler.</param>
|
||||
public NavMenu(INavMenuInteractionHandler interactionHandler)
|
||||
: base(interactionHandler)
|
||||
{
|
||||
UpdatePseudoClasses();
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (!IsOpen)
|
||||
@@ -158,6 +148,7 @@ public class NavMenu : NavMenuBase
|
||||
if (change.Property == ModeProperty)
|
||||
{
|
||||
SetupItemContainerTheme(true);
|
||||
SetupInteractionHandler(true);
|
||||
}
|
||||
UpdatePseudoClasses();
|
||||
}
|
||||
@@ -173,10 +164,14 @@ public class NavMenu : NavMenuBase
|
||||
element.ClearValue(ItemContainerThemeProperty);
|
||||
}
|
||||
|
||||
if (element is NavMenuItem navMenuItem && Mode == NavMenuMode.Horizontal)
|
||||
if (element is NavMenuItem navMenuItem)
|
||||
{
|
||||
BindUtils.RelayBind(this, ActiveBarHeightProperty, navMenuItem, NavMenuItem.ActiveBarHeightProperty);
|
||||
BindUtils.RelayBind(this, ActiveBarWidthProperty, navMenuItem, NavMenuItem.ActiveBarWidthProperty);
|
||||
if (Mode == NavMenuMode.Horizontal)
|
||||
{
|
||||
BindUtils.RelayBind(this, ActiveBarHeightProperty, navMenuItem, NavMenuItem.ActiveBarHeightProperty);
|
||||
BindUtils.RelayBind(this, ActiveBarWidthProperty, navMenuItem, NavMenuItem.ActiveBarWidthProperty);
|
||||
}
|
||||
BindUtils.RelayBind(this, ModeProperty, navMenuItem, NavMenuItem.ModeProperty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,16 +188,23 @@ public class NavMenu : NavMenuBase
|
||||
{
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
SetupItemContainerTheme();
|
||||
SetupInteractionHandler();
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
|
||||
InteractionHandler?.Attach(this);
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(this, HorizontalBorderThicknessProperty, GlobalTokenResourceKey.LineWidth,
|
||||
BindingPriority.Template,
|
||||
new RenderScaleAwareDoubleConfigure(this));
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
InteractionHandler?.Detach(this);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
@@ -211,6 +213,26 @@ public class NavMenu : NavMenuBase
|
||||
TokenResourceBinder.CreateTokenBinding(this, ActiveBarHeightProperty, NavMenuTokenResourceKey.ActiveBarHeight);
|
||||
}
|
||||
|
||||
private void SetupInteractionHandler(bool needMount = false)
|
||||
{
|
||||
if (needMount)
|
||||
{
|
||||
InteractionHandler?.Detach(this);
|
||||
}
|
||||
if (Mode == NavMenuMode.Inline)
|
||||
{
|
||||
InteractionHandler = new InlineNavMenuInteractionHandler();
|
||||
}
|
||||
else
|
||||
{
|
||||
InteractionHandler = new DefaultNavMenuInteractionHandler();
|
||||
}
|
||||
if (needMount)
|
||||
{
|
||||
InteractionHandler?.Attach(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupItemContainerTheme(bool force = false)
|
||||
{
|
||||
if (ItemContainerTheme is null || force)
|
||||
@@ -231,4 +253,9 @@ public class NavMenu : NavMenuBase
|
||||
TokenResourceBinder.CreateGlobalResourceBinding(this, ItemContainerThemeProperty, resourceKey);
|
||||
}
|
||||
}
|
||||
|
||||
internal void UpdateSelectionFromItem(INavMenuItem? item)
|
||||
{
|
||||
UpdateSelectionFromEventSource(item);
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public abstract class NavMenuBase : SelectingItemsControl, IFocusScope, INavMenu
|
||||
|
||||
#endregion
|
||||
|
||||
INavMenuInteractionHandler INavMenu.InteractionHandler => InteractionHandler;
|
||||
INavMenuInteractionHandler? INavMenu.InteractionHandler => InteractionHandler;
|
||||
|
||||
IRenderRoot? INavMenu.VisualRoot => VisualRoot;
|
||||
|
||||
@@ -87,17 +87,7 @@ public abstract class NavMenuBase : SelectingItemsControl, IFocusScope, INavMenu
|
||||
/// <summary>
|
||||
/// Gets the interaction handler for the menu.
|
||||
/// </summary>
|
||||
protected internal INavMenuInteractionHandler InteractionHandler { get; }
|
||||
|
||||
protected NavMenuBase()
|
||||
{
|
||||
InteractionHandler = new DefaultNavMenuInteractionHandler(false);
|
||||
}
|
||||
|
||||
protected NavMenuBase(INavMenuInteractionHandler interactionHandler)
|
||||
{
|
||||
InteractionHandler = interactionHandler ?? throw new ArgumentNullException(nameof(interactionHandler));
|
||||
}
|
||||
protected internal INavMenuInteractionHandler? InteractionHandler { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Closes the menu.
|
||||
@@ -135,20 +125,6 @@ public abstract class NavMenuBase : SelectingItemsControl, IFocusScope, INavMenu
|
||||
// Don't handle here: let the interaction handler handle it.
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
InteractionHandler.Attach(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
InteractionHandler.Detach(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a submenu opens somewhere in the menu.
|
||||
/// </summary>
|
||||
|
||||
@@ -236,6 +236,11 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
o => o.PopupMinWidth,
|
||||
(o, v) => o.PopupMinWidth = v);
|
||||
|
||||
internal static readonly DirectProperty<NavMenuItem, NavMenuMode> ModeProperty =
|
||||
AvaloniaProperty.RegisterDirect<NavMenuItem, NavMenuMode>(nameof(Mode),
|
||||
o => o.Mode,
|
||||
(o, v) => o.Mode = v);
|
||||
|
||||
public double ActiveBarWidth
|
||||
{
|
||||
get => GetValue(ActiveBarWidthProperty);
|
||||
@@ -268,6 +273,13 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
get => _popupMinWidth;
|
||||
set => SetAndRaise(PopupMinWidthProperty, ref _popupMinWidth, value);
|
||||
}
|
||||
|
||||
private NavMenuMode _mode;
|
||||
public NavMenuMode Mode
|
||||
{
|
||||
get => _mode;
|
||||
set => SetAndRaise(ModeProperty, ref _mode, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -371,6 +383,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
private KeyGesture? _hotkey;
|
||||
private bool _isEmbeddedInMenu;
|
||||
private Border? _horizontalFrame;
|
||||
private IDisposable? _itemContainerThemeDisposable;
|
||||
|
||||
static NavMenuItem()
|
||||
{
|
||||
@@ -721,6 +734,9 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
else if (change.Property == IconProperty)
|
||||
{
|
||||
SetupItemIcon();
|
||||
} else if (change.Property == ModeProperty)
|
||||
{
|
||||
SetupItemContainerTheme(true);
|
||||
}
|
||||
|
||||
if (change.Property == BoundsProperty ||
|
||||
@@ -728,6 +744,7 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
{
|
||||
SetupEffectivePopupMinWidth();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SetupItemIcon()
|
||||
@@ -918,4 +935,16 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SetupItemContainerTheme(bool force = false)
|
||||
{
|
||||
if (ItemContainerTheme is null || force)
|
||||
{
|
||||
_itemContainerThemeDisposable?.Dispose();
|
||||
if (Mode == NavMenuMode.Inline)
|
||||
{
|
||||
_itemContainerThemeDisposable = TokenResourceBinder.CreateGlobalResourceBinding(this, ItemContainerThemeProperty, InlineNavMenuItemTheme.ID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,11 +22,11 @@ internal class NavMenuItemTheme : BaseNavMenuItemTheme
|
||||
{
|
||||
}
|
||||
|
||||
protected override void BuildExtraItem(Grid containerLayout, INameScope scope)
|
||||
protected override void BuildExtraItem(Panel layout, INameScope scope)
|
||||
{
|
||||
var popup = CreateMenuPopup();
|
||||
popup.RegisterInNameScope(scope);
|
||||
containerLayout.Children.Add(popup);
|
||||
layout.Children.Add(popup);
|
||||
}
|
||||
|
||||
protected Popup CreateMenuPopup()
|
||||
|
||||
@@ -185,6 +185,11 @@ internal class NavMenuToken : AbstractControlDesignToken
|
||||
/// </summary>
|
||||
public Thickness ItemContentPadding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 垂直面板的元素间距
|
||||
/// </summary>
|
||||
public double VerticalItemsPanelSpacing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 菜单项内部元素边距
|
||||
/// </summary>
|
||||
@@ -436,9 +441,10 @@ internal class NavMenuToken : AbstractControlDesignToken
|
||||
MenuPopupMaxHeight = ItemHeight * 30;
|
||||
TopLevelItemPopupMarginToAnchor = _globalToken.MarginXXS;
|
||||
|
||||
MenuPopupBg = _globalToken.ColorBgElevated;
|
||||
MenuPopupBorderRadius = _globalToken.BorderRadiusLG;
|
||||
MenuPopupContentPadding = new Thickness(_globalToken.PaddingXXS, MenuPopupBorderRadius.TopLeft / 2);
|
||||
MenuPopupBoxShadows = _globalToken.BoxShadowsSecondary;
|
||||
MenuPopupBg = _globalToken.ColorBgElevated;
|
||||
MenuPopupBorderRadius = _globalToken.BorderRadiusLG;
|
||||
MenuPopupContentPadding = new Thickness(_globalToken.PaddingXXS, MenuPopupBorderRadius.TopLeft / 2);
|
||||
MenuPopupBoxShadows = _globalToken.BoxShadowsSecondary;
|
||||
VerticalItemsPanelSpacing = _globalToken.MarginXXS;
|
||||
}
|
||||
}
|
||||
@@ -175,7 +175,7 @@ internal class TopLevelHorizontalNavMenuItemTheme : BaseControlTheme
|
||||
TokenResourceBinder.CreateTokenBinding(popup, Popup.MaskShadowsProperty,
|
||||
MenuTokenResourceKey.MenuPopupBoxShadows);
|
||||
|
||||
CreateTemplateParentBinding(popup, Avalonia.Controls.Primitives.Popup.IsOpenProperty,
|
||||
CreateTemplateParentBinding(popup, Popup.IsOpenProperty,
|
||||
NavMenuItem.IsSubMenuOpenProperty, BindingMode.TwoWay);
|
||||
|
||||
return popup;
|
||||
|
||||
@@ -36,11 +36,32 @@ public static partial class MotionFactory
|
||||
var scaleYSetter = new Setter
|
||||
{
|
||||
Property = ScaleTransform.ScaleYProperty,
|
||||
Value = 0.8
|
||||
Value = 0.1
|
||||
};
|
||||
startFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
animation.Children.Add(startFrame);
|
||||
|
||||
var middleFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.9)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 0.2
|
||||
};
|
||||
middleFrame.Setters.Add(opacitySetter);
|
||||
|
||||
var scaleYSetter = new Setter
|
||||
{
|
||||
Property = ScaleTransform.ScaleYProperty,
|
||||
Value = 0.9
|
||||
};
|
||||
middleFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
animation.Children.Add(middleFrame);
|
||||
|
||||
var endFrame = new KeyFrame
|
||||
{
|
||||
@@ -100,6 +121,27 @@ public static partial class MotionFactory
|
||||
startFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
animation.Children.Add(startFrame);
|
||||
|
||||
var middleFrame = new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0.9)
|
||||
};
|
||||
{
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 0.2
|
||||
};
|
||||
middleFrame.Setters.Add(opacitySetter);
|
||||
|
||||
var scaleYSetter = new Setter
|
||||
{
|
||||
Property = ScaleTransform.ScaleYProperty,
|
||||
Value = 0.9
|
||||
};
|
||||
middleFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
animation.Children.Add(middleFrame);
|
||||
|
||||
var endFrame = new KeyFrame
|
||||
{
|
||||
@@ -115,7 +157,7 @@ public static partial class MotionFactory
|
||||
var scaleYSetter = new Setter
|
||||
{
|
||||
Property = ScaleTransform.ScaleYProperty,
|
||||
Value = 0.8
|
||||
Value = 0.0
|
||||
};
|
||||
endFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
@@ -154,7 +196,7 @@ public static partial class MotionFactory
|
||||
var scaleYSetter = new Setter
|
||||
{
|
||||
Property = ScaleTransform.ScaleYProperty,
|
||||
Value = 0.8
|
||||
Value = 0.1
|
||||
};
|
||||
startFrame.Setters.Add(scaleYSetter);
|
||||
}
|
||||
@@ -168,7 +210,7 @@ public static partial class MotionFactory
|
||||
var opacitySetter = new Setter
|
||||
{
|
||||
Property = Visual.OpacityProperty,
|
||||
Value = 1.0
|
||||
Value = 0.2
|
||||
};
|
||||
endFrame.Setters.Add(opacitySetter);
|
||||
var scaleYSetter = new Setter
|
||||
|
||||
Reference in New Issue
Block a user