mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-27 21:58:05 +08:00
Merge branch 'feature/popupconfirm' into develop
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+1
@@ -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());
|
||||
|
||||
+1
@@ -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));
|
||||
|
||||
+10
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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() { }
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user