NavMenuPopup menu item style completed

This commit is contained in:
polarboy
2024-09-23 10:02:57 +08:00
parent d06ed4af80
commit 3cfbaa439d
7 changed files with 453 additions and 45 deletions
@@ -370,12 +370,20 @@ namespace AtomUI.Theme.Styling
public static class NavMenuTokenResourceKey
{
public static readonly TokenResourceKey PopupMinWidth = new TokenResourceKey("NavMenu.PopupMinWidth", "AtomUI.Token");
public static readonly TokenResourceKey MenuPopupBorderRadius = new TokenResourceKey("NavMenu.MenuPopupBorderRadius", "AtomUI.Token");
public static readonly TokenResourceKey MenuPopupBoxShadows = new TokenResourceKey("NavMenu.MenuPopupBoxShadows", "AtomUI.Token");
public static readonly TokenResourceKey MenuPopupContentPadding = new TokenResourceKey("NavMenu.MenuPopupContentPadding", "AtomUI.Token");
public static readonly TokenResourceKey MenuPopupMinWidth = new TokenResourceKey("NavMenu.MenuPopupMinWidth", "AtomUI.Token");
public static readonly TokenResourceKey MenuPopupMaxWidth = new TokenResourceKey("NavMenu.MenuPopupMaxWidth", "AtomUI.Token");
public static readonly TokenResourceKey MenuPopupMinHeight = new TokenResourceKey("NavMenu.MenuPopupMinHeight", "AtomUI.Token");
public static readonly TokenResourceKey MenuPopupMaxHeight = new TokenResourceKey("NavMenu.MenuPopupMaxHeight", "AtomUI.Token");
public static readonly TokenResourceKey TopLevelItemPopupMarginToAnchor = new TokenResourceKey("NavMenu.TopLevelItemPopupMarginToAnchor", "AtomUI.Token");
public static readonly TokenResourceKey GroupTitleColor = new TokenResourceKey("NavMenu.GroupTitleColor", "AtomUI.Token");
public static readonly TokenResourceKey GroupTitleLineHeight = new TokenResourceKey("NavMenu.GroupTitleLineHeight", "AtomUI.Token");
public static readonly TokenResourceKey GroupTitleFontSize = new TokenResourceKey("NavMenu.GroupTitleFontSize", "AtomUI.Token");
public static readonly TokenResourceKey ItemBorderRadius = new TokenResourceKey("NavMenu.ItemBorderRadius", "AtomUI.Token");
public static readonly TokenResourceKey SubMenuItemBorderRadius = new TokenResourceKey("NavMenu.SubMenuItemBorderRadius", "AtomUI.Token");
public static readonly TokenResourceKey KeyGestureColor = new TokenResourceKey("NavMenu.KeyGestureColor", "AtomUI.Token");
public static readonly TokenResourceKey ItemColor = new TokenResourceKey("NavMenu.ItemColor", "AtomUI.Token");
public static readonly TokenResourceKey ItemHoverColor = new TokenResourceKey("NavMenu.ItemHoverColor", "AtomUI.Token");
public static readonly TokenResourceKey HorizontalItemHoverColor = new TokenResourceKey("NavMenu.HorizontalItemHoverColor", "AtomUI.Token");
@@ -396,19 +404,20 @@ namespace AtomUI.Theme.Styling
public static readonly TokenResourceKey HorizontalItemSelectedBg = new TokenResourceKey("NavMenu.HorizontalItemSelectedBg", "AtomUI.Token");
public static readonly TokenResourceKey ActiveBarWidth = new TokenResourceKey("NavMenu.ActiveBarWidth", "AtomUI.Token");
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 ItemMargin = new TokenResourceKey("NavMenu.ItemMargin", "AtomUI.Token");
public static readonly TokenResourceKey HorizontalItemMargin = new TokenResourceKey("NavMenu.HorizontalItemMargin", "AtomUI.Token");
public static readonly TokenResourceKey ItemPadding = new TokenResourceKey("NavMenu.ItemPadding", "AtomUI.Token");
public static readonly TokenResourceKey HorizontalItemHoverBg = new TokenResourceKey("NavMenu.HorizontalItemHoverBg", "AtomUI.Token");
public static readonly TokenResourceKey HorizontalItemBorderRadius = new TokenResourceKey("NavMenu.HorizontalItemBorderRadius", "AtomUI.Token");
public static readonly TokenResourceKey ItemHeight = new TokenResourceKey("NavMenu.ItemHeight", "AtomUI.Token");
public static readonly TokenResourceKey CollapsedWidth = new TokenResourceKey("NavMenu.CollapsedWidth", "AtomUI.Token");
public static readonly TokenResourceKey PopupBg = new TokenResourceKey("NavMenu.PopupBg", "AtomUI.Token");
public static readonly TokenResourceKey MenuPopupBg = new TokenResourceKey("NavMenu.MenuPopupBg", "AtomUI.Token");
public static readonly TokenResourceKey HorizontalLineHeight = new TokenResourceKey("NavMenu.HorizontalLineHeight", "AtomUI.Token");
public static readonly TokenResourceKey IconMargin = new TokenResourceKey("NavMenu.IconMargin", "AtomUI.Token");
public static readonly TokenResourceKey IconSize = new TokenResourceKey("NavMenu.IconSize", "AtomUI.Token");
public static readonly TokenResourceKey CollapsedIconSize = new TokenResourceKey("NavMenu.CollapsedIconSize", "AtomUI.Token");
public static readonly TokenResourceKey DarkPopupBg = new TokenResourceKey("NavMenu.DarkPopupBg", "AtomUI.Token");
public static readonly TokenResourceKey DarkMenuPopupBg = new TokenResourceKey("NavMenu.DarkMenuPopupBg", "AtomUI.Token");
public static readonly TokenResourceKey DarkItemColor = new TokenResourceKey("NavMenu.DarkItemColor", "AtomUI.Token");
public static readonly TokenResourceKey DarkDangerItemColor = new TokenResourceKey("NavMenu.DarkDangerItemColor", "AtomUI.Token");
public static readonly TokenResourceKey DarkItemBg = new TokenResourceKey("NavMenu.DarkItemBg", "AtomUI.Token");
+17 -1
View File
@@ -4,6 +4,7 @@ using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Converters;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Mixins;
using Avalonia.Controls.Primitives;
@@ -353,6 +354,8 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
private EventHandler CanExecuteChangedHandler => _canExecuteChangeHandler ??= new(CanExecuteChanged);
#endregion
internal static PlatformKeyGestureConverter KeyGestureConverter = new();
/// <summary>
/// The default value for the <see cref="ItemsControl.ItemsPanel"/> property.
@@ -563,7 +566,8 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
}
_horizontalFrame = e.NameScope.Find<Border>(TopLevelHorizontalNavMenuItemTheme.FramePart);
TokenResourceBinder.CreateTokenBinding(this, PopupMinWidthProperty, NavMenuTokenResourceKey.PopupMinWidth);
TokenResourceBinder.CreateTokenBinding(this, PopupMinWidthProperty, NavMenuTokenResourceKey.MenuPopupMinWidth);
SetupItemIcon();
}
protected override void UpdateDataValidation(
@@ -712,6 +716,10 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
{
SetupHorizontalEffectiveIndicatorWidth();
}
else if (change.Property == IconProperty)
{
SetupItemIcon();
}
if (change.Property == BoundsProperty ||
change.Property == PopupMinWidthProperty)
@@ -720,6 +728,14 @@ public class NavMenuItem : HeaderedSelectingItemsControl,
}
}
private void SetupItemIcon()
{
if (Icon is not null && Icon is PathIcon menuItemIcon)
{
menuItemIcon.Name = ThemeConstants.ItemIconPart;
}
}
private void SetupHorizontalEffectiveIndicatorWidth()
{
var width = Bounds.Width;
+279 -2
View File
@@ -1,21 +1,298 @@
using AtomUI.Theme;
using AtomUI.Icon;
using AtomUI.Media;
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Animation;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Styling;
namespace AtomUI.Controls;
[ControlThemeProvider]
internal class NavMenuItemTheme : BaseControlTheme
{
public const string ItemDecoratorPart = "PART_ItemDecorator";
public const string MainContainerPart = "PART_MainContainer";
public const string ItemIconPresenterPart = "PART_ItemIconPresenter";
public const string ItemTextPresenterPart = "PART_ItemTextPresenter";
public const string InputGestureTextPart = "PART_InputGestureText";
public const string MenuIndicatorIconPart = "PART_MenuIndicatorIcon";
public const string PopupPart = "PART_Popup";
public const string ItemsPresenterPart = "PART_ItemsPresenter";
public NavMenuItemTheme()
: base(typeof(NavMenuItem))
{
}
protected override IControlTemplate BuildControlTemplate()
{
return new FuncControlTemplate<NavMenuItem>((item, scope) =>
{
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 = new PathIcon
{
Name = MenuIndicatorIconPart,
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Center,
Kind = "RightOutlined"
};
TokenResourceBinder.CreateGlobalTokenBinding(menuIndicatorIcon, Layoutable.WidthProperty,
GlobalTokenResourceKey.IconSizeXS);
TokenResourceBinder.CreateGlobalTokenBinding(menuIndicatorIcon, Layoutable.HeightProperty,
GlobalTokenResourceKey.IconSizeXS);
Grid.SetColumn(menuIndicatorIcon, 3);
menuIndicatorIcon.RegisterInNameScope(scope);
var popup = CreateMenuPopup();
popup.RegisterInNameScope(scope);
layout.Children.Add(iconPresenter);
layout.Children.Add(itemTextPresenter);
layout.Children.Add(inputGestureText);
layout.Children.Add(menuIndicatorIcon);
layout.Children.Add(popup);
container.Child = layout;
layoutWrapper.Children.Add(container);
return layoutWrapper;
});
}
private Popup CreateMenuPopup()
{
var popup = new Popup
{
Name = PopupPart,
WindowManagerAddShadowHint = false,
IsLightDismissEnabled = false,
Placement = PlacementMode.RightEdgeAlignedTop
};
var border = new Border();
TokenResourceBinder.CreateTokenBinding(border, Border.BackgroundProperty,
GlobalTokenResourceKey.ColorBgContainer);
TokenResourceBinder.CreateTokenBinding(border, Border.CornerRadiusProperty,
NavMenuTokenResourceKey.MenuPopupBorderRadius);
TokenResourceBinder.CreateTokenBinding(border, Layoutable.MinWidthProperty,
NavMenuTokenResourceKey.MenuPopupMinWidth);
TokenResourceBinder.CreateTokenBinding(border, Layoutable.MaxWidthProperty,
NavMenuTokenResourceKey.MenuPopupMaxWidth);
TokenResourceBinder.CreateTokenBinding(border, Layoutable.MinHeightProperty,
NavMenuTokenResourceKey.MenuPopupMinHeight);
TokenResourceBinder.CreateTokenBinding(border, Layoutable.MaxHeightProperty,
NavMenuTokenResourceKey.MenuPopupMaxHeight);
TokenResourceBinder.CreateTokenBinding(border, Decorator.PaddingProperty,
NavMenuTokenResourceKey.MenuPopupContentPadding);
var scrollViewer = new MenuScrollViewer();
var itemsPresenter = new ItemsPresenter
{
Name = ItemsPresenterPart
};
CreateTemplateParentBinding(itemsPresenter, ItemsPresenter.ItemsPanelProperty, ItemsControl.ItemsPanelProperty);
Grid.SetIsSharedSizeScope(itemsPresenter, true);
scrollViewer.Content = itemsPresenter;
border.Child = scrollViewer;
popup.Child = border;
TokenResourceBinder.CreateTokenBinding(popup, Popup.MarginToAnchorProperty,
NavMenuTokenResourceKey.TopLevelItemPopupMarginToAnchor);
TokenResourceBinder.CreateTokenBinding(popup, Popup.MaskShadowsProperty,
NavMenuTokenResourceKey.MenuPopupBoxShadows);
CreateTemplateParentBinding(popup, Avalonia.Controls.Primitives.Popup.IsOpenProperty,
NavMenuItem.IsSubMenuOpenProperty, BindingMode.TwoWay);
return popup;
}
protected override void BuildStyles()
{
BuildCommonStyle();
BuildMenuIndicatorStyle();
BuildMenuIconStyle();
BuildDisabledStyle();
}
private void BuildCommonStyle()
{
var commonStyle = new Style(selector => selector.Nesting());
commonStyle.Add(TemplatedControl.ForegroundProperty, NavMenuTokenResourceKey.ItemColor);
{
var keyGestureStyle = new Style(selector => selector.Nesting().Template().Name(InputGestureTextPart));
keyGestureStyle.Add(TextBlock.ForegroundProperty, NavMenuTokenResourceKey.KeyGestureColor);
commonStyle.Add(keyGestureStyle);
}
{
var borderStyle = new Style(selector => selector.Nesting().Template().Name(ItemDecoratorPart));
borderStyle.Add(Layoutable.MinHeightProperty, NavMenuTokenResourceKey.ItemHeight);
borderStyle.Add(Decorator.PaddingProperty, NavMenuTokenResourceKey.ItemContentPadding);
borderStyle.Add(Border.BackgroundProperty, NavMenuTokenResourceKey.ItemBg);
borderStyle.Add(Border.CornerRadiusProperty, NavMenuTokenResourceKey.ItemBorderRadius);
commonStyle.Add(borderStyle);
}
// Hover 状态
var hoverStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.PointerOver));
hoverStyle.Add(TemplatedControl.ForegroundProperty, NavMenuTokenResourceKey.ItemHoverColor);
{
var borderStyle = new Style(selector => selector.Nesting().Template().Name(ItemDecoratorPart));
borderStyle.Add(Border.BackgroundProperty, NavMenuTokenResourceKey.ItemHoverBg);
hoverStyle.Add(borderStyle);
}
commonStyle.Add(hoverStyle);
Add(commonStyle);
}
private void BuildMenuIndicatorStyle()
{
{
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconPart));
menuIndicatorStyle.Add(Visual.IsVisibleProperty, true);
Add(menuIndicatorStyle);
}
var hasSubMenuStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Empty));
{
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconPart));
menuIndicatorStyle.Add(Visual.IsVisibleProperty, false);
hasSubMenuStyle.Add(menuIndicatorStyle);
}
Add(hasSubMenuStyle);
}
private void BuildMenuIconStyle()
{
{
var iconViewBoxStyle = new Style(selector => selector.Nesting().Template().Name(ItemIconPresenterPart));
iconViewBoxStyle.Add(Visual.IsVisibleProperty, false);
Add(iconViewBoxStyle);
}
var hasIconStyle = new Style(selector => selector.Nesting().Class(":icon"));
{
var iconViewBoxStyle = new Style(selector => selector.Nesting().Template().Name(ItemIconPresenterPart));
iconViewBoxStyle.Add(Visual.IsVisibleProperty, true);
hasIconStyle.Add(iconViewBoxStyle);
}
Add(hasIconStyle);
}
private void BuildDisabledStyle()
{
var disabledStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Disabled));
disabledStyle.Add(TemplatedControl.ForegroundProperty, NavMenuTokenResourceKey.ItemDisabledColor);
Add(disabledStyle);
}
protected override void BuildInstanceStyles(Control control)
{
var iconStyle = new Style(selector => selector.Name(ThemeConstants.ItemIconPart));
iconStyle.Add(PathIcon.WidthProperty, NavMenuTokenResourceKey.ItemIconSize);
iconStyle.Add(PathIcon.HeightProperty, NavMenuTokenResourceKey.ItemIconSize);
iconStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorText);
iconStyle.Add(PathIcon.DisabledFilledBrushProperty, NavMenuTokenResourceKey.ItemDisabledColor);
iconStyle.Add(PathIcon.SelectedFilledBrushProperty, GlobalTokenResourceKey.ColorPrimary);
control.Styles.Add(iconStyle);
var disabledIconStyle = new Style(selector => selector.OfType<PathIcon>().Class(StdPseudoClass.Disabled));
disabledIconStyle.Add(PathIcon.IconModeProperty, IconMode.Disabled);
control.Styles.Add(disabledIconStyle);
}
}
+86 -30
View File
@@ -11,9 +11,44 @@ internal class NavMenuToken : AbstractControlDesignToken
public const string ID = "NavMenu";
/// <summary>
/// 弹出菜单的宽度
/// 菜单的圆角
/// </summary>
public double PopupMinWidth { get; set; }
public CornerRadius MenuPopupBorderRadius { get; set; }
/// <summary>
/// 菜单 Popup 阴影
/// </summary>
public BoxShadows MenuPopupBoxShadows { get; set; }
/// <summary>
/// 菜单内容边距
/// </summary>
public Thickness MenuPopupContentPadding { get; set; }
/// <summary>
/// 菜单 Popup 最小宽度
/// </summary>
public double MenuPopupMinWidth { get; set; }
/// <summary>
/// 菜单 Popup 最大宽度
/// </summary>
public double MenuPopupMaxWidth { get; set; }
/// <summary>
/// 菜单 Popup 最小高度
/// </summary>
public double MenuPopupMinHeight { get; set; }
/// <summary>
/// 菜单 Popup 最大高度
/// </summary>
public double MenuPopupMaxHeight { get; set; }
/// <summary>
/// 顶层弹出菜单,距离顶层菜单项的边距
/// </summary>
public double TopLevelItemPopupMarginToAnchor { get; set; }
/// <summary>
/// 分组标题文字颜色
@@ -40,6 +75,11 @@ internal class NavMenuToken : AbstractControlDesignToken
/// </summary>
public CornerRadius SubMenuItemBorderRadius { get; set; }
/// <summary>
/// 快捷键颜色
/// </summary>
public Color KeyGestureColor { get; set; }
/// <summary>
/// 菜单项文字颜色
/// </summary>
@@ -143,6 +183,16 @@ internal class NavMenuToken : AbstractControlDesignToken
/// <summary>
/// 菜单项外间距
/// </summary>
public Thickness ItemContentMargin { get; set; }
/// <summary>
/// 菜单项横向内间距
/// </summary>
public Thickness ItemContentPadding { get; set; }
/// <summary>
/// 菜单项内部元素边距
/// </summary>
public Thickness ItemMargin { get; set; }
/// <summary>
@@ -150,11 +200,6 @@ internal class NavMenuToken : AbstractControlDesignToken
/// </summary>
public Thickness HorizontalItemMargin { get; set; }
/// <summary>
/// 菜单项横向内间距
/// </summary>
public Thickness ItemPadding { get; set; }
/// <summary>
/// 横向菜单项横悬浮态背景色
/// </summary>
@@ -178,7 +223,7 @@ internal class NavMenuToken : AbstractControlDesignToken
/// <summary>
/// 弹出框背景色
/// </summary>
public Color PopupBg { get; set; }
public Color MenuPopupBg { get; set; }
/// <summary>
/// 横向菜单行高
@@ -204,7 +249,7 @@ internal class NavMenuToken : AbstractControlDesignToken
/// <summary>
/// 暗色模式下的浮层菜单的背景颜色
/// </summary>
public Color DarkPopupBg { get; set; }
public Color DarkMenuPopupBg { get; set; }
/// <summary>
/// 暗色模式下的菜单项文字颜色
@@ -315,15 +360,13 @@ internal class NavMenuToken : AbstractControlDesignToken
var activeBarHeight = !double.IsNaN(ActiveBarHeight)
? ActiveBarHeight
: _globalToken.LineWidthBold;
var itemMargin = ItemMargin != default ? ItemMargin : new Thickness(_globalToken.MarginXXS, _globalToken.MarginXXS);
var itemContentMargin = ItemContentMargin != default ? ItemContentMargin : new Thickness(_globalToken.MarginXXS, _globalToken.MarginXXS);
var colorTextDark = ColorUtils.FromRgbF(
0.65d,
colorTextLightSolid.GetRedF(),
colorTextLightSolid.GetGreenF(),
colorTextLightSolid.GetBlueF());
PopupMinWidth = 160d;
ItemBorderRadius = _globalToken.BorderRadiusLG;
SubMenuItemBorderRadius = _globalToken.BorderRadiusSM;
ItemColor = _globalToken.ColorText;
@@ -351,19 +394,18 @@ internal class NavMenuToken : AbstractControlDesignToken
DangerItemActiveBg = _globalToken.ColorError;
DangerItemSelectedBg = _globalToken.ColorError;
ItemMargin = itemMargin;
HorizontalItemBorderRadius = new CornerRadius(0);
HorizontalItemHoverBg = Colors.Transparent;
ItemHeight = _globalToken.ControlHeightLG;
GroupTitleLineHeight = _globalToken.ControlHeight;
CollapsedWidth = _globalToken.ControlHeightLG * 2;
PopupBg = _globalToken.ColorBgElevated;
ItemPadding = new Thickness(_globalToken.Padding, 0);
HorizontalLineHeight = _globalToken.ControlHeightLG * 1.15;
IconSize = _globalToken.FontSize;
IconMargin = new Thickness(0, 0, _globalToken.ControlHeightSM - _globalToken.FontSize, 0);
CollapsedIconSize = _globalToken.FontSizeLG;
GroupTitleFontSize = _globalToken.FontSize;
KeyGestureColor = _globalToken.ColorTextSecondary;
ItemContentMargin = itemContentMargin;
ItemContentPadding = new Thickness(_globalToken.Padding, _globalToken.PaddingXXS);
ItemMargin = new Thickness(0, 0, _globalToken.MarginXXS, 0);
ItemHeight = _globalToken.ControlHeight;
GroupTitleLineHeight = _globalToken.ControlHeight;
CollapsedWidth = _globalToken.ControlHeight * 2;
IconSize = _globalToken.FontSize;
IconMargin = new Thickness(0, 0, _globalToken.ControlHeightSM - _globalToken.FontSize, 0);
CollapsedIconSize = _globalToken.FontSizeLG;
GroupTitleFontSize = _globalToken.FontSize;
// Disabled
DarkItemDisabledColor = ColorUtils.FromRgbF(0.25d,
@@ -375,7 +417,7 @@ internal class NavMenuToken : AbstractControlDesignToken
DarkItemColor = colorTextDark;
DarkDangerItemColor = _globalToken.ColorError;
DarkItemBg = Color.Parse("#001529");
DarkPopupBg = Color.Parse("#001529");
DarkMenuPopupBg = Color.Parse("#001529");
DarkSubMenuItemBg = Color.Parse("#000c17");
DarkItemSelectedColor = colorTextLightSolid;
@@ -388,13 +430,27 @@ internal class NavMenuToken : AbstractControlDesignToken
DarkDangerItemSelectedColor = colorTextLightSolid;
DarkDangerItemActiveBg = _globalToken.ColorError;
MenuHorizontalHeight = _globalToken.ControlHeightLG * 1.15;
HorizontalItemMargin = new Thickness(_globalToken.Padding, 0);
MenuHorizontalHeight = _globalToken.ControlHeightLG * 1.15;
HorizontalItemMargin = new Thickness(_globalToken.Padding, 0);
HorizontalLineHeight = _globalToken.ControlHeightLG * 1.15;
HorizontalItemBorderRadius = new CornerRadius(0);
HorizontalItemHoverBg = Colors.Transparent;
MenuArrowSize = _globalToken.FontSize / 7 * 5;
MenuArrowOffset = MenuArrowSize * 0.25;
MenuSubMenuBg = _globalToken.ColorBgElevated;
ItemIconSize = _globalToken.IconSize;
MenuPopupMinWidth = 160d;
MenuPopupMaxWidth = 800d;
MenuPopupMinHeight = ItemHeight * 3;
MenuPopupMaxHeight = ItemHeight * 30;
TopLevelItemPopupMarginToAnchor = _globalToken.MarginXXS;
MenuPopupBg = _globalToken.ColorBgElevated;
MenuPopupBorderRadius = _globalToken.BorderRadiusLG;
MenuPopupContentPadding = new Thickness(_globalToken.PaddingXXS, MenuPopupBorderRadius.TopLeft / 2);
MenuPopupBoxShadows = _globalToken.BoxShadowsSecondary;
}
}
@@ -3,4 +3,10 @@
internal static class ThemeConstants
{
public const string PopupPart = "PART_Popup";
public const string ItemIconPart = "PART_ItemIcon";
// 菜单项 SizeGridName
public const string IconPresenterSizeGroup = "IconPresenter";
public const string InputGestureTextSizeGroup = "InputGestureText";
public const string MenuIndicatorIconSizeGroup = "MenuIndicatorIcon";
}
@@ -135,7 +135,7 @@ internal class TopLevelHorizontalNavMenuItemTheme : BaseControlTheme
{
Name = PopupPart,
WindowManagerAddShadowHint = false,
IsLightDismissEnabled = true,
IsLightDismissEnabled = false,
Placement = PlacementMode.BottomEdgeAlignedLeft
};
@@ -229,7 +229,7 @@ internal class TopLevelHorizontalNavMenuItemTheme : BaseControlTheme
protected override void BuildInstanceStyles(Control control)
{
var iconStyle = new Style(selector => selector.OfType<PathIcon>());
var iconStyle = new Style(selector => selector.Name(ThemeConstants.ItemIconPart));
iconStyle.Add(PathIcon.WidthProperty, NavMenuTokenResourceKey.ItemIconSize);
iconStyle.Add(PathIcon.HeightProperty, NavMenuTokenResourceKey.ItemIconSize);
iconStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorText);
+50 -6
View File
@@ -6,8 +6,11 @@ using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Diagnostics;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.Media;
@@ -64,6 +67,7 @@ public class Popup : AvaloniaPopup
private PopupShadowLayer? _shadowLayer;
private CompositeDisposable? _compositeDisposable;
private IDisposable? _selfLightDismissDisposable;
private bool _initialized;
private ManagedPopupPositionerInfo? _managedPopupPositioner;
protected bool _animating;
@@ -77,13 +81,14 @@ public class Popup : AvaloniaPopup
AffectsMeasure<Popup>(PlacementProperty);
AffectsMeasure<Popup>(PlacementAnchorProperty);
AffectsMeasure<Popup>(PlacementGravityProperty);
IsLightDismissEnabledProperty.OverrideDefaultValue<Popup>(false);
}
public Popup()
{
IsLightDismissEnabled = false;
Closed += HandleClosed;
Opened += HandleOpened;
Closed += HandleClosed;
Opened += HandleOpened;
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
@@ -124,7 +129,9 @@ public class Popup : AvaloniaPopup
VerticalOffset = offsetY;
_compositeDisposable?.Dispose();
_shadowLayer = null;
_selfLightDismissDisposable?.Dispose();
_firstDetected = true;
_shadowLayer = null;
}
private void HandleOpened(object? sender, EventArgs? args)
@@ -160,6 +167,41 @@ public class Popup : AvaloniaPopup
{
CreateShadowLayer();
}
// 如果没有启动,我们使用自己的处理函数,一版是为了增加我们自己的动画效果
if (!IsLightDismissEnabled)
{
var inputManager = AvaloniaLocator.Current.GetService<IInputManager>()!;
_selfLightDismissDisposable = inputManager.Process.Subscribe(HandleMouseClick);
}
}
}
private bool _firstDetected = true;
private void HandleMouseClick(RawInputEventArgs args)
{
if (!IsOpen)
{
return;
}
if (args is RawPointerEventArgs pointerEventArgs)
{
if (pointerEventArgs.Type == RawPointerEventType.LeftButtonUp)
{
if (_firstDetected)
{
_firstDetected = false;
return;
}
if (this is IPopupHostProvider popupHostProvider)
{
if (popupHostProvider.PopupHost != pointerEventArgs.Root)
{
CloseAnimation();
}
}
}
}
}
@@ -270,6 +312,7 @@ public class Popup : AvaloniaPopup
?? new Rect(0, 0, double.MaxValue, double.MaxValue);
}
// TODO review 后可能需要删除
private static IReadOnlyList<ManagedPopupPositionerScreenInfo> GetScreenInfos(TopLevel topLevel)
{
if (topLevel is WindowBase window)
@@ -280,10 +323,11 @@ public class Popup : AvaloniaPopup
new ManagedPopupPositionerScreenInfo(s.Bounds.ToRect(1), s.WorkingArea.ToRect(1)))
.ToArray();
}
return Array.Empty<ManagedPopupPositionerScreenInfo>();
}
// TODO review 后可能需要删除
private static Rect GetParentClientAreaScreenGeometry(TopLevel topLevel)
{
// Popup positioner operates with abstract coordinates, but in our case they are pixel ones