Merge branch 'feature/popupconfirm' into develop

This commit is contained in:
polarboy
2024-08-27 12:55:54 +08:00
19 changed files with 564 additions and 41 deletions
@@ -0,0 +1,21 @@
<UserControl
x:Class="AtomUI.Demo.Desktop.ShowCase.PopupConfirmShowCase"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:atom="https://atomui.net"
xmlns:showcase="clr-namespace:AtomUI.Demo.Desktop.ShowCase"
mc:Ignorable="d">
<showcase:ShowCasePanel>
<showcase:ShowCaseItem
Title="Basic usage"
Description="The basic example supports the title and description props of confirmation.">
<atom:PopupConfirm
Title="Delete the task"
ConfirmContent="Are you sure to delete this task?">
<atom:Button ButtonType="Default" IsDanger="True">Delete</atom:Button>
</atom:PopupConfirm>
</showcase:ShowCaseItem>
</showcase:ShowCasePanel>
</UserControl>
@@ -0,0 +1,11 @@
using Avalonia.Controls;
namespace AtomUI.Demo.Desktop.ShowCase;
public partial class PopupConfirmShowCase : UserControl
{
public PopupConfirmShowCase()
{
InitializeComponent();
}
}
@@ -84,6 +84,9 @@
<TabItem Header="InfoFlyout">
<showcases:InfoFlyoutShowCase />
</TabItem>
<TabItem Header="PopupConfirm">
<showcases:PopupConfirmShowCase />
</TabItem>
<TabItem Header="ProgressBar">
<showcases:ProgressBarShowCase />
</TabItem>
@@ -5,6 +5,7 @@ using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Styling;
namespace AtomUI.Controls;
+11 -12
View File
@@ -16,6 +16,7 @@ using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.VisualTree;
namespace AtomUI.Controls;
@@ -249,13 +250,6 @@ public class Button : AvaloniaButton,
var size = base.MeasureOverride(availableSize);
var targetWidth = size.Width;
var targetHeight = size.Height;
// targetHeight += Padding.Top + Padding.Bottom;
// if (Shape != ButtonShape.Round) {
// targetWidth += Padding.Left + Padding.Right;
// } else {
// targetWidth += Math.Max(Padding.Left + Padding.Right, targetHeight);
// }
targetHeight = Math.Max(targetHeight, ControlHeight);
@@ -399,17 +393,13 @@ public class Button : AvaloniaButton,
};
}
}
TokenResourceBinder.CreateGlobalTokenBinding(this, BorderThicknessProperty, GlobalTokenResourceKey.BorderThickness,
BindingPriority.Template,
new RenderScaleAwareThicknessConfigure(this));
_customStyle.CollectStyleState();
ApplyShapeStyleConfig();
ApplyIconModeStyleConfig();
UpdatePseudoClasses();
SetupIcon();
SetupIconBrush();
SetupEffectiveBorderThickness();
}
protected virtual void ApplyIconModeStyleConfig()
@@ -490,6 +480,15 @@ public class Button : AvaloniaButton,
}
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
TokenResourceBinder.CreateGlobalTokenBinding(this, BorderThicknessProperty, GlobalTokenResourceKey.BorderThickness,
BindingPriority.Template,
new RenderScaleAwareThicknessConfigure(this));
SetupEffectiveBorderThickness();
}
private void SetupEffectiveBorderThickness()
{
if (ButtonType == ButtonType.Default) {
+10 -10
View File
@@ -6,12 +6,12 @@ using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Metadata;
using Avalonia.Styling;
using Avalonia.Threading;
using Avalonia.VisualTree;
namespace AtomUI.Controls;
@@ -134,7 +134,7 @@ public class Flyout : PopupFlyoutBase
SetupArrowPosition(Popup);
}
private void SetupArrowPosition(Popup popup, FlyoutPresenter? flyoutPresenter = null)
protected void SetupArrowPosition(Popup popup, FlyoutPresenter? flyoutPresenter = null)
{
if (flyoutPresenter is null) {
var child = popup.Child;
@@ -323,14 +323,14 @@ public class Flyout : PopupFlyoutBase
}
}
if (Popup.PlacementTarget?.GetVisualRoot() is null) {
return base.HideCore(false);
}
IsOpen = false;
Dispatcher.UIThread.Post(() =>
{
Popup.CloseAnimation(HandlePopupClosed);
});
// if (Popup.PlacementTarget?.GetVisualRoot() is null) {
// return base.HideCore(false);
// }
// IsOpen = false;
// Dispatcher.UIThread.Post(() =>
// {
// Popup.CloseAnimation(HandlePopupClosed);
// });
return true;
}
+12 -12
View File
@@ -146,8 +146,7 @@ public class FlyoutHost : Control
}
#endregion
private bool _initialized = false;
private DispatcherTimer? _mouseEnterDelayTimer;
private DispatcherTimer? _mouseLeaveDelayTimer;
private CompositeDisposable? _subscriptions;
@@ -157,35 +156,36 @@ public class FlyoutHost : Control
PlacementProperty.OverrideDefaultValue<FlyoutHost>(PlacementMode.Top);
}
public sealed override void ApplyTemplate()
public override void ApplyTemplate()
{
base.ApplyTemplate();
if (!_initialized) {
if (AnchorTarget is not null) {
((ISetLogicalParent)AnchorTarget).SetParent(this);
VisualChildren.Add(AnchorTarget);
}
TokenResourceBinder.CreateGlobalTokenBinding(this, MarginToAnchorProperty, GlobalTokenResourceKey.MarginXXS);
_initialized = true;
if (AnchorTarget is not null) {
((ISetLogicalParent)AnchorTarget).SetParent(this);
VisualChildren.Add(AnchorTarget);
}
TokenResourceBinder.CreateGlobalTokenBinding(this, MarginToAnchorProperty, GlobalTokenResourceKey.MarginXXS);
SetupFlyoutProperties();
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
SetupTriggerHandler();
SetupFlyoutProperties();
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
if (AnchorTarget is not null) {
((ISetLogicalParent)AnchorTarget).SetParent(null);
VisualChildren.Remove(AnchorTarget);
}
StopMouseLeaveTimer();
StopMouseEnterTimer();
_subscriptions?.Dispose();
}
private void SetupFlyoutProperties()
protected virtual void SetupFlyoutProperties()
{
if (Flyout is not null) {
BindUtils.RelayBind(this, PlacementProperty, Flyout);
@@ -1,4 +1,5 @@
using Avalonia.Input;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.LogicalTree;
namespace AtomUI.Controls;
@@ -20,4 +21,9 @@ public class FlyoutPresenter : ArrowDecoratedBox
}
base.OnKeyDown(e);
}
public FlyoutPresenter()
{
SetValue(CursorProperty, new Cursor(StandardCursorType.Arrow), BindingPriority.Template);
}
}
@@ -64,8 +64,6 @@ public class MenuFlyout : Flyout
set => SetValue(ItemTemplateProperty, value);
}
private Classes? _classes;
protected override Control CreatePresenter()
{
var presenter = new MenuFlyoutPresenter()
@@ -106,10 +104,6 @@ public class MenuFlyout : Flyout
protected override void OnOpening(CancelEventArgs args)
{
if (Popup.Child is { } presenter) {
if (_classes != null) {
SetPresenterClasses(presenter, FlyoutPresenterClasses);
}
if (FlyoutPresenterTheme is { } theme) {
presenter.SetValue(Control.ThemeProperty, theme);
}
@@ -44,6 +44,7 @@
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.NumericUpDownTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.OptionButtonGroupTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.OptionButtonTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.PopupConfirmContainerTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.CircleProgressTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.DashboardProgressTheme());
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.ProgressBarTheme());
@@ -23,6 +23,7 @@
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.MenuToken));
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.NumericUpDownToken));
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.OptionButtonToken));
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.PopupConfirmToken));
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.ProgressBarToken));
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.RadioButtonToken));
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.SegmentedToken));
@@ -317,6 +317,16 @@ namespace AtomUI.Theme.Styling
public static readonly TokenResourceKey PaddingSM = new TokenResourceKey("OptionButton.PaddingSM", "AtomUI.Token");
}
public static class PopupConfirmTokenResourceKey
{
public static readonly TokenResourceKey PopupMinWidth = new TokenResourceKey("PopupConfirm.PopupMinWidth", "AtomUI.Token");
public static readonly TokenResourceKey PopupMinHeight = new TokenResourceKey("PopupConfirm.PopupMinHeight", "AtomUI.Token");
public static readonly TokenResourceKey ButtonMargin = new TokenResourceKey("PopupConfirm.ButtonMargin", "AtomUI.Token");
public static readonly TokenResourceKey IconMargin = new TokenResourceKey("PopupConfirm.IconMargin", "AtomUI.Token");
public static readonly TokenResourceKey ContentContainerMargin = new TokenResourceKey("PopupConfirm.ContentContainerMargin", "AtomUI.Token");
public static readonly TokenResourceKey TitleMargin = new TokenResourceKey("PopupConfirm.TitleMargin", "AtomUI.Token");
}
public static class ProgressBarTokenResourceKey
{
public static readonly TokenResourceKey DefaultColor = new TokenResourceKey("ProgressBar.DefaultColor", "AtomUI.Token");
@@ -0,0 +1,114 @@
using Avalonia;
using Avalonia.Controls.Templates;
namespace AtomUI.Controls;
public enum PopupConfirmStatus
{
Info,
Warning,
Error
}
public class PopupConfirm : FlyoutHost
{
#region 公共属性属性
public static readonly StyledProperty<string> OkTextProperty =
AvaloniaProperty.Register<PopupConfirm, string>(nameof(OkText), "Ok");
public static readonly StyledProperty<string> CancelTextProperty =
AvaloniaProperty.Register<PopupConfirm, string>(nameof(CancelText), "Cancel");
public static readonly StyledProperty<ButtonType> OkButtonTypeProperty =
AvaloniaProperty.Register<PopupConfirm, ButtonType>(nameof(OkButtonType), ButtonType.Primary);
public static readonly StyledProperty<bool> IsShowCancelButtonProperty =
AvaloniaProperty.Register<PopupConfirm, bool>(nameof(IsShowCancelButton), true);
public static readonly StyledProperty<string> TitleProperty =
AvaloniaProperty.Register<PopupConfirm, string>(nameof(Title));
public static readonly StyledProperty<object?> ConfirmContentProperty =
AvaloniaProperty.Register<PopupConfirm, object?>(nameof(ConfirmContent));
public static readonly StyledProperty<IDataTemplate?> ConfirmContentTemplateProperty =
AvaloniaProperty.Register<PopupConfirm, IDataTemplate?>(nameof(ConfirmContentTemplate));
public static readonly StyledProperty<PathIcon?> IconProperty
= AvaloniaProperty.Register<PopupConfirm, PathIcon?>(nameof(Icon));
public static readonly StyledProperty<PopupConfirmStatus> ConfirmStatusProperty
= AvaloniaProperty.Register<PopupConfirm, PopupConfirmStatus>(nameof(ConfirmStatus), PopupConfirmStatus.Warning);
public string OkText
{
get => GetValue(OkTextProperty);
set => SetValue(OkTextProperty, value);
}
public string CancelText
{
get => GetValue(CancelTextProperty);
set => SetValue(CancelTextProperty, value);
}
public ButtonType OkButtonType
{
get => GetValue(OkButtonTypeProperty);
set => SetValue(OkButtonTypeProperty, value);
}
public bool IsShowCancelButton
{
get => GetValue(IsShowCancelButtonProperty);
set => SetValue(IsShowCancelButtonProperty, value);
}
public string Title
{
get => GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
public object? ConfirmContent
{
get => GetValue(ConfirmContentProperty);
set => SetValue(ConfirmContentProperty, value);
}
public IDataTemplate? ConfirmContentTemplate
{
get => GetValue(ConfirmContentTemplateProperty);
set => SetValue(ConfirmContentTemplateProperty, value);
}
public PathIcon? Icon
{
get => GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
public PopupConfirmStatus ConfirmStatus
{
get => GetValue(ConfirmStatusProperty);
set => SetValue(ConfirmStatusProperty, value);
}
#endregion
public sealed override void ApplyTemplate()
{
if (Flyout is null) {
Flyout = new PopupConfirmFlyout(this);
}
if (Icon is null) {
Icon = new PathIcon()
{
Kind = "ExclamationCircleFilled"
};
}
base.ApplyTemplate();
}
}
@@ -0,0 +1,93 @@
using Avalonia;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
namespace AtomUI.Controls;
internal class PopupConfirmContainer : TemplatedControl
{
#region 内部属性定义
internal static readonly StyledProperty<string> OkTextProperty =
PopupConfirm.OkTextProperty.AddOwner<PopupConfirmContainer>();
internal static readonly StyledProperty<string> CancelTextProperty =
PopupConfirm.CancelTextProperty.AddOwner<PopupConfirmContainer>();
internal static readonly StyledProperty<ButtonType> OkButtonTypeProperty =
PopupConfirm.OkButtonTypeProperty.AddOwner<PopupConfirmContainer>();
internal static readonly StyledProperty<bool> IsShowCancelButtonProperty =
PopupConfirm.IsShowCancelButtonProperty.AddOwner<PopupConfirmContainer>();
internal static readonly StyledProperty<string> TitleProperty =
PopupConfirm.TitleProperty.AddOwner<PopupConfirmContainer>();
internal static readonly StyledProperty<object?> ConfirmContentProperty =
PopupConfirm.ConfirmContentProperty.AddOwner<PopupConfirmContainer>();
internal static readonly StyledProperty<IDataTemplate?> ConfirmContentTemplateProperty =
PopupConfirm.ConfirmContentTemplateProperty.AddOwner<PopupConfirmContainer>();
internal static readonly StyledProperty<PathIcon?> IconProperty =
PopupConfirm.IconProperty.AddOwner<PopupConfirmContainer>();
internal static readonly StyledProperty<PopupConfirmStatus> ConfirmStatusProperty
= PopupConfirm.ConfirmStatusProperty.AddOwner<PopupConfirmContainer>();
internal string OkText
{
get => GetValue(OkTextProperty);
set => SetValue(OkTextProperty, value);
}
internal string CancelText
{
get => GetValue(CancelTextProperty);
set => SetValue(CancelTextProperty, value);
}
internal ButtonType OkButtonType
{
get => GetValue(OkButtonTypeProperty);
set => SetValue(OkButtonTypeProperty, value);
}
internal bool IsShowCancelButton
{
get => GetValue(IsShowCancelButtonProperty);
set => SetValue(IsShowCancelButtonProperty, value);
}
internal string Title
{
get => GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
internal object? ConfirmContent
{
get => GetValue(ConfirmContentProperty);
set => SetValue(ConfirmContentProperty, value);
}
internal IDataTemplate? ConfirmContentTemplate
{
get => GetValue(ConfirmContentTemplateProperty);
set => SetValue(ConfirmContentTemplateProperty, value);
}
public PathIcon? Icon
{
get => GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
public PopupConfirmStatus ConfirmStatus
{
get => GetValue(ConfirmStatusProperty);
set => SetValue(ConfirmStatusProperty, value);
}
#endregion
}
@@ -0,0 +1,171 @@
using AtomUI.Theme;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
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.Styling;
namespace AtomUI.Controls;
[ControlThemeProvider]
internal class PopupConfirmContainerTheme : BaseControlTheme
{
public const string MainLayoutPart = "PART_MainLayout";
public const string OkButtonPart = "PART_OkButton";
public const string TitlePart = "PART_Title";
public const string ContentPart = "PART_Content";
public const string IconContentPart = "PART_IconContent";
public PopupConfirmContainerTheme()
: base(typeof(PopupConfirmContainer)) { }
protected override IControlTemplate? BuildControlTemplate()
{
return new FuncControlTemplate<PopupConfirmContainer>((popupConfirmContainer, scope) =>
{
var mainLayout = new DockPanel()
{
Name = MainLayoutPart,
LastChildFill = true
};
var buttons = BuildButtons(popupConfirmContainer, scope);
mainLayout.Children.Add(buttons);
var content = BuildContent(popupConfirmContainer, scope);
mainLayout.Children.Add(content);
TokenResourceBinder.CreateTokenBinding(mainLayout, DockPanel.MinWidthProperty, PopupConfirmTokenResourceKey.PopupMinWidth);
TokenResourceBinder.CreateTokenBinding(mainLayout, DockPanel.MinHeightProperty, PopupConfirmTokenResourceKey.PopupMinHeight);
BuildInstanceStyles(popupConfirmContainer);
return mainLayout;
});
}
private DockPanel BuildContent(PopupConfirmContainer popupConfirmContainer, INameScope scope)
{
var wrapperLayout = new DockPanel()
{
LastChildFill = true
};
var contentLayout = new DockPanel()
{
LastChildFill = true
};
var iconContentPresenter = new ContentPresenter()
{
Name = IconContentPart
};
CreateTemplateParentBinding(iconContentPresenter, ContentPresenter.ContentProperty, PopupConfirmContainer.IconProperty);
CreateTemplateParentBinding(iconContentPresenter, ContentPresenter.IsVisibleProperty, PopupConfirmContainer.IconProperty,
BindingMode.Default,
ObjectConverters.IsNotNull);
DockPanel.SetDock(iconContentPresenter, Dock.Left);
wrapperLayout.Children.Add(iconContentPresenter);
wrapperLayout.Children.Add(contentLayout);
var titleTextBlock = new TextBlock()
{
Name = TitlePart,
TextWrapping = TextWrapping.NoWrap
};
CreateTemplateParentBinding(titleTextBlock, TextBlock.TextProperty, PopupConfirmContainer.TitleProperty);
DockPanel.SetDock(titleTextBlock, Dock.Top);
contentLayout.Children.Add(titleTextBlock);
var contentPresenter = new ContentPresenter()
{
Name = ContentPart
};
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, PopupConfirmContainer.ConfirmContentProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty, PopupConfirmContainer.ConfirmContentTemplateProperty);
contentLayout.Children.Add(contentPresenter);
return wrapperLayout;
}
private StackPanel BuildButtons(PopupConfirmContainer popupConfirmContainer, INameScope scope)
{
var buttonLayout = new StackPanel()
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Bottom
};
DockPanel.SetDock(buttonLayout, Dock.Bottom);
var cancelButton = new Button()
{
SizeType = SizeType.Small,
HorizontalAlignment = HorizontalAlignment.Right
};
TokenResourceBinder.CreateTokenBinding(cancelButton, Button.MarginProperty, PopupConfirmTokenResourceKey.ButtonMargin);
CreateTemplateParentBinding(cancelButton, Button.TextProperty, PopupConfirmContainer.CancelTextProperty);
CreateTemplateParentBinding(cancelButton, Button.IsVisibleProperty, PopupConfirmContainer.IsShowCancelButtonProperty);
buttonLayout.Children.Add(cancelButton);
var okButton = new Button()
{
Name = OkButtonPart,
SizeType = SizeType.Small,
HorizontalAlignment = HorizontalAlignment.Right
};
okButton.RegisterInNameScope(scope);
TokenResourceBinder.CreateTokenBinding(okButton, Button.MarginProperty, PopupConfirmTokenResourceKey.ButtonMargin);
CreateTemplateParentBinding(okButton, Button.TextProperty, PopupConfirmContainer.OkTextProperty);
CreateTemplateParentBinding(okButton, Button.ButtonTypeProperty, PopupConfirmContainer.OkButtonTypeProperty);
buttonLayout.Children.Add(okButton);
return buttonLayout;
}
protected override void BuildInstanceStyles(Control control)
{
{
var iconStyle = new Style(selector => selector.Name(IconContentPart).Child().OfType<PathIcon>());
iconStyle.Add(PathIcon.WidthProperty, GlobalTokenResourceKey.IconSizeLG);
iconStyle.Add(PathIcon.HeightProperty, GlobalTokenResourceKey.IconSizeLG);
iconStyle.Add(PathIcon.VerticalAlignmentProperty, VerticalAlignment.Top);
control.Styles.Add(iconStyle);
}
var infoStatusStyle = new Style(selector => selector.PropertyEquals(PopupConfirmContainer.ConfirmStatusProperty, PopupConfirmStatus.Info)
.Descendant().Name(IconContentPart).Child().OfType<PathIcon>());
infoStatusStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorPrimary);
control.Styles.Add(infoStatusStyle);
var warningStatusStyle = new Style(selector => selector.PropertyEquals(PopupConfirmContainer.ConfirmStatusProperty, PopupConfirmStatus.Warning)
.Descendant().Name(IconContentPart).Child().OfType<PathIcon>());
warningStatusStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorWarning);
control.Styles.Add(warningStatusStyle);
var errorStatusStyle = new Style(selector => selector.PropertyEquals(PopupConfirmContainer.ConfirmStatusProperty, PopupConfirmStatus.Error)
.Descendant().Name(IconContentPart).Child().OfType<PathIcon>());
errorStatusStyle.Add(PathIcon.NormalFilledBrushProperty, GlobalTokenResourceKey.ColorError);
control.Styles.Add(errorStatusStyle);
}
protected override void BuildStyles()
{
var commonStyle = new Style(selector => selector.Nesting());
var iconContentPresenter = new Style(selector => selector.Nesting().Template().Name(IconContentPart));
iconContentPresenter.Add(ContentPresenter.MarginProperty, PopupConfirmTokenResourceKey.IconMargin);
var titleStyle = new Style(selector => selector.Nesting().Template().Name(TitlePart));
titleStyle.Add(TextBlock.MarginProperty, PopupConfirmTokenResourceKey.TitleMargin);
titleStyle.Add(TextBlock.ForegroundProperty, GlobalTokenResourceKey.ColorTextHeading);
titleStyle.Add(TextBlock.FontWeightProperty, FontWeight.SemiBold);
commonStyle.Add(titleStyle);
var contentStyle = new Style(selector => selector.Nesting().Template().Name(ContentPart));
contentStyle.Add(ContentPresenter.MarginProperty, PopupConfirmTokenResourceKey.ContentContainerMargin);
commonStyle.Add(contentStyle);
commonStyle.Add(iconContentPresenter);
Add(commonStyle);
}
}
@@ -0,0 +1,39 @@
using AtomUI.Data;
using Avalonia.Controls;
namespace AtomUI.Controls;
internal class PopupConfirmFlyout : Flyout
{
internal WeakReference<PopupConfirm> PopupConfirmRef { get; set; }
public PopupConfirmFlyout(PopupConfirm popupConfirm)
{
PopupConfirmRef = new WeakReference<PopupConfirm>(popupConfirm);
}
protected override Control CreatePresenter()
{
var presenter = new FlyoutPresenter();
if (PopupConfirmRef.TryGetTarget(out var popupConfirm)) {
var popupConfirmContainer = new PopupConfirmContainer();
BindUtils.RelayBind(popupConfirm, PopupConfirm.OkTextProperty, popupConfirmContainer, PopupConfirmContainer.OkTextProperty);
BindUtils.RelayBind(popupConfirm, PopupConfirm.CancelTextProperty, popupConfirmContainer, PopupConfirmContainer.CancelTextProperty);
BindUtils.RelayBind(popupConfirm, PopupConfirm.OkButtonTypeProperty, popupConfirmContainer, PopupConfirmContainer.OkButtonTypeProperty);
BindUtils.RelayBind(popupConfirm, PopupConfirm.IsShowCancelButtonProperty, popupConfirmContainer, PopupConfirmContainer.IsShowCancelButtonProperty);
BindUtils.RelayBind(popupConfirm, PopupConfirm.TitleProperty, popupConfirmContainer, PopupConfirmContainer.TitleProperty);
BindUtils.RelayBind(popupConfirm, PopupConfirm.ConfirmStatusProperty, popupConfirmContainer, PopupConfirmContainer.ConfirmStatusProperty);
BindUtils.RelayBind(popupConfirm, PopupConfirm.IconProperty, popupConfirmContainer, PopupConfirmContainer.IconProperty);
BindUtils.RelayBind(popupConfirm, PopupConfirm.ConfirmContentProperty, popupConfirmContainer, PopupConfirmContainer.ConfirmContentProperty);
BindUtils.RelayBind(popupConfirm, PopupConfirm.ConfirmContentTemplateProperty, popupConfirmContainer, PopupConfirmContainer.ConfirmContentTemplateProperty);
presenter.Content = popupConfirmContainer;
}
BindUtils.RelayBind(this, IsShowArrowEffectiveProperty, presenter, IsShowArrowProperty);
CalculateShowArrowEffective();
SetupArrowPosition(Popup, presenter);
return presenter;
}
}
@@ -0,0 +1,56 @@
using AtomUI.Theme.TokenSystem;
using Avalonia;
namespace AtomUI.Controls;
[ControlDesignToken]
internal class PopupConfirmToken : AbstractControlDesignToken
{
public const string ID = "PopupConfirm";
public PopupConfirmToken()
: base(ID)
{
}
/// <summary>
/// 菜单 Popup 最小宽度
/// </summary>
public double PopupMinWidth { get; set; }
/// <summary>
/// 菜单 Popup 最小高度
/// </summary>
public double PopupMinHeight { get; set; }
/// <summary>
/// 按钮的外边距
/// </summary>
public Thickness ButtonMargin { get; set; }
/// <summary>
/// Icon 外边距
/// </summary>
public Thickness IconMargin { get; set; }
/// <summary>
/// 主内容区域外边距
/// </summary>
public Thickness ContentContainerMargin { get; set; }
/// <summary>
/// 标题栏外边距
/// </summary>
public Thickness TitleMargin { get; set; }
internal override void CalculateFromAlias()
{
base.CalculateFromAlias();
PopupMinWidth = 240;
PopupMinHeight= 80;
ButtonMargin = new Thickness(_globalToken.MarginXS, 0, 0, 0);
IconMargin = new Thickness(_globalToken.MarginXS, _globalToken.MarginXS + _globalToken.MarginXXS / 2, _globalToken.MarginXS, 0);
ContentContainerMargin = new Thickness(0, 0, 0, _globalToken.MarginXS);
TitleMargin = new Thickness(0, _globalToken.MarginXS, 0, _globalToken.MarginXS);
}
}
+2
View File
@@ -1,4 +1,5 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Data;
@@ -35,6 +36,7 @@ public abstract class BaseControlTheme : ControlTheme
}
protected virtual void BuildStyles() { }
protected virtual void BuildInstanceStyles(Control control) { }
protected virtual void NotifyPreBuild() { }
protected virtual void NotifyBuildCompleted() { }
+1
View File
@@ -32,6 +32,7 @@ public class ThemeManager : Styles, IThemeManager
public IReadOnlyList<string> CustomThemeDirs => _customThemeDirs;
public static ThemeManager Current { get; }
public string DefaultThemeId { get; set; }
public double RenderScaling { get; internal set; }
internal List<Type> ControlTokenTypes { get; set; }
private CultureInfo? _cultureInfo;