mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-29 18:38:16 +08:00
Refactor AnimationUtils
This commit is contained in:
parent
9d04394913
commit
95905bc890
26
src/AtomUI.Base/Utils/AnimationUtils.cs
Normal file
26
src/AtomUI.Base/Utils/AnimationUtils.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
|
||||
namespace AtomUI.Utils;
|
||||
|
||||
public class AnimationUtils
|
||||
{
|
||||
protected AnimationUtils() {}
|
||||
|
||||
public static ITransition CreateTransition<T>(AvaloniaProperty targetProperty,
|
||||
TimeSpan? duration = null,
|
||||
Easing? easing = null)
|
||||
where T : TransitionBase, new()
|
||||
{
|
||||
easing ??= new LinearEasing();
|
||||
duration ??= TimeSpan.FromMilliseconds(300);
|
||||
var transition = new T
|
||||
{
|
||||
Property = targetProperty,
|
||||
Easing = easing,
|
||||
Duration = duration.Value
|
||||
};
|
||||
return transition;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Palette;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Controls.Badge;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Controls.Badge;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
|
@ -5,8 +5,6 @@ using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,8 +1,8 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Diagnostics;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
|
@ -1,9 +1,8 @@
|
||||
using System.Globalization;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Automation.Peers;
|
||||
|
@ -1,8 +1,7 @@
|
||||
using AtomUI.Controls.Primitives;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Documents;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
|
@ -1,9 +1,8 @@
|
||||
using System.Globalization;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,8 +1,7 @@
|
||||
using AtomUI.Controls.Primitives;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
|
@ -1,8 +1,8 @@
|
||||
using System.ComponentModel;
|
||||
using System.Reactive.Disposables;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives.PopupPositioning;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives.PopupPositioning;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Diagnostics;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
@ -74,7 +74,7 @@ internal class PickerClearUpButtonTheme : BaseControlTheme
|
||||
PickerClearUpButton.IsInClearModeProperty);
|
||||
layout.Children.Add(clearButton);
|
||||
}
|
||||
|
||||
|
||||
protected override void BuildInstanceStyles(Control control)
|
||||
{
|
||||
var iconStyle = new Style(selector => selector.Name(InfoIconContentPart).Child().OfType<PathIcon>());
|
||||
|
@ -1,4 +1,4 @@
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Controls.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.LogicalTree;
|
||||
|
@ -1,3 +1,4 @@
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.LogicalTree;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,11 +1,8 @@
|
||||
using AtomUI.Controls.Primitives;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
@ -1,8 +1,8 @@
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
|
@ -1,11 +1,9 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Styling;
|
||||
|
||||
@ -15,12 +13,12 @@ namespace AtomUI.Controls;
|
||||
internal class HorizontalNavMenuTheme : BaseNavMenuTheme
|
||||
{
|
||||
public const string ID = "HorizontalNavMenu";
|
||||
|
||||
|
||||
public HorizontalNavMenuTheme()
|
||||
: base(typeof(NavMenu))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override string ThemeResourceKey()
|
||||
{
|
||||
return ID;
|
||||
|
@ -1,7 +1,6 @@
|
||||
using AtomUI.Controls.Primitives;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
@ -23,19 +22,19 @@ internal class InlineNavMenuItemTheme : BaseNavMenuItemTheme
|
||||
public const string MenuIndicatorIconLayoutPart = "PART_MenuIndicatorIconLayout";
|
||||
public const string ChildItemsPresenterPart = "PART_ChildItemsPresenter";
|
||||
public const string ChildItemsLayoutTransformPart = "PART_ChildItemsLayoutTransform";
|
||||
|
||||
|
||||
public InlineNavMenuItemTheme() : base(typeof(NavMenuItem))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public override string ThemeResourceKey()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
|
||||
protected override Control BuildMenuIndicatorIcon(INameScope scope)
|
||||
{
|
||||
var indicatorIcon = base.BuildMenuIndicatorIcon(scope);
|
||||
var indicatorIcon = base.BuildMenuIndicatorIcon(scope);
|
||||
var menuIndicatorIconPresenter = new Border()
|
||||
{
|
||||
Name = MenuIndicatorIconLayoutPart,
|
||||
@ -55,14 +54,14 @@ internal class InlineNavMenuItemTheme : BaseNavMenuItemTheme
|
||||
{
|
||||
Orientation = Orientation.Vertical
|
||||
};
|
||||
|
||||
|
||||
var headerContent = base.BuildMenuItemContent(navMenuItem, scope);
|
||||
|
||||
|
||||
var childItemsLayoutTransform = new MotionActorControl()
|
||||
{
|
||||
Name = ChildItemsLayoutTransformPart,
|
||||
Name = ChildItemsLayoutTransformPart,
|
||||
};
|
||||
TokenResourceBinder.CreateTokenBinding(childItemsLayoutTransform, MotionActorControl.MarginProperty,
|
||||
TokenResourceBinder.CreateTokenBinding(childItemsLayoutTransform, MotionActorControl.MarginProperty,
|
||||
NavMenuTokenResourceKey.VerticalItemsPanelSpacing, BindingPriority.Template,
|
||||
(v) =>
|
||||
{
|
||||
@ -74,7 +73,7 @@ internal class InlineNavMenuItemTheme : BaseNavMenuItemTheme
|
||||
return new Thickness();
|
||||
});
|
||||
childItemsLayoutTransform.RegisterInNameScope(scope);
|
||||
|
||||
|
||||
var itemsPresenter = new ItemsPresenter
|
||||
{
|
||||
Name = ChildItemsPresenterPart,
|
||||
@ -84,7 +83,7 @@ internal class InlineNavMenuItemTheme : BaseNavMenuItemTheme
|
||||
CreateTemplateParentBinding(itemsPresenter, ItemsPresenter.ItemsPanelProperty, NavMenuItem.ItemsPanelProperty);
|
||||
|
||||
childItemsLayoutTransform.Child = itemsPresenter;
|
||||
|
||||
|
||||
rootLayout.Children.Add(headerContent);
|
||||
rootLayout.Children.Add(childItemsLayoutTransform);
|
||||
return rootLayout;
|
||||
@ -109,8 +108,9 @@ internal class InlineNavMenuItemTheme : BaseNavMenuItemTheme
|
||||
{
|
||||
base.BuildStyles();
|
||||
BuildMenuIndicatorStyle();
|
||||
|
||||
var itemsPanelStyle = new Style(selector => selector.Nesting().Template().Name(ChildItemsPresenterPart).Child().OfType<StackPanel>());
|
||||
|
||||
var itemsPanelStyle = new Style(selector =>
|
||||
selector.Nesting().Template().Name(ChildItemsPresenterPart).Child().OfType<StackPanel>());
|
||||
itemsPanelStyle.Add(StackPanel.SpacingProperty, NavMenuTokenResourceKey.VerticalItemsPanelSpacing);
|
||||
Add(itemsPanelStyle);
|
||||
}
|
||||
@ -118,8 +118,9 @@ internal class InlineNavMenuItemTheme : BaseNavMenuItemTheme
|
||||
private void BuildMenuIndicatorStyle()
|
||||
{
|
||||
{
|
||||
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconLayoutPart));
|
||||
var transformOptions = new TransformOperations.Builder(1);
|
||||
var menuIndicatorStyle =
|
||||
new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconLayoutPart));
|
||||
var transformOptions = new TransformOperations.Builder(1);
|
||||
transformOptions.AppendRotate(MathUtils.Deg2Rad(90));
|
||||
menuIndicatorStyle.Add(Border.RenderTransformProperty, transformOptions.Build());
|
||||
menuIndicatorStyle.Add(Visual.IsVisibleProperty, true);
|
||||
@ -127,8 +128,9 @@ internal class InlineNavMenuItemTheme : BaseNavMenuItemTheme
|
||||
}
|
||||
var openSubMenuStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Open));
|
||||
{
|
||||
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconLayoutPart));
|
||||
var transformOptions = new TransformOperations.Builder(1);
|
||||
var menuIndicatorStyle =
|
||||
new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconLayoutPart));
|
||||
var transformOptions = new TransformOperations.Builder(1);
|
||||
transformOptions.AppendRotate(MathUtils.Deg2Rad(-90));
|
||||
menuIndicatorStyle.Add(Border.RenderTransformProperty, transformOptions.Build());
|
||||
openSubMenuStyle.Add(menuIndicatorStyle);
|
||||
@ -136,7 +138,8 @@ internal class InlineNavMenuItemTheme : BaseNavMenuItemTheme
|
||||
Add(openSubMenuStyle);
|
||||
var emptySubMenuStyle = new Style(selector => selector.Nesting().Class(StdPseudoClass.Empty));
|
||||
{
|
||||
var menuIndicatorStyle = new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconLayoutPart));
|
||||
var menuIndicatorStyle =
|
||||
new Style(selector => selector.Nesting().Template().Name(MenuIndicatorIconLayoutPart));
|
||||
menuIndicatorStyle.Add(Visual.IsVisibleProperty, false);
|
||||
emptySubMenuStyle.Add(menuIndicatorStyle);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
using System.Windows.Input;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Input;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Templates;
|
||||
@ -14,23 +14,23 @@ internal class NavMenuItemTheme : BaseNavMenuItemTheme
|
||||
{
|
||||
public const string ItemsPresenterPart = "PART_ItemsPresenter";
|
||||
public const string PopupFramePart = "PART_PopupFrame";
|
||||
|
||||
|
||||
public NavMenuItemTheme()
|
||||
: base(typeof(NavMenuItem))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected NavMenuItemTheme(Type targetType) : base(targetType)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected override void BuildExtraItem(Panel layout, INameScope scope)
|
||||
{
|
||||
var popup = CreateMenuPopup();
|
||||
popup.RegisterInNameScope(scope);
|
||||
layout.Children.Add(popup);
|
||||
}
|
||||
|
||||
|
||||
protected Popup CreateMenuPopup()
|
||||
{
|
||||
var popup = new Popup
|
||||
@ -45,7 +45,7 @@ internal class NavMenuItemTheme : BaseNavMenuItemTheme
|
||||
{
|
||||
Name = PopupFramePart
|
||||
};
|
||||
|
||||
|
||||
TokenResourceBinder.CreateTokenBinding(popup, Popup.MarginToAnchorProperty,
|
||||
NavMenuTokenResourceKey.TopLevelItemPopupMarginToAnchor);
|
||||
TokenResourceBinder.CreateTokenBinding(border, Border.CornerRadiusProperty,
|
||||
@ -80,11 +80,12 @@ internal class NavMenuItemTheme : BaseNavMenuItemTheme
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
base.BuildStyles();
|
||||
var itemsPanelStyle = new Style(selector => selector.Nesting().Template().Name(ItemsPresenterPart).Child().OfType<StackPanel>());
|
||||
var itemsPanelStyle = new Style(selector =>
|
||||
selector.Nesting().Template().Name(ItemsPresenterPart).Child().OfType<StackPanel>());
|
||||
itemsPanelStyle.Add(StackPanel.SpacingProperty, NavMenuTokenResourceKey.VerticalItemsPanelSpacing);
|
||||
Add(itemsPanelStyle);
|
||||
|
||||
@ -93,8 +94,9 @@ internal class NavMenuItemTheme : BaseNavMenuItemTheme
|
||||
popupFrameStyle.Add(Border.BackgroundProperty, GlobalTokenResourceKey.ColorBgContainer);
|
||||
Add(popupFrameStyle);
|
||||
}
|
||||
|
||||
var darkCommonStyle = new Style(selector => selector.Nesting().PropertyEquals(NavMenuItem.IsDarkStyleProperty, true));
|
||||
|
||||
var darkCommonStyle =
|
||||
new Style(selector => selector.Nesting().PropertyEquals(NavMenuItem.IsDarkStyleProperty, true));
|
||||
{
|
||||
var popupFrameStyle = new Style(selector => selector.Nesting().Template().Name(PopupFramePart));
|
||||
popupFrameStyle.Add(Border.BackgroundProperty, NavMenuTokenResourceKey.DarkItemBg);
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,8 +1,8 @@
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
|
@ -1,12 +1,8 @@
|
||||
using AtomUI.Controls.Primitives;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,8 +1,8 @@
|
||||
using System.Reactive.Disposables;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.MotionScene;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Diagnostics;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
@ -10,6 +10,7 @@ using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Media;
|
||||
using AnimationUtils = AtomUI.Controls.Utils.AnimationUtils;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,8 +1,7 @@
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,4 +1,5 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Automation.Peers;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using System.Globalization;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using System.Globalization;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Converters;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
|
@ -1,9 +1,8 @@
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
|
@ -1,9 +1,8 @@
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,6 +1,6 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,7 +1,7 @@
|
||||
using AtomUI.Reflection;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Palette;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Diagnostics;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
|
@ -2,9 +2,8 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
@ -1,5 +1,6 @@
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
|
@ -3,7 +3,6 @@ using AtomUI.Media;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.Utils;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
|
32
src/AtomUI.Controls/Utils/AnimationUtils.cs
Normal file
32
src/AtomUI.Controls/Utils/AnimationUtils.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace AtomUI.Controls.Utils;
|
||||
|
||||
public sealed class AnimationUtils : AtomUI.Utils.AnimationUtils
|
||||
{
|
||||
public static ITransition CreateTransition<T>(AvaloniaProperty targetProperty,
|
||||
TokenResourceKey? durationResourceKey = null,
|
||||
Easing? easing = null)
|
||||
where T : TransitionBase, new()
|
||||
{
|
||||
easing ??= new LinearEasing();
|
||||
durationResourceKey ??= GlobalTokenResourceKey.MotionDurationMid;
|
||||
var transition = new T
|
||||
{
|
||||
Property = targetProperty,
|
||||
Easing = easing
|
||||
};
|
||||
var application = Application.Current;
|
||||
if (application is not null)
|
||||
{
|
||||
transition.Bind(TransitionBase.DurationProperty, application.GetResourceObservable(durationResourceKey));
|
||||
}
|
||||
|
||||
return transition;
|
||||
}
|
||||
}
|
@ -7,4 +7,8 @@
|
||||
<PackageReference Include="Avalonia"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AtomUI.Base\AtomUI.Base.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -3,7 +3,7 @@ using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Icon;
|
||||
|
||||
public class IconImage : DrawingImage, IImage
|
||||
internal class IconImage : DrawingImage, IImage
|
||||
{
|
||||
public static readonly StyledProperty<IconInfo> DataProperty = AvaloniaProperty.Register<
|
||||
IconImage,
|
||||
|
667
src/AtomUI.Icon/PathIcon.cs
Normal file
667
src/AtomUI.Icon/PathIcon.cs
Normal file
@ -0,0 +1,667 @@
|
||||
using AtomUI.Media;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Reactive;
|
||||
using Avalonia.Rendering;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Icon;
|
||||
|
||||
public sealed class PathIcon : Control, ICustomHitTest
|
||||
{
|
||||
public static readonly StyledProperty<string> KindProperty = AvaloniaProperty.Register<PathIcon, string>(
|
||||
nameof(Kind), string.Empty);
|
||||
|
||||
public static readonly StyledProperty<IconAnimation> LoadingAnimationProperty =
|
||||
AvaloniaProperty.Register<PathIcon, IconAnimation>(
|
||||
nameof(LoadingAnimation));
|
||||
|
||||
public static readonly StyledProperty<string?> PackageProviderProperty =
|
||||
AvaloniaProperty.Register<PathIcon, string?>(
|
||||
nameof(PackageProvider));
|
||||
|
||||
// Fill 和 Outline 支持的颜色
|
||||
public static readonly StyledProperty<IBrush?> NormalFilledBrushProperty =
|
||||
AvaloniaProperty.Register<PathIcon, IBrush?>(
|
||||
nameof(NormalFilledBrush));
|
||||
|
||||
public static readonly StyledProperty<IBrush?> ActiveFilledBrushProperty =
|
||||
AvaloniaProperty.Register<PathIcon, IBrush?>(
|
||||
nameof(ActiveFilledBrush));
|
||||
|
||||
public static readonly StyledProperty<IBrush?> SelectedFilledBrushProperty =
|
||||
AvaloniaProperty.Register<PathIcon, IBrush?>(
|
||||
nameof(SelectedFilledBrush));
|
||||
|
||||
public static readonly StyledProperty<IBrush?> DisabledFilledBrushProperty =
|
||||
AvaloniaProperty.Register<PathIcon, IBrush?>(
|
||||
nameof(DisabledFilledBrush));
|
||||
|
||||
// TwoTone 类型的颜色
|
||||
public static readonly StyledProperty<IBrush?> PrimaryFilledBrushProperty =
|
||||
AvaloniaProperty.Register<PathIcon, IBrush?>(
|
||||
nameof(PrimaryFilledBrush));
|
||||
|
||||
public static readonly StyledProperty<IBrush?> SecondaryFilledBrushProperty =
|
||||
AvaloniaProperty.Register<PathIcon, IBrush?>(
|
||||
nameof(SecondaryFilledBrush));
|
||||
|
||||
public static readonly StyledProperty<TimeSpan> LoadingAnimationDurationProperty =
|
||||
AvaloniaProperty.Register<PathIcon, TimeSpan>(
|
||||
nameof(LoadingAnimationDuration), TimeSpan.FromSeconds(1));
|
||||
|
||||
public static readonly StyledProperty<TimeSpan> FillAnimationDurationProperty =
|
||||
AvaloniaProperty.Register<PathIcon, TimeSpan>(
|
||||
nameof(FillAnimationDuration), TimeSpan.FromSeconds(300));
|
||||
|
||||
public static readonly StyledProperty<IconMode> IconModeProperty =
|
||||
AvaloniaProperty.Register<PathIcon, IconMode>(nameof(IconMode));
|
||||
|
||||
public string Kind
|
||||
{
|
||||
get => GetValue(KindProperty);
|
||||
set => SetValue(KindProperty, value);
|
||||
}
|
||||
|
||||
public string? PackageProvider
|
||||
{
|
||||
get => GetValue(PackageProviderProperty);
|
||||
set => SetValue(PackageProviderProperty, value);
|
||||
}
|
||||
|
||||
public IBrush? NormalFilledBrush
|
||||
{
|
||||
get => GetValue(NormalFilledBrushProperty);
|
||||
set => SetValue(NormalFilledBrushProperty, value);
|
||||
}
|
||||
|
||||
public IBrush? ActiveFilledBrush
|
||||
{
|
||||
get => GetValue(ActiveFilledBrushProperty);
|
||||
set => SetValue(ActiveFilledBrushProperty, value);
|
||||
}
|
||||
|
||||
public IBrush? SelectedFilledBrush
|
||||
{
|
||||
get => GetValue(SelectedFilledBrushProperty);
|
||||
set => SetValue(SelectedFilledBrushProperty, value);
|
||||
}
|
||||
|
||||
public IBrush? DisabledFilledBrush
|
||||
{
|
||||
get => GetValue(DisabledFilledBrushProperty);
|
||||
set => SetValue(DisabledFilledBrushProperty, value);
|
||||
}
|
||||
|
||||
public IBrush? PrimaryFilledBrush
|
||||
{
|
||||
get => GetValue(PrimaryFilledBrushProperty);
|
||||
set => SetValue(PrimaryFilledBrushProperty, value);
|
||||
}
|
||||
|
||||
public IBrush? SecondaryFilledBrush
|
||||
{
|
||||
get => GetValue(SecondaryFilledBrushProperty);
|
||||
set => SetValue(SecondaryFilledBrushProperty, value);
|
||||
}
|
||||
|
||||
public TimeSpan LoadingAnimationDuration
|
||||
{
|
||||
get => GetValue(LoadingAnimationDurationProperty);
|
||||
set => SetValue(LoadingAnimationDurationProperty, value);
|
||||
}
|
||||
|
||||
public TimeSpan FillAnimationDuration
|
||||
{
|
||||
get => GetValue(FillAnimationDurationProperty);
|
||||
set => SetValue(FillAnimationDurationProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// PathIcon 的模式,只对 Outlined 和 Filled 类型有效
|
||||
/// </summary>
|
||||
public IconMode IconMode
|
||||
{
|
||||
get => GetValue(IconModeProperty);
|
||||
set => SetValue(IconModeProperty, value);
|
||||
}
|
||||
|
||||
private static readonly StyledProperty<IBrush?> FilledBrushProperty
|
||||
= AvaloniaProperty.Register<ToggleSwitch, IBrush?>(
|
||||
nameof(IBrush));
|
||||
|
||||
/// <summary>
|
||||
/// 当是非 TwoTone icon 的时候,填充色是支持渐变的
|
||||
/// </summary>
|
||||
private IBrush? FilledBrush
|
||||
{
|
||||
get => GetValue(FilledBrushProperty);
|
||||
set => SetValue(FilledBrushProperty, value);
|
||||
}
|
||||
|
||||
public IconThemeType ThemeType => _iconInfo?.ThemeType ?? IconThemeType.Filled;
|
||||
|
||||
public IconAnimation LoadingAnimation
|
||||
{
|
||||
get => GetValue(LoadingAnimationProperty);
|
||||
set => SetValue(LoadingAnimationProperty, value);
|
||||
}
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
internal static readonly StyledProperty<double> AngleAnimationRotateProperty =
|
||||
AvaloniaProperty.Register<PathIcon, double>(
|
||||
nameof(AngleAnimationRotate));
|
||||
|
||||
internal double AngleAnimationRotate
|
||||
{
|
||||
get => GetValue(AngleAnimationRotateProperty);
|
||||
set => SetValue(AngleAnimationRotateProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private Animation? _animation;
|
||||
private CancellationTokenSource? _animationCancellationTokenSource;
|
||||
private WeakReference<IIconPackageProvider>? _iconPackageRef;
|
||||
private readonly List<Matrix> _transforms;
|
||||
private readonly List<Geometry> _sourceGeometriesData;
|
||||
private IconInfo? _iconInfo;
|
||||
private Rect _viewBox;
|
||||
|
||||
static PathIcon()
|
||||
{
|
||||
AffectsGeometry(KindProperty, PackageProviderProperty);
|
||||
AffectsMeasure<PathIcon>(HeightProperty, WidthProperty);
|
||||
AffectsRender<PathIcon>(IconModeProperty,
|
||||
FilledBrushProperty,
|
||||
PrimaryFilledBrushProperty,
|
||||
SecondaryFilledBrushProperty);
|
||||
HorizontalAlignmentProperty.OverrideDefaultValue<PathIcon>(HorizontalAlignment.Left);
|
||||
VerticalAlignmentProperty.OverrideDefaultValue<PathIcon>(VerticalAlignment.Center);
|
||||
}
|
||||
|
||||
public PathIcon()
|
||||
{
|
||||
var rotateTransform = new RotateTransform();
|
||||
RenderTransform = rotateTransform;
|
||||
_sourceGeometriesData = new List<Geometry>();
|
||||
_transforms = new List<Matrix>();
|
||||
}
|
||||
|
||||
private void SetupTransitions()
|
||||
{
|
||||
Transitions ??= new Transitions()
|
||||
{
|
||||
AnimationUtils.CreateTransition<SolidColorBrushTransition>(FilledBrushProperty, FillAnimationDuration)
|
||||
};
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (change.Property == KindProperty)
|
||||
{
|
||||
// TODO 这里不存在记录日志吗?暂时构造一个默认的
|
||||
if (VisualRoot is not null)
|
||||
{
|
||||
BuildSourceRenderData();
|
||||
}
|
||||
}
|
||||
else if (change.Property == IsEnabledProperty)
|
||||
{
|
||||
// TODO 这个地方需要优化一点,是否需要保存老的,当状态为 Enabled 的时候进行还原
|
||||
if (!IsEnabled)
|
||||
{
|
||||
IconMode = IconMode.Disabled;
|
||||
}
|
||||
}
|
||||
else if (change.Property == NormalFilledBrushProperty ||
|
||||
change.Property == ActiveFilledBrushProperty ||
|
||||
change.Property == SelectedFilledBrushProperty ||
|
||||
change.Property == DisabledFilledBrushProperty ||
|
||||
change.Property == PrimaryFilledBrushProperty ||
|
||||
change.Property == SecondaryFilledBrushProperty ||
|
||||
change.Property == IconModeProperty)
|
||||
{
|
||||
SetupFilledBrush();
|
||||
}
|
||||
else if (change.Property == AngleAnimationRotateProperty)
|
||||
{
|
||||
SetCurrentValue(RenderTransformProperty, new RotateTransform(AngleAnimationRotate));
|
||||
}
|
||||
|
||||
if (VisualRoot is not null)
|
||||
{
|
||||
if (change.Property == LoadingAnimationProperty)
|
||||
{
|
||||
SetupRotateAnimation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupRotateAnimation()
|
||||
{
|
||||
if (_animation is not null)
|
||||
{
|
||||
_animationCancellationTokenSource?.Cancel();
|
||||
_animation = null;
|
||||
_animationCancellationTokenSource = null;
|
||||
}
|
||||
|
||||
if (LoadingAnimation == IconAnimation.Spin || LoadingAnimation == IconAnimation.Pulse)
|
||||
{
|
||||
_animation = new Animation
|
||||
{
|
||||
Duration = LoadingAnimationDuration,
|
||||
IterationCount = new IterationCount(ulong.MaxValue),
|
||||
Children =
|
||||
{
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue(0d),
|
||||
Setters = { new Setter(AngleAnimationRotateProperty, 0d) }
|
||||
},
|
||||
new KeyFrame
|
||||
{
|
||||
Cue = new Cue(1d),
|
||||
Setters = { new Setter(AngleAnimationRotateProperty, 360d) }
|
||||
}
|
||||
}
|
||||
};
|
||||
if (LoadingAnimation == IconAnimation.Pulse)
|
||||
{
|
||||
_animation.Easing = new PulseEasing();
|
||||
}
|
||||
|
||||
if (VisualRoot is not null)
|
||||
{
|
||||
_animationCancellationTokenSource = new CancellationTokenSource();
|
||||
_animation.RunAsync(this, _animationCancellationTokenSource.Token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupFilledBrush()
|
||||
{
|
||||
var colorInfo = _iconInfo?.ColorInfo;
|
||||
if (IconMode == IconMode.Normal)
|
||||
{
|
||||
if (NormalFilledBrush is not null)
|
||||
{
|
||||
FilledBrush = NormalFilledBrush;
|
||||
}
|
||||
else if (colorInfo.HasValue)
|
||||
{
|
||||
FilledBrush = new SolidColorBrush(colorInfo.Value.NormalColor);
|
||||
}
|
||||
}
|
||||
else if (IconMode == IconMode.Active)
|
||||
{
|
||||
if (ActiveFilledBrush is not null)
|
||||
{
|
||||
FilledBrush = ActiveFilledBrush;
|
||||
}
|
||||
else if (NormalFilledBrush is not null)
|
||||
{
|
||||
FilledBrush = NormalFilledBrush;
|
||||
}
|
||||
else if (colorInfo.HasValue)
|
||||
{
|
||||
FilledBrush = new SolidColorBrush(colorInfo.Value.ActiveColor);
|
||||
}
|
||||
}
|
||||
else if (IconMode == IconMode.Selected)
|
||||
{
|
||||
if (SelectedFilledBrush is not null)
|
||||
{
|
||||
FilledBrush = SelectedFilledBrush;
|
||||
}
|
||||
else if (NormalFilledBrush is not null)
|
||||
{
|
||||
FilledBrush = NormalFilledBrush;
|
||||
}
|
||||
else if (colorInfo.HasValue)
|
||||
{
|
||||
FilledBrush = new SolidColorBrush(colorInfo.Value.SelectedColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DisabledFilledBrush is not null)
|
||||
{
|
||||
FilledBrush = DisabledFilledBrush;
|
||||
}
|
||||
else if (NormalFilledBrush is not null)
|
||||
{
|
||||
FilledBrush = NormalFilledBrush;
|
||||
}
|
||||
else if (colorInfo.HasValue)
|
||||
{
|
||||
FilledBrush = new SolidColorBrush(colorInfo.Value.DisabledColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalidates the geometry of this shape.
|
||||
/// </summary>
|
||||
private void InvalidateGeometry()
|
||||
{
|
||||
if (_animation is not null)
|
||||
{
|
||||
_animationCancellationTokenSource?.Cancel();
|
||||
}
|
||||
|
||||
_sourceGeometriesData.Clear();
|
||||
_transforms.Clear();
|
||||
_iconInfo = null;
|
||||
InvalidateMeasure();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Marks a property as affecting the shape's geometry.
|
||||
/// </summary>
|
||||
/// <param name="properties">The properties.</param>
|
||||
/// <remarks>
|
||||
/// After a call to this method in a control's static constructor, any change to the
|
||||
/// property will cause <see cref="InvalidateGeometry" /> to be called on the element.
|
||||
/// </remarks>
|
||||
private static void AffectsGeometry(params AvaloniaProperty[] properties)
|
||||
{
|
||||
foreach (var property in properties)
|
||||
{
|
||||
property.Changed.Subscribe(new AnonymousObserver<AvaloniaPropertyChangedEventArgs>(e =>
|
||||
{
|
||||
if (e.Sender is PathIcon icon)
|
||||
{
|
||||
AffectsGeometryInvalidate(icon, e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
private static void AffectsGeometryInvalidate(PathIcon control, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
// If the geometry is invalidated when Bounds changes, only invalidate when the Size
|
||||
// portion changes.
|
||||
if (e.Property == BoundsProperty)
|
||||
{
|
||||
var oldBounds = (Rect)e.OldValue!;
|
||||
var newBounds = (Rect)e.NewValue!;
|
||||
if (oldBounds.Size == newBounds.Size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
control.InvalidateGeometry();
|
||||
}
|
||||
|
||||
private void BuildSourceRenderData()
|
||||
{
|
||||
if (_sourceGeometriesData.Count > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var manager = IconManager.Current;
|
||||
PackageProvider ??= manager.DefaultPackage;
|
||||
|
||||
var iconPackage = manager.GetIconProvider(PackageProvider);
|
||||
// 这里报错还是?
|
||||
if (iconPackage is not null)
|
||||
{
|
||||
_iconPackageRef = new WeakReference<IIconPackageProvider>(iconPackage);
|
||||
}
|
||||
|
||||
if (_iconPackageRef != null && _iconPackageRef.TryGetTarget(out var iconPackageProvider))
|
||||
{
|
||||
// TODO 这里可能需要优化,针对 IconInfo 的拷贝问题
|
||||
_iconInfo = iconPackageProvider.GetIcon(Kind) ?? new IconInfo();
|
||||
foreach (var geometryData in _iconInfo.Data)
|
||||
{
|
||||
_sourceGeometriesData.Add(Geometry.Parse(geometryData.PathData));
|
||||
}
|
||||
|
||||
_viewBox = _iconInfo!.ViewBox;
|
||||
// 先求最大的 bounds
|
||||
// 裁剪边距算法,暂时先注释掉
|
||||
Geometry? combined = null;
|
||||
foreach (var geometry in _sourceGeometriesData)
|
||||
{
|
||||
if (combined is null)
|
||||
{
|
||||
combined = geometry;
|
||||
}
|
||||
else
|
||||
{
|
||||
combined = new CombinedGeometry(combined, geometry);
|
||||
}
|
||||
}
|
||||
|
||||
var combinedBounds = combined!.Bounds;
|
||||
|
||||
var marginHorizontal = Math.Min(_iconInfo.ViewBox.Right - combinedBounds.Right, combinedBounds.X);
|
||||
var marginVertical = Math.Min(_iconInfo.ViewBox.Bottom - combinedBounds.Bottom, combinedBounds.Y);
|
||||
var margin = Math.Min(marginHorizontal, marginVertical);
|
||||
|
||||
var scaleX = 1 - margin / _viewBox.Width;
|
||||
var scaleY = 1 - margin / _viewBox.Height;
|
||||
|
||||
if (margin > 0)
|
||||
{
|
||||
for (var i = 0; i < _sourceGeometriesData.Count; i++)
|
||||
{
|
||||
var geometry = _sourceGeometriesData[i];
|
||||
var cloned = geometry.Clone();
|
||||
var offsetX = -margin / 2;
|
||||
var offsetY = -margin / 2;
|
||||
var matrix = Matrix.CreateTranslation(offsetX, offsetY);
|
||||
matrix = matrix * Matrix.CreateScale(scaleX, scaleY);
|
||||
cloned.Transform = new MatrixTransform(matrix);
|
||||
_sourceGeometriesData[i] = cloned;
|
||||
}
|
||||
|
||||
_viewBox = combined!.Bounds;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
SetupTransitions();
|
||||
SetupRotateAnimation();
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
if (_sourceGeometriesData.Count == 0)
|
||||
{
|
||||
BuildSourceRenderData();
|
||||
SetupFilledBrush();
|
||||
}
|
||||
if (_animation is not null && _animationCancellationTokenSource is null)
|
||||
{
|
||||
_animationCancellationTokenSource = new CancellationTokenSource();
|
||||
_animation.RunAsync(this, _animationCancellationTokenSource.Token);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnDetachedFromVisualTree(e);
|
||||
_animationCancellationTokenSource?.Cancel();
|
||||
_animationCancellationTokenSource = null;
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
if (_sourceGeometriesData.Count == 0)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
Size targetSize = default;
|
||||
for (var i = 0; i < _sourceGeometriesData.Count; i++)
|
||||
{
|
||||
var sourceGeometry = _sourceGeometriesData[i];
|
||||
var currentSize = CalculateSizeAndTransform(availableSize, sourceGeometry.Bounds).size;
|
||||
targetSize = new Size(Math.Max(targetSize.Width, currentSize.Width),
|
||||
Math.Min(targetSize.Height, currentSize.Height));
|
||||
}
|
||||
|
||||
return targetSize;
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
_transforms.Clear();
|
||||
// This should probably use GetRenderBounds(strokeThickness) but then the calculations
|
||||
// will multiply the stroke thickness as well, which isn't correct.
|
||||
for (var i = 0; i < _sourceGeometriesData.Count; i++)
|
||||
{
|
||||
var sourceGeometry = _sourceGeometriesData[i];
|
||||
var (_, transform) = CalculateSizeAndTransform(finalSize, sourceGeometry.Bounds);
|
||||
_transforms.Insert(i, transform);
|
||||
}
|
||||
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
if (IsVisible &&
|
||||
_sourceGeometriesData.Count > 0 &&
|
||||
Bounds.Width > 0 &&
|
||||
Bounds.Width > 0)
|
||||
{
|
||||
for (var i = 0; i < _sourceGeometriesData.Count; i++)
|
||||
{
|
||||
var renderedGeometry = _sourceGeometriesData[i];
|
||||
var geometryData = _iconInfo!.Data[i];
|
||||
IBrush? fillBrush = null;
|
||||
if (_iconInfo.ThemeType == IconThemeType.TwoTone)
|
||||
{
|
||||
var colorInfo = _iconInfo.TwoToneColorInfo;
|
||||
if (colorInfo.HasValue)
|
||||
{
|
||||
if (geometryData.IsPrimary)
|
||||
{
|
||||
if (PrimaryFilledBrush is not null)
|
||||
{
|
||||
fillBrush = PrimaryFilledBrush;
|
||||
}
|
||||
else
|
||||
{
|
||||
fillBrush = new SolidColorBrush(colorInfo.Value.PrimaryColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SecondaryFilledBrush is not null)
|
||||
{
|
||||
fillBrush = SecondaryFilledBrush;
|
||||
}
|
||||
else
|
||||
{
|
||||
fillBrush = new SolidColorBrush(colorInfo.Value.SecondaryColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fillBrush = FilledBrush;
|
||||
}
|
||||
|
||||
using var state = context.PushTransform(_transforms[i]);
|
||||
context.DrawGeometry(fillBrush, null, renderedGeometry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private (Size size, Matrix transform) CalculateSizeAndTransform(Size availableSize, Rect shapeBounds)
|
||||
{
|
||||
var shapeSize = new Size(shapeBounds.Width, shapeBounds.Height);
|
||||
var desiredX = availableSize.Width;
|
||||
var desiredY = availableSize.Height;
|
||||
var sx = 0.0;
|
||||
var sy = 0.0;
|
||||
var viewBoxWidth = _viewBox.Width;
|
||||
var viewBoxHeight = _viewBox.Height;
|
||||
|
||||
// 计算大小的比例因子
|
||||
var shapeWidthScale = shapeBounds.Width / viewBoxWidth;
|
||||
var shapeHeightScale = shapeBounds.Height / viewBoxHeight;
|
||||
|
||||
// 计算位移的比例因子
|
||||
var offsetXScale = Math.Floor(availableSize.Width / viewBoxWidth);
|
||||
var offsetYScale = Math.Floor(availableSize.Height / viewBoxHeight);
|
||||
|
||||
var offsetX = shapeBounds.X;
|
||||
var offsetY = shapeBounds.Y;
|
||||
|
||||
shapeSize = shapeBounds.Size;
|
||||
|
||||
if (double.IsInfinity(availableSize.Width))
|
||||
{
|
||||
desiredX = shapeSize.Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
desiredX = availableSize.Width * shapeWidthScale;
|
||||
offsetX *= offsetXScale;
|
||||
}
|
||||
|
||||
if (double.IsInfinity(availableSize.Height))
|
||||
{
|
||||
desiredY = shapeSize.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
desiredY = availableSize.Height * shapeHeightScale;
|
||||
offsetY *= offsetYScale;
|
||||
}
|
||||
|
||||
var translate = Matrix.CreateTranslation(-offsetX, -offsetY);
|
||||
if (shapeBounds.Width > 0)
|
||||
{
|
||||
sx = desiredX / shapeSize.Width;
|
||||
}
|
||||
|
||||
if (shapeBounds.Height > 0)
|
||||
{
|
||||
sy = desiredY / shapeSize.Height;
|
||||
}
|
||||
|
||||
if (double.IsInfinity(availableSize.Width))
|
||||
{
|
||||
sx = sy;
|
||||
}
|
||||
|
||||
if (double.IsInfinity(availableSize.Height))
|
||||
{
|
||||
sy = sx;
|
||||
}
|
||||
|
||||
sx = sy = Math.Min(sx, sy);
|
||||
|
||||
translate = translate * Matrix.CreateScale(sx, sy);
|
||||
var size = new Size(shapeSize.Width * sx, shapeSize.Height * sy);
|
||||
return (size, translate);
|
||||
}
|
||||
|
||||
public bool HitTest(Point point)
|
||||
{
|
||||
var targetRect = new Rect(0, 0, DesiredSize.Width, DesiredSize.Height);
|
||||
return targetRect.Contains(point);
|
||||
}
|
||||
}
|
@ -5,7 +5,7 @@ using Avalonia.Data;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Utils;
|
||||
namespace AtomUI.Theme.Data;
|
||||
|
||||
public static class TokenResourceBinder
|
||||
{
|
||||
|
@ -1,64 +0,0 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Animation.Easings;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Theme.Utils;
|
||||
|
||||
public static class AnimationUtils
|
||||
{
|
||||
public static Animation RunAnimation<ValueType>(AvaloniaProperty targetProperty,
|
||||
ValueType startValue,
|
||||
ValueType endValue,
|
||||
TimeSpan duration,
|
||||
Easing? easing = null)
|
||||
{
|
||||
if (easing is null)
|
||||
{
|
||||
easing = new LinearEasing();
|
||||
}
|
||||
|
||||
var animation = new Animation
|
||||
{
|
||||
Duration = duration,
|
||||
Easing = easing,
|
||||
FillMode = FillMode.Backward,
|
||||
Children =
|
||||
{
|
||||
new KeyFrame
|
||||
{
|
||||
Setters = { new Setter(targetProperty, startValue) }, KeyTime = TimeSpan.FromMilliseconds(0)
|
||||
},
|
||||
new KeyFrame
|
||||
{
|
||||
Setters = { new Setter(targetProperty, endValue) }, KeyTime = duration
|
||||
}
|
||||
}
|
||||
};
|
||||
return animation;
|
||||
}
|
||||
|
||||
public static ITransition CreateTransition<T>(AvaloniaProperty targetProperty,
|
||||
TokenResourceKey? durationResourceKey = null,
|
||||
Easing? easing = null)
|
||||
where T : TransitionBase, new()
|
||||
{
|
||||
easing ??= new LinearEasing();
|
||||
durationResourceKey ??= GlobalTokenResourceKey.MotionDurationMid;
|
||||
var transition = new T
|
||||
{
|
||||
Property = targetProperty,
|
||||
Easing = easing
|
||||
};
|
||||
var application = Application.Current;
|
||||
if (application is not null)
|
||||
{
|
||||
transition.Bind(TransitionBase.DurationProperty, application.GetResourceObservable(durationResourceKey));
|
||||
}
|
||||
|
||||
return transition;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user