mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-29 18:38:16 +08:00
完成 Popup 菜单分割控件
This commit is contained in:
parent
198a40617c
commit
44d61f86b5
@ -23,6 +23,9 @@
|
|||||||
<PackageVersion Include="xunit.extensibility.execution" Version="2.8.0" />
|
<PackageVersion Include="xunit.extensibility.execution" Version="2.8.0" />
|
||||||
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.0" />
|
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.0" />
|
||||||
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.1.0" />
|
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.1.0" />
|
||||||
|
<!-- 开发支持 -->
|
||||||
|
|
||||||
|
<PackageVersion Include="Nlnet.Avalonia.DevTools" Version="1.0.1-beta.22" />
|
||||||
|
|
||||||
<!-- 源码生成 -->
|
<!-- 源码生成 -->
|
||||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0-3.final" />
|
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0-3.final" />
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
<PackageReference Include="Avalonia.Themes.Fluent" />
|
<PackageReference Include="Avalonia.Themes.Fluent" />
|
||||||
<PackageReference Include="Avalonia.Controls.DataGrid" />
|
<PackageReference Include="Avalonia.Controls.DataGrid" />
|
||||||
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" />
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" />
|
||||||
|
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Nlnet.Avalonia.DevTools" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" />
|
<PackageReference Include="CommunityToolkit.Mvvm" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@ using AtomUI.Icon.AntDesign;
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Dialogs;
|
using Avalonia.Dialogs;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
using Nlnet.Avalonia.DevTools;
|
||||||
|
|
||||||
namespace AtomUI.Demo.Desktop;
|
namespace AtomUI.Demo.Desktop;
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ class Program
|
|||||||
.UseManagedSystemDialogs()
|
.UseManagedSystemDialogs()
|
||||||
.UsePlatformDetect()
|
.UsePlatformDetect()
|
||||||
.UseAtomUI()
|
.UseAtomUI()
|
||||||
|
.UseDevToolsForAvalonia()
|
||||||
.UseIconPackage<AntDesignIconPackage>(true)
|
.UseIconPackage<AntDesignIconPackage>(true)
|
||||||
.With(new Win32PlatformOptions())
|
.With(new Win32PlatformOptions())
|
||||||
.LogToTrace();
|
.LogToTrace();
|
||||||
|
@ -126,6 +126,8 @@ public class Alert : TemplatedControl, IControlCustomStyle
|
|||||||
_customStyle.HandleTemplateApplied(e.NameScope);
|
_customStyle.HandleTemplateApplied(e.NameScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IControlCustomStyle 实现
|
||||||
|
|
||||||
void IControlCustomStyle.HandleTemplateApplied(INameScope scope)
|
void IControlCustomStyle.HandleTemplateApplied(INameScope scope)
|
||||||
{
|
{
|
||||||
BindUtils.CreateTokenBinding(this, BorderThicknessProperty, GlobalResourceKey.BorderThickness,
|
BindUtils.CreateTokenBinding(this, BorderThicknessProperty, GlobalResourceKey.BorderThickness,
|
||||||
@ -133,8 +135,6 @@ public class Alert : TemplatedControl, IControlCustomStyle
|
|||||||
new RenderScaleAwareThicknessConfigure(this));
|
new RenderScaleAwareThicknessConfigure(this));
|
||||||
SetupCloseButton();
|
SetupCloseButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IControlCustomStyle 实现
|
|
||||||
|
|
||||||
void IControlCustomStyle.HandlePropertyChangedForStyle(AvaloniaPropertyChangedEventArgs e)
|
void IControlCustomStyle.HandlePropertyChangedForStyle(AvaloniaPropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
|
@ -118,15 +118,14 @@ namespace AtomUI.Styling
|
|||||||
{
|
{
|
||||||
public static readonly TokenResourceKey MenuPopupBorderRadius = new TokenResourceKey("Menu.MenuPopupBorderRadius");
|
public static readonly TokenResourceKey MenuPopupBorderRadius = new TokenResourceKey("Menu.MenuPopupBorderRadius");
|
||||||
public static readonly TokenResourceKey MenuPopupBoxShadows = new TokenResourceKey("Menu.MenuPopupBoxShadows");
|
public static readonly TokenResourceKey MenuPopupBoxShadows = new TokenResourceKey("Menu.MenuPopupBoxShadows");
|
||||||
|
public static readonly TokenResourceKey MenuPopupContentPadding = new TokenResourceKey("Menu.MenuPopupContentPadding");
|
||||||
public static readonly TokenResourceKey MenuPopupMinWidth = new TokenResourceKey("Menu.MenuPopupMinWidth");
|
public static readonly TokenResourceKey MenuPopupMinWidth = new TokenResourceKey("Menu.MenuPopupMinWidth");
|
||||||
public static readonly TokenResourceKey MenuPopupMaxWidth = new TokenResourceKey("Menu.MenuPopupMaxWidth");
|
public static readonly TokenResourceKey MenuPopupMaxWidth = new TokenResourceKey("Menu.MenuPopupMaxWidth");
|
||||||
public static readonly TokenResourceKey MenuPopupMinHeight = new TokenResourceKey("Menu.MenuPopupMinHeight");
|
public static readonly TokenResourceKey MenuPopupMinHeight = new TokenResourceKey("Menu.MenuPopupMinHeight");
|
||||||
public static readonly TokenResourceKey MenuPopupMaxHeight = new TokenResourceKey("Menu.MenuPopupMaxHeight");
|
public static readonly TokenResourceKey MenuPopupMaxHeight = new TokenResourceKey("Menu.MenuPopupMaxHeight");
|
||||||
public static readonly TokenResourceKey MenuArrowSize = new TokenResourceKey("Menu.MenuArrowSize");
|
public static readonly TokenResourceKey MenuArrowSize = new TokenResourceKey("Menu.MenuArrowSize");
|
||||||
public static readonly TokenResourceKey MenuArrowOffset = new TokenResourceKey("Menu.MenuArrowOffset");
|
public static readonly TokenResourceKey MenuArrowOffset = new TokenResourceKey("Menu.MenuArrowOffset");
|
||||||
public static readonly TokenResourceKey MenuMargin = new TokenResourceKey("Menu.MenuMargin");
|
|
||||||
public static readonly TokenResourceKey MenuTearOffHeight = new TokenResourceKey("Menu.MenuTearOffHeight");
|
public static readonly TokenResourceKey MenuTearOffHeight = new TokenResourceKey("Menu.MenuTearOffHeight");
|
||||||
public static readonly TokenResourceKey MenuContentPadding = new TokenResourceKey("Menu.MenuContentPadding");
|
|
||||||
public static readonly TokenResourceKey MenuBgColor = new TokenResourceKey("Menu.MenuBgColor");
|
public static readonly TokenResourceKey MenuBgColor = new TokenResourceKey("Menu.MenuBgColor");
|
||||||
public static readonly TokenResourceKey ItemColor = new TokenResourceKey("Menu.ItemColor");
|
public static readonly TokenResourceKey ItemColor = new TokenResourceKey("Menu.ItemColor");
|
||||||
public static readonly TokenResourceKey ItemHoverColor = new TokenResourceKey("Menu.ItemHoverColor");
|
public static readonly TokenResourceKey ItemHoverColor = new TokenResourceKey("Menu.ItemHoverColor");
|
||||||
@ -159,6 +158,7 @@ namespace AtomUI.Styling
|
|||||||
public static readonly TokenResourceKey TopLevelItemLineHeightLG = new TokenResourceKey("Menu.TopLevelItemLineHeightLG");
|
public static readonly TokenResourceKey TopLevelItemLineHeightLG = new TokenResourceKey("Menu.TopLevelItemLineHeightLG");
|
||||||
public static readonly TokenResourceKey TopLevelItemLineHeightSM = new TokenResourceKey("Menu.TopLevelItemLineHeightSM");
|
public static readonly TokenResourceKey TopLevelItemLineHeightSM = new TokenResourceKey("Menu.TopLevelItemLineHeightSM");
|
||||||
public static readonly TokenResourceKey TopLevelItemPopupMarginToAnchor = new TokenResourceKey("Menu.TopLevelItemPopupMarginToAnchor");
|
public static readonly TokenResourceKey TopLevelItemPopupMarginToAnchor = new TokenResourceKey("Menu.TopLevelItemPopupMarginToAnchor");
|
||||||
|
public static readonly TokenResourceKey SeparatorItemHeight = new TokenResourceKey("Menu.SeparatorItemHeight");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class OptionButtonResourceKey
|
public static class OptionButtonResourceKey
|
||||||
|
@ -1,12 +1,28 @@
|
|||||||
using AtomUI.Styling;
|
using AtomUI.Styling;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
namespace AtomUI.Controls;
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
[ControlThemeProvider]
|
[ControlThemeProvider]
|
||||||
public class MenuItemTheme : ControlTheme
|
internal class MenuItemTheme : ControlTheme
|
||||||
{
|
{
|
||||||
public MenuItemTheme()
|
public MenuItemTheme()
|
||||||
: base(typeof(MenuItem))
|
: base(typeof(MenuItem))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override IControlTemplate? BuildControlTemplate()
|
||||||
|
{
|
||||||
|
return new FuncControlTemplate<MenuItem>((item, scope) =>
|
||||||
|
{
|
||||||
|
return new Border()
|
||||||
|
{
|
||||||
|
Height = 30,
|
||||||
|
Background = new SolidColorBrush(Colors.Chocolate),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,8 +1,42 @@
|
|||||||
namespace AtomUI.Controls;
|
using AtomUI.Styling;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Metadata;
|
||||||
|
using Avalonia.Controls.Presenters;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
|
||||||
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
using AvaloniaScrollViewer = Avalonia.Controls.ScrollViewer;
|
using AvaloniaScrollViewer = Avalonia.Controls.ScrollViewer;
|
||||||
|
|
||||||
public class MenuScrollViewer : AvaloniaScrollViewer
|
[TemplatePart(MenuScrollViewerTheme.ScrollDownButtonPart, typeof(IconButton))]
|
||||||
|
[TemplatePart(MenuScrollViewerTheme.ScrollUpButtonPart, typeof(IconButton))]
|
||||||
|
[TemplatePart(MenuScrollViewerTheme.ScrollViewContentPart, typeof(ScrollContentPresenter))]
|
||||||
|
public class MenuScrollViewer : AvaloniaScrollViewer, IControlCustomStyle
|
||||||
{
|
{
|
||||||
|
private readonly IControlCustomStyle _customStyle;
|
||||||
|
private IconButton? _scrollUpButton;
|
||||||
|
private IconButton? _scrollDownButton;
|
||||||
|
private ScrollContentPresenter? _scrollViewContent;
|
||||||
|
|
||||||
|
public MenuScrollViewer()
|
||||||
|
{
|
||||||
|
_customStyle = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate(e);
|
||||||
|
_customStyle.HandleTemplateApplied(e.NameScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IControlCustomStyle 实现
|
||||||
|
|
||||||
|
void IControlCustomStyle.HandleTemplateApplied(INameScope scope)
|
||||||
|
{
|
||||||
|
_scrollUpButton = scope.Find<IconButton>(MenuScrollViewerTheme.ScrollUpButtonPart);
|
||||||
|
_scrollDownButton = scope.Find<IconButton>(MenuScrollViewerTheme.ScrollDownButtonPart);
|
||||||
|
_scrollViewContent = scope.Find<ScrollContentPresenter>(MenuScrollViewerTheme.ScrollViewContentPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
}
|
}
|
@ -1,12 +1,82 @@
|
|||||||
using AtomUI.Styling;
|
using AtomUI.Styling;
|
||||||
|
using AtomUI.Utils;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Presenters;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
using Avalonia.Input.GestureRecognizers;
|
||||||
|
|
||||||
namespace AtomUI.Controls;
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
[ControlThemeProvider]
|
[ControlThemeProvider]
|
||||||
public class MenuScrollViewerTheme : ControlTheme
|
internal class MenuScrollViewerTheme : ControlTheme
|
||||||
{
|
{
|
||||||
|
public const string ScrollUpButtonPart = "Part_ScrollUpButton";
|
||||||
|
public const string ScrollDownButtonPart = "Part_ScrollDownButton";
|
||||||
|
public const string ScrollViewContentPart = "PART_ContentPresenter";
|
||||||
|
public const string MainContainerPart = "Part_MainContainer";
|
||||||
|
|
||||||
public MenuScrollViewerTheme()
|
public MenuScrollViewerTheme()
|
||||||
: base(typeof(MenuScrollViewer))
|
: base(typeof(MenuScrollViewer)) { }
|
||||||
|
|
||||||
|
protected override IControlTemplate BuildControlTemplate()
|
||||||
{
|
{
|
||||||
|
return new FuncControlTemplate<MenuScrollViewer>((viewer, scope) =>
|
||||||
|
{
|
||||||
|
var dockPanel = new DockPanel();
|
||||||
|
var scrollUpButton = new IconButton()
|
||||||
|
{
|
||||||
|
Name = ScrollUpButtonPart,
|
||||||
|
};
|
||||||
|
DockPanel.SetDock(scrollUpButton, Dock.Top);
|
||||||
|
var scrollDownButton = new IconButton()
|
||||||
|
{
|
||||||
|
Name = ScrollDownButtonPart
|
||||||
|
};
|
||||||
|
DockPanel.SetDock(scrollDownButton, Dock.Bottom);
|
||||||
|
|
||||||
|
var scrollViewContent = CreateScrollContentPresenter(viewer);
|
||||||
|
|
||||||
|
dockPanel.Children.Add(scrollUpButton);
|
||||||
|
dockPanel.Children.Add(scrollDownButton);
|
||||||
|
dockPanel.Children.Add(scrollViewContent);
|
||||||
|
scrollUpButton.RegisterInNameScope(scope);
|
||||||
|
scrollDownButton.RegisterInNameScope(scope);
|
||||||
|
scrollViewContent.RegisterInNameScope(scope);
|
||||||
|
return dockPanel;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScrollContentPresenter CreateScrollContentPresenter(MenuScrollViewer viewer)
|
||||||
|
{
|
||||||
|
var scrollViewContent = new ScrollContentPresenter()
|
||||||
|
{
|
||||||
|
Name = ScrollViewContentPart
|
||||||
|
};
|
||||||
|
CreateTemplateParentBinding(scrollViewContent, ScrollContentPresenter.MarginProperty,
|
||||||
|
MenuScrollViewer.PaddingProperty);
|
||||||
|
CreateTemplateParentBinding(scrollViewContent, ScrollContentPresenter.HorizontalSnapPointsAlignmentProperty,
|
||||||
|
MenuScrollViewer.HorizontalSnapPointsAlignmentProperty);
|
||||||
|
CreateTemplateParentBinding(scrollViewContent, ScrollContentPresenter.HorizontalSnapPointsTypeProperty,
|
||||||
|
MenuScrollViewer.HorizontalSnapPointsTypeProperty);
|
||||||
|
CreateTemplateParentBinding(scrollViewContent, ScrollContentPresenter.VerticalSnapPointsAlignmentProperty,
|
||||||
|
MenuScrollViewer.VerticalSnapPointsAlignmentProperty);
|
||||||
|
CreateTemplateParentBinding(scrollViewContent, ScrollContentPresenter.VerticalSnapPointsTypeProperty,
|
||||||
|
MenuScrollViewer.VerticalSnapPointsTypeProperty);
|
||||||
|
var scrollGestureRecognizer = new ScrollGestureRecognizer();
|
||||||
|
BindUtils.RelayBind(scrollViewContent, ScrollContentPresenter.CanHorizontallyScrollProperty, scrollGestureRecognizer,
|
||||||
|
ScrollGestureRecognizer.CanHorizontallyScrollProperty);
|
||||||
|
BindUtils.RelayBind(scrollViewContent, ScrollContentPresenter.CanVerticallyScrollProperty, scrollGestureRecognizer,
|
||||||
|
ScrollGestureRecognizer.CanVerticallyScrollProperty);
|
||||||
|
|
||||||
|
CreateTemplateParentBinding(scrollGestureRecognizer, ScrollGestureRecognizer.IsScrollInertiaEnabledProperty,
|
||||||
|
MenuScrollViewer.IsScrollInertiaEnabledProperty);
|
||||||
|
scrollViewContent.GestureRecognizers.Add(scrollGestureRecognizer);
|
||||||
|
|
||||||
|
return scrollViewContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void BuildStyles()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,16 @@
|
|||||||
namespace AtomUI.Controls;
|
using Avalonia;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
public class MenuSeparator
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
|
using AvaloniaSeparator = Avalonia.Controls.Separator;
|
||||||
|
|
||||||
|
public class MenuSeparator : AvaloniaSeparator
|
||||||
{
|
{
|
||||||
|
public override void Render(DrawingContext context)
|
||||||
|
{
|
||||||
|
var linePen = new Pen(BorderBrush);
|
||||||
|
var offsetY = Bounds.Height / 2.0;
|
||||||
|
context.DrawLine(linePen, new Point(0, offsetY), new Point(Bounds.Right, offsetY));
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
using AtomUI.Styling;
|
using AtomUI.Styling;
|
||||||
|
using Avalonia.Styling;
|
||||||
|
|
||||||
namespace AtomUI.Controls;
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
@ -9,4 +10,12 @@ public class MenuSeparatorTheme : ControlTheme
|
|||||||
: base(typeof(MenuSeparator))
|
: base(typeof(MenuSeparator))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void BuildStyles()
|
||||||
|
{
|
||||||
|
var commonStyle = new Style(selector => selector.Nesting());
|
||||||
|
commonStyle.Add(MenuSeparator.MinHeightProperty, MenuResourceKey.SeparatorItemHeight);
|
||||||
|
commonStyle.Add(MenuSeparator.BorderBrushProperty, GlobalResourceKey.ColorBorder);
|
||||||
|
Add(commonStyle);
|
||||||
|
}
|
||||||
}
|
}
|
@ -53,8 +53,7 @@ public class MenuTheme : ControlTheme
|
|||||||
protected override void BuildStyles()
|
protected override void BuildStyles()
|
||||||
{
|
{
|
||||||
var commonStyle = new Style(selector => selector.Nesting());
|
var commonStyle = new Style(selector => selector.Nesting());
|
||||||
commonStyle.Add(Menu.BackgroundProperty, GlobalResourceKey.ColorBgContainer);
|
commonStyle.Add(Menu.BackgroundProperty, MenuResourceKey.MenuBgColor);
|
||||||
commonStyle.Add(Menu.PaddingProperty, new Thickness(0));
|
|
||||||
commonStyle.Add(Menu.BorderBrushProperty, GlobalResourceKey.ColorBorder);
|
commonStyle.Add(Menu.BorderBrushProperty, GlobalResourceKey.ColorBorder);
|
||||||
var largeSizeType = new Style(selector => selector.Nesting().PropertyEquals(Menu.SizeTypeProperty, SizeType.Large));
|
var largeSizeType = new Style(selector => selector.Nesting().PropertyEquals(Menu.SizeTypeProperty, SizeType.Large));
|
||||||
largeSizeType.Add(Menu.MinHeightProperty, GlobalResourceKey.ControlHeightLG);
|
largeSizeType.Add(Menu.MinHeightProperty, GlobalResourceKey.ControlHeightLG);
|
||||||
|
@ -25,6 +25,11 @@ internal class MenuToken : AbstractControlDesignToken
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public BoxShadows MenuPopupBoxShadows { get; set; }
|
public BoxShadows MenuPopupBoxShadows { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 菜单内容边距
|
||||||
|
/// </summary>
|
||||||
|
public Thickness MenuPopupContentPadding { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 菜单 Popup 最小宽度
|
/// 菜单 Popup 最小宽度
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -55,22 +60,12 @@ internal class MenuToken : AbstractControlDesignToken
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double MenuArrowOffset { get; set; }
|
public double MenuArrowOffset { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 菜单间距
|
|
||||||
/// </summary>
|
|
||||||
public Thickness MenuMargin { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 分离菜单项的高度,这个用于菜单中快捷功能的图标显示
|
/// 分离菜单项的高度,这个用于菜单中快捷功能的图标显示
|
||||||
/// TODO 暂时还没实现,但是最终会实现
|
/// TODO 暂时还没实现,但是最终会实现
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double MenuTearOffHeight { get; set; }
|
public double MenuTearOffHeight { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 菜单内容边距
|
|
||||||
/// </summary>
|
|
||||||
public double MenuContentPadding { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 弹出框背景色
|
/// 弹出框背景色
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -231,7 +226,11 @@ internal class MenuToken : AbstractControlDesignToken
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double TopLevelItemPopupMarginToAnchor { get; set; }
|
public double TopLevelItemPopupMarginToAnchor { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 菜单分割项的高度
|
||||||
|
/// </summary>
|
||||||
|
public double SeparatorItemHeight { get; set; }
|
||||||
|
|
||||||
internal override void CalculateFromAlias()
|
internal override void CalculateFromAlias()
|
||||||
{
|
{
|
||||||
base.CalculateFromAlias();
|
base.CalculateFromAlias();
|
||||||
@ -271,13 +270,6 @@ internal class MenuToken : AbstractControlDesignToken
|
|||||||
ItemPaddingInline = new Thickness(padding);
|
ItemPaddingInline = new Thickness(padding);
|
||||||
ItemIconSize = fontSize;
|
ItemIconSize = fontSize;
|
||||||
ItemIconMarginInlineEnd = controlHeightSM - fontSize;
|
ItemIconMarginInlineEnd = controlHeightSM - fontSize;
|
||||||
MenuArrowSize = (fontSize / 7.0) * 5.0;
|
|
||||||
MenuArrowOffset = MenuArrowSize * 0.5;
|
|
||||||
MenuTearOffHeight = ItemHeight * 1.2; // 暂时这么定义吧
|
|
||||||
MenuContentPadding = _globalToken.PaddingXXS / 2; // 先默认一个最小的内容间距
|
|
||||||
MenuMargin = new Thickness(1);
|
|
||||||
|
|
||||||
MenuPopupBoxShadows = _globalToken.BoxShadowsSecondary;
|
|
||||||
|
|
||||||
TopLevelItemColor = colorNeutralToken.ColorText;
|
TopLevelItemColor = colorNeutralToken.ColorText;
|
||||||
TopLevelItemSelectedColor = colorNeutralToken.ColorTextSecondary;
|
TopLevelItemSelectedColor = colorNeutralToken.ColorTextSecondary;
|
||||||
@ -322,5 +314,13 @@ internal class MenuToken : AbstractControlDesignToken
|
|||||||
MenuPopupMinHeight = ItemHeight * 3;
|
MenuPopupMinHeight = ItemHeight * 3;
|
||||||
MenuPopupMaxHeight = ItemHeight * 30;
|
MenuPopupMaxHeight = ItemHeight * 30;
|
||||||
|
|
||||||
|
SeparatorItemHeight = _globalToken.SeedToken.LineWidth * 5; // 上下两像素,留一像素给自己
|
||||||
|
|
||||||
|
MenuArrowSize = (fontSize / 7.0) * 5.0;
|
||||||
|
MenuArrowOffset = MenuArrowSize * 0.5;
|
||||||
|
MenuTearOffHeight = ItemHeight * 1.2; // 暂时这么定义吧
|
||||||
|
|
||||||
|
MenuPopupContentPadding = new Thickness(_globalToken.PaddingXXS, MenuPopupBorderRadius.TopLeft / 2);
|
||||||
|
MenuPopupBoxShadows = _globalToken.BoxShadowsSecondary;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,11 @@
|
|||||||
using AtomUI.Styling;
|
using AtomUI.Styling;
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Presenters;
|
using Avalonia.Controls.Presenters;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
using Avalonia.Data;
|
using Avalonia.Data;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Media;
|
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
|
||||||
namespace AtomUI.Controls;
|
namespace AtomUI.Controls;
|
||||||
@ -19,6 +17,7 @@ public class TopLevelMenuItemTheme : ControlTheme
|
|||||||
|
|
||||||
public const string PopupPart = "PART_Popup";
|
public const string PopupPart = "PART_Popup";
|
||||||
public const string HeaderPresenterPart = "PART_HeaderPresenter";
|
public const string HeaderPresenterPart = "PART_HeaderPresenter";
|
||||||
|
public const string ItemsPresenterPart = "PART_ItemsPresenter";
|
||||||
|
|
||||||
public TopLevelMenuItemTheme() : base(typeof(MenuItem)) {}
|
public TopLevelMenuItemTheme() : base(typeof(MenuItem)) {}
|
||||||
|
|
||||||
@ -59,6 +58,7 @@ public class TopLevelMenuItemTheme : ControlTheme
|
|||||||
|
|
||||||
private Popup CreateMenuPopup(MenuItem menuItem)
|
private Popup CreateMenuPopup(MenuItem menuItem)
|
||||||
{
|
{
|
||||||
|
|
||||||
var popup = new Popup()
|
var popup = new Popup()
|
||||||
{
|
{
|
||||||
Name = PopupPart,
|
Name = PopupPart,
|
||||||
@ -66,8 +66,31 @@ public class TopLevelMenuItemTheme : ControlTheme
|
|||||||
IsLightDismissEnabled = true,
|
IsLightDismissEnabled = true,
|
||||||
Placement = PlacementMode.BottomEdgeAlignedLeft,
|
Placement = PlacementMode.BottomEdgeAlignedLeft,
|
||||||
OverlayInputPassThroughElement = menuItem,
|
OverlayInputPassThroughElement = menuItem,
|
||||||
Child = new Border()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var border = new Border();
|
||||||
|
BindUtils.CreateTokenBinding(border, Border.BackgroundProperty, GlobalResourceKey.ColorBgContainer);
|
||||||
|
BindUtils.CreateTokenBinding(border, Border.CornerRadiusProperty, MenuResourceKey.MenuPopupBorderRadius);
|
||||||
|
BindUtils.CreateTokenBinding(border, Border.MinWidthProperty, MenuResourceKey.MenuPopupMinWidth);
|
||||||
|
BindUtils.CreateTokenBinding(border, Border.MaxWidthProperty, MenuResourceKey.MenuPopupMaxWidth);
|
||||||
|
BindUtils.CreateTokenBinding(border, Border.MinHeightProperty, MenuResourceKey.MenuPopupMinHeight);
|
||||||
|
BindUtils.CreateTokenBinding(border, Border.MaxHeightProperty, MenuResourceKey.MenuPopupMaxHeight);
|
||||||
|
BindUtils.CreateTokenBinding(border, Border.PaddingProperty, MenuResourceKey.MenuPopupContentPadding);
|
||||||
|
|
||||||
|
var scrollViewer = new MenuScrollViewer();
|
||||||
|
var itemsPresenter = new ItemsPresenter()
|
||||||
|
{
|
||||||
|
Name = ItemsPresenterPart,
|
||||||
|
};
|
||||||
|
CreateTemplateParentBinding(itemsPresenter, ItemsPresenter.ItemsPanelProperty, MenuItem.ItemsPanelProperty);
|
||||||
|
Grid.SetIsSharedSizeScope(itemsPresenter, true);
|
||||||
|
scrollViewer.Content = itemsPresenter;
|
||||||
|
border.Child = scrollViewer;
|
||||||
|
popup.Child = border;
|
||||||
|
|
||||||
|
BindUtils.CreateTokenBinding(popup, Popup.MarginToAnchorProperty, MenuResourceKey.TopLevelItemPopupMarginToAnchor);
|
||||||
|
BindUtils.CreateTokenBinding(popup, Popup.MaskShadowsProperty, MenuResourceKey.MenuPopupBoxShadows);
|
||||||
|
|
||||||
CreateTemplateParentBinding(popup, Popup.IsOpenProperty, MenuItem.IsSubMenuOpenProperty, BindingMode.TwoWay);
|
CreateTemplateParentBinding(popup, Popup.IsOpenProperty, MenuItem.IsSubMenuOpenProperty, BindingMode.TwoWay);
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
@ -77,7 +100,6 @@ public class TopLevelMenuItemTheme : ControlTheme
|
|||||||
BuildCommonStyle();
|
BuildCommonStyle();
|
||||||
BuildSizeTypeStyle();
|
BuildSizeTypeStyle();
|
||||||
BuildDisabledStyle();
|
BuildDisabledStyle();
|
||||||
BuildPopupStyle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildCommonStyle()
|
private void BuildCommonStyle()
|
||||||
@ -132,25 +154,6 @@ public class TopLevelMenuItemTheme : ControlTheme
|
|||||||
Add(smallSizeStyle);
|
Add(smallSizeStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildPopupStyle()
|
|
||||||
{
|
|
||||||
var popupStyle = new Style(selector => selector.Nesting().Template().OfType<Popup>());
|
|
||||||
|
|
||||||
popupStyle.Add(Popup.MarginToAnchorProperty, MenuResourceKey.TopLevelItemPopupMarginToAnchor);
|
|
||||||
popupStyle.Add(Popup.MaskShadowsProperty, MenuResourceKey.MenuPopupBoxShadows);
|
|
||||||
|
|
||||||
Add(popupStyle);
|
|
||||||
|
|
||||||
var borderStyle = new Style(selector => selector.Nesting().Template().OfType<Popup>().Child().OfType<Border>());
|
|
||||||
borderStyle.Add(Border.BackgroundProperty, GlobalResourceKey.ColorBgContainer);
|
|
||||||
borderStyle.Add(Border.CornerRadiusProperty, MenuResourceKey.MenuPopupBorderRadius);
|
|
||||||
borderStyle.Add(Border.MinWidthProperty, MenuResourceKey.MenuPopupMinWidth);
|
|
||||||
borderStyle.Add(Border.MaxWidthProperty, MenuResourceKey.MenuPopupMaxWidth);
|
|
||||||
borderStyle.Add(Border.MinHeightProperty, MenuResourceKey.MenuPopupMinHeight);
|
|
||||||
borderStyle.Add(Border.MaxHeightProperty, MenuResourceKey.MenuPopupMaxHeight);
|
|
||||||
Add(borderStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BuildDisabledStyle()
|
private void BuildDisabledStyle()
|
||||||
{
|
{
|
||||||
var disabledStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Disabled));
|
var disabledStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Disabled));
|
||||||
|
@ -7,14 +7,14 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Data;
|
using Avalonia.Data;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.LogicalTree;
|
|
||||||
using Avalonia.Markup.Xaml.Templates;
|
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Media.Imaging;
|
using Avalonia.Media.Imaging;
|
||||||
using Avalonia.Metadata;
|
using Avalonia.Metadata;
|
||||||
|
|
||||||
namespace AtomUI.Controls;
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
|
using AvaloniaSeparator = Avalonia.Controls.Separator;
|
||||||
|
|
||||||
public enum SeparatorTitlePosition
|
public enum SeparatorTitlePosition
|
||||||
{
|
{
|
||||||
Left,
|
Left,
|
||||||
@ -22,7 +22,7 @@ public enum SeparatorTitlePosition
|
|||||||
Center
|
Center
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class Separator : TemplatedControl, IControlCustomStyle
|
public class Separator : AvaloniaSeparator, IControlCustomStyle
|
||||||
{
|
{
|
||||||
#region 公共属性定义
|
#region 公共属性定义
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ namespace AtomUI.Controls;
|
|||||||
[ControlThemeProvider]
|
[ControlThemeProvider]
|
||||||
internal class SeparatorTheme : ControlTheme
|
internal class SeparatorTheme : ControlTheme
|
||||||
{
|
{
|
||||||
public const string TitlePart = "PART_CloseBtn";
|
public const string TitlePart = "PART_Title";
|
||||||
|
|
||||||
public SeparatorTheme()
|
public SeparatorTheme()
|
||||||
: base(typeof(Separator)) { }
|
: base(typeof(Separator)) { }
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
using Avalonia.Data;
|
using Avalonia.Data;
|
||||||
@ -11,9 +10,9 @@ using AvaloniaControlTheme = Avalonia.Styling.ControlTheme;
|
|||||||
|
|
||||||
public class ControlTheme : AvaloniaControlTheme
|
public class ControlTheme : AvaloniaControlTheme
|
||||||
{
|
{
|
||||||
public ControlTheme() {}
|
public ControlTheme() { }
|
||||||
public ControlTheme(Type targetType) : base(targetType) {}
|
public ControlTheme(Type targetType) : base(targetType) { }
|
||||||
|
|
||||||
public void Build()
|
public void Build()
|
||||||
{
|
{
|
||||||
NotifyPreBuild();
|
NotifyPreBuild();
|
||||||
@ -22,6 +21,7 @@ public class ControlTheme : AvaloniaControlTheme
|
|||||||
if (template is not null) {
|
if (template is not null) {
|
||||||
Add(new Setter(TemplatedControl.TemplateProperty, template));
|
Add(new Setter(TemplatedControl.TemplateProperty, template));
|
||||||
}
|
}
|
||||||
|
|
||||||
NotifyBuildCompleted();
|
NotifyBuildCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,24 +30,52 @@ public class ControlTheme : AvaloniaControlTheme
|
|||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual IControlTemplate? BuildControlTemplate() { return default; }
|
protected virtual IControlTemplate? BuildControlTemplate()
|
||||||
protected virtual void BuildStyles() {}
|
{
|
||||||
protected virtual void NotifyPreBuild() {}
|
return default;
|
||||||
protected virtual void NotifyBuildCompleted() {}
|
}
|
||||||
|
|
||||||
protected static IDisposable CreateTemplateParentBinding(Control control, AvaloniaProperty property, string templateParentPath,
|
protected virtual void BuildStyles() { }
|
||||||
|
protected virtual void NotifyPreBuild() { }
|
||||||
|
protected virtual void NotifyBuildCompleted() { }
|
||||||
|
|
||||||
|
protected static IDisposable CreateTemplateParentBinding(AvaloniaObject target, AvaloniaProperty property,
|
||||||
|
string templateParentPath,
|
||||||
BindingMode mode = BindingMode.Default)
|
BindingMode mode = BindingMode.Default)
|
||||||
{
|
{
|
||||||
return control.Bind(property, new Binding(templateParentPath)
|
return target.Bind(property, new Binding(templateParentPath)
|
||||||
{
|
{
|
||||||
RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
|
RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
|
||||||
Mode = mode
|
Mode = mode
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static IDisposable CreateTemplateParentBinding(Control control, AvaloniaProperty property, AvaloniaProperty templateParentProperty,
|
protected static IDisposable CreateTemplateParentBinding<T>(AvaloniaObject target, StyledProperty<T> property,
|
||||||
|
string templateParentPath,
|
||||||
|
BindingMode mode = BindingMode.Default)
|
||||||
|
{
|
||||||
|
return target.Bind(property, new Binding(templateParentPath)
|
||||||
|
{
|
||||||
|
RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
|
||||||
|
Mode = mode
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static IDisposable CreateTemplateParentBinding<T>(AvaloniaObject target, DirectPropertyBase<T> property,
|
||||||
|
string templateParentPath,
|
||||||
|
BindingMode mode = BindingMode.Default)
|
||||||
|
{
|
||||||
|
return target.Bind(property, new Binding(templateParentPath)
|
||||||
|
{
|
||||||
|
RelativeSource = new RelativeSource(RelativeSourceMode.TemplatedParent),
|
||||||
|
Mode = mode
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static IDisposable CreateTemplateParentBinding(AvaloniaObject target, AvaloniaProperty property,
|
||||||
|
AvaloniaProperty templateParentProperty,
|
||||||
BindingMode mode = BindingMode.Default)
|
BindingMode mode = BindingMode.Default)
|
||||||
{
|
{
|
||||||
return CreateTemplateParentBinding(control, property, templateParentProperty.Name, mode);
|
return CreateTemplateParentBinding(target, property, templateParentProperty.Name, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,7 @@ public static class BindUtils
|
|||||||
{
|
{
|
||||||
public static IDisposable RelayBind(AvaloniaObject source, AvaloniaProperty sourceProperty, AvaloniaObject target,
|
public static IDisposable RelayBind(AvaloniaObject source, AvaloniaProperty sourceProperty, AvaloniaObject target,
|
||||||
AvaloniaProperty? targetProperty = null,
|
AvaloniaProperty? targetProperty = null,
|
||||||
BindingMode mode = BindingMode.OneWay)
|
BindingMode mode = BindingMode.Default)
|
||||||
{
|
{
|
||||||
targetProperty ??= sourceProperty;
|
targetProperty ??= sourceProperty;
|
||||||
var registry = AvaloniaPropertyRegistry.Instance;
|
var registry = AvaloniaPropertyRegistry.Instance;
|
||||||
|
Loading…
Reference in New Issue
Block a user