mirror of
https://gitee.com/chinware/atomui.git
synced 2024-12-02 03:47:52 +08:00
Refactor DotBadgeAdorner motion
This commit is contained in:
parent
6fc24d2bd8
commit
668d50ff7f
@ -1,14 +1,13 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using Avalonia;
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Animation;
|
using Avalonia.Animation;
|
||||||
using Avalonia.Animation.Easings;
|
using Avalonia.Animation.Easings;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.MotionScene;
|
||||||
|
|
||||||
internal static partial class MotionFactory
|
internal static partial class MotionFactory
|
||||||
{
|
{
|
||||||
public static MotionConfig BuildCollapseMotion(Direction direction, TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildCollapseMotion(Direction direction, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseOut();
|
easing ??= new CubicEaseOut();
|
||||||
@ -104,10 +103,10 @@ internal static partial class MotionFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildExpandMotion(Direction direction, TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildExpandMotion(Direction direction, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseIn();
|
easing ??= new CubicEaseIn();
|
||||||
@ -204,6 +203,6 @@ internal static partial class MotionFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ using Avalonia.Controls;
|
|||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Media.Transformation;
|
using Avalonia.Media.Transformation;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Primitives;
|
namespace AtomUI.MotionScene;
|
||||||
|
|
||||||
public class MotionActorControl : Decorator
|
public class MotionActorControl : Decorator
|
||||||
{
|
{
|
||||||
@ -13,12 +13,21 @@ public class MotionActorControl : Decorator
|
|||||||
public static readonly StyledProperty<TransformOperations?> MotionTransformProperty =
|
public static readonly StyledProperty<TransformOperations?> MotionTransformProperty =
|
||||||
AvaloniaProperty.Register<MotionActorControl, TransformOperations?>(nameof(MotionTransform));
|
AvaloniaProperty.Register<MotionActorControl, TransformOperations?>(nameof(MotionTransform));
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> UseRenderTransformProperty =
|
||||||
|
AvaloniaProperty.Register<LayoutTransformControl, bool>(nameof(UseRenderTransform));
|
||||||
|
|
||||||
public TransformOperations? MotionTransform
|
public TransformOperations? MotionTransform
|
||||||
{
|
{
|
||||||
get => GetValue(MotionTransformProperty);
|
get => GetValue(MotionTransformProperty);
|
||||||
set => SetValue(MotionTransformProperty, value);
|
set => SetValue(MotionTransformProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool UseRenderTransform
|
||||||
|
{
|
||||||
|
get => GetValue(UseRenderTransformProperty);
|
||||||
|
set => SetValue(UseRenderTransformProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public Control? MotionTransformRoot => Child;
|
public Control? MotionTransformRoot => Child;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -109,7 +118,7 @@ public class MotionActorControl : Decorator
|
|||||||
}
|
}
|
||||||
|
|
||||||
_transformation = matrix;
|
_transformation = matrix;
|
||||||
_matrixTransform.Matrix = FilterScaleTransform(matrix);
|
_matrixTransform.Matrix = UseRenderTransform ? matrix : FilterScaleTransform(matrix);
|
||||||
RenderTransform = _matrixTransform;
|
RenderTransform = _matrixTransform;
|
||||||
// New transform means re-layout is necessary
|
// New transform means re-layout is necessary
|
||||||
InvalidateMeasure();
|
InvalidateMeasure();
|
||||||
@ -145,15 +154,15 @@ public class MotionActorControl : Decorator
|
|||||||
|
|
||||||
protected override Size ArrangeOverride(Size finalSize)
|
protected override Size ArrangeOverride(Size finalSize)
|
||||||
{
|
{
|
||||||
if (MotionTransformRoot == null || MotionTransform == null)
|
if (MotionTransformRoot == null || MotionTransform == null || UseRenderTransform)
|
||||||
{
|
{
|
||||||
// TODO 这里可能会引起混淆,因为我们不会对 Target 实施 Scale 转换
|
// TODO 这里可能会引起混淆,因为我们不会对 Target 实施 Scale 转换
|
||||||
SetCurrentValue(MotionTransformProperty, RenderTransform);
|
|
||||||
return base.ArrangeOverride(finalSize);
|
return base.ArrangeOverride(finalSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the largest available size after the transformation
|
// Determine the largest available size after the transformation
|
||||||
Size finalSizeTransformed = ComputeLargestTransformedSize(finalSize);
|
Size finalSizeTransformed = ComputeLargestTransformedSize(finalSize);
|
||||||
|
|
||||||
if (IsSizeSmaller(finalSizeTransformed, MotionTransformRoot.DesiredSize))
|
if (IsSizeSmaller(finalSizeTransformed, MotionTransformRoot.DesiredSize))
|
||||||
{
|
{
|
||||||
// Some elements do not like being given less space than they asked for (ex: TextBlock)
|
// Some elements do not like being given less space than they asked for (ex: TextBlock)
|
||||||
@ -182,7 +191,7 @@ public class MotionActorControl : Decorator
|
|||||||
//// Unfortunately, all the work so far is invalid because the wrong DesiredSize was used
|
//// Unfortunately, all the work so far is invalid because the wrong DesiredSize was used
|
||||||
//// Make a note of the actual DesiredSize
|
//// Make a note of the actual DesiredSize
|
||||||
// _childActualSize = arrangedsize;
|
// _childActualSize = arrangedsize;
|
||||||
//// Force a new measure/arrange pass
|
// //// Force a new measure/arrange pass
|
||||||
// InvalidateMeasure();
|
// InvalidateMeasure();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -197,7 +206,7 @@ public class MotionActorControl : Decorator
|
|||||||
|
|
||||||
protected override Size MeasureOverride(Size availableSize)
|
protected override Size MeasureOverride(Size availableSize)
|
||||||
{
|
{
|
||||||
if (MotionTransformRoot == null || MotionTransform == null)
|
if (MotionTransformRoot == null || MotionTransform == null || UseRenderTransform)
|
||||||
{
|
{
|
||||||
return base.MeasureOverride(availableSize);
|
return base.MeasureOverride(availableSize);
|
||||||
}
|
}
|
@ -2,14 +2,14 @@
|
|||||||
using Avalonia.Animation;
|
using Avalonia.Animation;
|
||||||
using Avalonia.Media.Transformation;
|
using Avalonia.Media.Transformation;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.MotionScene;
|
||||||
|
|
||||||
internal record MotionConfig
|
internal record MotionConfigX
|
||||||
{
|
{
|
||||||
public RelativePoint RenderTransformOrigin { get; }
|
public RelativePoint RenderTransformOrigin { get; }
|
||||||
public IList<Animation> Animations { get; }
|
public IList<Animation> Animations { get; }
|
||||||
|
|
||||||
public MotionConfig(RelativePoint renderTransformOrigin, IList<Animation> animations)
|
public MotionConfigX(RelativePoint renderTransformOrigin, IList<Animation> animations)
|
||||||
{
|
{
|
||||||
RenderTransformOrigin = renderTransformOrigin;
|
RenderTransformOrigin = renderTransformOrigin;
|
||||||
Animations = animations;
|
Animations = animations;
|
||||||
@ -18,36 +18,36 @@ internal record MotionConfig
|
|||||||
|
|
||||||
internal static partial class MotionFactory
|
internal static partial class MotionFactory
|
||||||
{
|
{
|
||||||
static TransformOperations BuildScaleTransform(double scaleX, double scaleY)
|
public static TransformOperations BuildScaleTransform(double scaleX, double scaleY)
|
||||||
{
|
{
|
||||||
var builder = new TransformOperations.Builder(1);
|
var builder = new TransformOperations.Builder(1);
|
||||||
builder.AppendScale(scaleX, scaleY);
|
builder.AppendScale(scaleX, scaleY);
|
||||||
return builder.Build();
|
return builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
static TransformOperations BuildScaleTransform(double scale)
|
public static TransformOperations BuildScaleTransform(double scale)
|
||||||
{
|
{
|
||||||
return BuildScaleTransform(scale, scale);
|
return BuildScaleTransform(scale, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static TransformOperations BuildScaleXTransform(double scale)
|
public static TransformOperations BuildScaleXTransform(double scale)
|
||||||
{
|
{
|
||||||
return BuildScaleTransform(scale, 1.0);
|
return BuildScaleTransform(scale, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static TransformOperations BuildScaleYTransform(double scale)
|
public static TransformOperations BuildScaleYTransform(double scale)
|
||||||
{
|
{
|
||||||
return BuildScaleTransform(1.0, scale);
|
return BuildScaleTransform(1.0, scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static TransformOperations BuildTranslateTransform(double offsetX, double offsetY)
|
public static TransformOperations BuildTranslateTransform(double offsetX, double offsetY)
|
||||||
{
|
{
|
||||||
var builder = new TransformOperations.Builder(1);
|
var builder = new TransformOperations.Builder(1);
|
||||||
builder.AppendTranslate(offsetX, offsetY);
|
builder.AppendTranslate(offsetX, offsetY);
|
||||||
return builder.Build();
|
return builder.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
static TransformOperations BuildTranslateScaleAndTransform(double scaleX, double scaleY, double offsetX, double offsetY)
|
public static TransformOperations BuildTranslateScaleAndTransform(double scaleX, double scaleY, double offsetX, double offsetY)
|
||||||
{
|
{
|
||||||
var builder = new TransformOperations.Builder(2);
|
var builder = new TransformOperations.Builder(2);
|
||||||
builder.AppendScale(scaleX, scaleY);
|
builder.AppendScale(scaleX, scaleY);
|
@ -1,16 +1,16 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using Avalonia;
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.MotionScene;
|
||||||
|
|
||||||
internal static class MotionInvoker
|
internal static class MotionInvoker
|
||||||
{
|
{
|
||||||
public static void Invoke(MotionActorControl target,
|
public static void Invoke(MotionActorControl target,
|
||||||
MotionConfig motionConfig,
|
MotionConfigX motionConfig,
|
||||||
Action? aboutToStart = null,
|
Action? aboutToStart = null,
|
||||||
Action? completedAction = null)
|
Action? completedAction = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||||
{
|
{
|
||||||
@ -23,7 +23,7 @@ internal static class MotionInvoker
|
|||||||
|
|
||||||
foreach (var animation in motionConfig.Animations)
|
foreach (var animation in motionConfig.Animations)
|
||||||
{
|
{
|
||||||
await animation.RunAsync(target);
|
await animation.RunAsync(target, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (completedAction != null)
|
if (completedAction != null)
|
@ -2,7 +2,7 @@
|
|||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Media.Transformation;
|
using Avalonia.Media.Transformation;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.MotionScene;
|
||||||
|
|
||||||
internal class MotionTransformOptionsAnimator : InterpolatingAnimator<TransformOperations>
|
internal class MotionTransformOptionsAnimator : InterpolatingAnimator<TransformOperations>
|
||||||
{
|
{
|
@ -1,15 +1,14 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using Avalonia;
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Animation;
|
using Avalonia.Animation;
|
||||||
using Avalonia.Animation.Easings;
|
using Avalonia.Animation.Easings;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.MotionScene;
|
||||||
|
|
||||||
internal static partial class MotionFactory
|
internal static partial class MotionFactory
|
||||||
{
|
{
|
||||||
public static MotionConfig BuildMoveDownInMotion(double offset,
|
public static MotionConfigX BuildMoveDownInMotion(double offset,
|
||||||
TimeSpan duration,
|
TimeSpan duration,
|
||||||
Easing? easing = null,
|
Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
@ -89,10 +88,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildMoveDownOutMotion(double offset,
|
public static MotionConfigX BuildMoveDownOutMotion(double offset,
|
||||||
TimeSpan duration,
|
TimeSpan duration,
|
||||||
Easing? easing = null,
|
Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
@ -173,10 +172,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildMoveUpInMotion(double offset, TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildMoveUpInMotion(double offset, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new QuinticEaseOut();
|
easing ??= new QuinticEaseOut();
|
||||||
@ -254,10 +253,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildMoveUpOutMotion(double offset, TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildMoveUpOutMotion(double offset, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new QuinticEaseIn();
|
easing ??= new QuinticEaseIn();
|
||||||
@ -345,10 +344,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildMoveLeftInMotion(double offset, TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildMoveLeftInMotion(double offset, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new QuinticEaseOut();
|
easing ??= new QuinticEaseOut();
|
||||||
@ -429,10 +428,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildMoveLeftOutMotion(double offset, TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildMoveLeftOutMotion(double offset, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new QuinticEaseIn();
|
easing ??= new QuinticEaseIn();
|
||||||
@ -509,10 +508,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildMoveRightInMotion(double offset, TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildMoveRightInMotion(double offset, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new QuinticEaseOut();
|
easing ??= new QuinticEaseOut();
|
||||||
@ -590,10 +589,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildMoveRightOutMotion(double offset, TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildMoveRightOutMotion(double offset, TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new QuinticEaseIn();
|
easing ??= new QuinticEaseIn();
|
||||||
@ -671,6 +670,6 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0, 0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,14 +1,13 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using Avalonia;
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Animation;
|
using Avalonia.Animation;
|
||||||
using Avalonia.Animation.Easings;
|
using Avalonia.Animation.Easings;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
|
||||||
namespace AtomUI.Controls.Utils;
|
namespace AtomUI.MotionScene;
|
||||||
|
|
||||||
internal static partial class MotionFactory
|
internal static partial class MotionFactory
|
||||||
{
|
{
|
||||||
public static MotionConfig BuildSlideUpInMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildSlideUpInMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseOut();
|
easing ??= new CubicEaseOut();
|
||||||
@ -63,10 +62,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildSlideUpOutMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildSlideUpOutMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseIn();
|
easing ??= new CubicEaseIn();
|
||||||
@ -122,10 +121,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildSlideDownInMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildSlideDownInMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseOut();
|
easing ??= new CubicEaseOut();
|
||||||
@ -181,10 +180,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildSlideDownOutMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildSlideDownOutMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseIn();
|
easing ??= new CubicEaseIn();
|
||||||
@ -240,10 +239,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(1.0, 1.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildSlideLeftInMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildSlideLeftInMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseOut();
|
easing ??= new CubicEaseOut();
|
||||||
@ -299,10 +298,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildSlideLeftOutMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildSlideLeftOutMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseIn();
|
easing ??= new CubicEaseIn();
|
||||||
@ -358,10 +357,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildSlideRightInMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildSlideRightInMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseOut();
|
easing ??= new CubicEaseOut();
|
||||||
@ -417,10 +416,10 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MotionConfig BuildSlideRightOutMotion(TimeSpan duration, Easing? easing = null,
|
public static MotionConfigX BuildSlideRightOutMotion(TimeSpan duration, Easing? easing = null,
|
||||||
FillMode fillMode = FillMode.None)
|
FillMode fillMode = FillMode.None)
|
||||||
{
|
{
|
||||||
easing ??= new CubicEaseIn();
|
easing ??= new CubicEaseIn();
|
||||||
@ -476,6 +475,6 @@ internal static partial class MotionFactory
|
|||||||
transformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
|
transformOrigin = new RelativePoint(1.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
animations.Add(animation);
|
animations.Add(animation);
|
||||||
return new MotionConfig(transformOrigin, animations);
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
}
|
}
|
||||||
}
|
}
|
250
src/AtomUI.Controls/Badge/BadgeMotionFactory.cs
Normal file
250
src/AtomUI.Controls/Badge/BadgeMotionFactory.cs
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
using AtomUI.MotionScene;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Animation;
|
||||||
|
using Avalonia.Animation.Easings;
|
||||||
|
using Avalonia.Styling;
|
||||||
|
|
||||||
|
namespace AtomUI.Controls.Badge;
|
||||||
|
|
||||||
|
internal static class BadgeMotionFactory
|
||||||
|
{
|
||||||
|
public static MotionConfigX BuildBadgeZoomBadgeInMotion(TimeSpan duration, Easing? easing = null,
|
||||||
|
FillMode fillMode = FillMode.None)
|
||||||
|
{
|
||||||
|
easing ??= new ExponentialEaseOut();
|
||||||
|
var animations = new List<Animation>();
|
||||||
|
RelativePoint transformOrigin = default;
|
||||||
|
var animation = new Animation
|
||||||
|
{
|
||||||
|
Duration = duration,
|
||||||
|
Easing = easing,
|
||||||
|
FillMode = fillMode
|
||||||
|
};
|
||||||
|
|
||||||
|
var startFrame = new KeyFrame
|
||||||
|
{
|
||||||
|
Cue = new Cue(0.0)
|
||||||
|
};
|
||||||
|
{
|
||||||
|
var opacitySetter = new Setter
|
||||||
|
{
|
||||||
|
Property = Visual.OpacityProperty,
|
||||||
|
Value = 0.0
|
||||||
|
};
|
||||||
|
startFrame.Setters.Add(opacitySetter);
|
||||||
|
|
||||||
|
var transformSetter = new Setter
|
||||||
|
{
|
||||||
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
|
Value = MotionFactory.BuildScaleTransform(0.0)
|
||||||
|
};
|
||||||
|
startFrame.Setters.Add(transformSetter);
|
||||||
|
}
|
||||||
|
animation.Children.Add(startFrame);
|
||||||
|
|
||||||
|
var endFrame = new KeyFrame
|
||||||
|
{
|
||||||
|
Cue = new Cue(1.0)
|
||||||
|
};
|
||||||
|
{
|
||||||
|
var opacitySetter = new Setter
|
||||||
|
{
|
||||||
|
Property = Visual.OpacityProperty,
|
||||||
|
Value = 1.0
|
||||||
|
};
|
||||||
|
endFrame.Setters.Add(opacitySetter);
|
||||||
|
|
||||||
|
var transformSetter = new Setter
|
||||||
|
{
|
||||||
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
|
Value = MotionFactory.BuildScaleTransform(1.0)
|
||||||
|
};
|
||||||
|
endFrame.Setters.Add(transformSetter);
|
||||||
|
}
|
||||||
|
animation.Children.Add(endFrame);
|
||||||
|
transformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
||||||
|
|
||||||
|
animations.Add(animation);
|
||||||
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MotionConfigX BuildBadgeZoomBadgeOutMotion(TimeSpan duration, Easing? easing = null,
|
||||||
|
FillMode fillMode = FillMode.None)
|
||||||
|
{
|
||||||
|
easing ??= new ExponentialEaseIn();
|
||||||
|
var animations = new List<Animation>();
|
||||||
|
RelativePoint transformOrigin = default;
|
||||||
|
var animation = new Animation
|
||||||
|
{
|
||||||
|
Duration = duration,
|
||||||
|
Easing = easing,
|
||||||
|
FillMode = fillMode
|
||||||
|
};
|
||||||
|
|
||||||
|
var startFrame = new KeyFrame
|
||||||
|
{
|
||||||
|
Cue = new Cue(0.0)
|
||||||
|
};
|
||||||
|
{
|
||||||
|
var opacitySetter = new Setter
|
||||||
|
{
|
||||||
|
Property = Visual.OpacityProperty,
|
||||||
|
Value = 1.0
|
||||||
|
};
|
||||||
|
startFrame.Setters.Add(opacitySetter);
|
||||||
|
|
||||||
|
var transformSetter = new Setter
|
||||||
|
{
|
||||||
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
|
Value = MotionFactory.BuildScaleTransform(1.0)
|
||||||
|
};
|
||||||
|
startFrame.Setters.Add(transformSetter);
|
||||||
|
}
|
||||||
|
animation.Children.Add(startFrame);
|
||||||
|
|
||||||
|
var endFrame = new KeyFrame
|
||||||
|
{
|
||||||
|
Cue = new Cue(1.0)
|
||||||
|
};
|
||||||
|
{
|
||||||
|
var opacitySetter = new Setter
|
||||||
|
{
|
||||||
|
Property = Visual.OpacityProperty,
|
||||||
|
Value = 0.0
|
||||||
|
};
|
||||||
|
endFrame.Setters.Add(opacitySetter);
|
||||||
|
|
||||||
|
var transformSetter = new Setter
|
||||||
|
{
|
||||||
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
|
Value = MotionFactory.BuildScaleTransform(0.0)
|
||||||
|
};
|
||||||
|
endFrame.Setters.Add(transformSetter);
|
||||||
|
}
|
||||||
|
animation.Children.Add(endFrame);
|
||||||
|
transformOrigin = new RelativePoint(0.5, 0.5, RelativeUnit.Relative);
|
||||||
|
|
||||||
|
animations.Add(animation);
|
||||||
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MotionConfigX BuildCountBadgeNoWrapperZoomBadgeInMotion(TimeSpan duration, Easing? easing = null,
|
||||||
|
FillMode fillMode = FillMode.None)
|
||||||
|
{
|
||||||
|
easing ??= new CircularEaseOut();
|
||||||
|
var animations = new List<Animation>();
|
||||||
|
RelativePoint transformOrigin = default;
|
||||||
|
var animation = new Animation
|
||||||
|
{
|
||||||
|
Duration = duration,
|
||||||
|
Easing = easing,
|
||||||
|
FillMode = fillMode
|
||||||
|
};
|
||||||
|
|
||||||
|
var startFrame = new KeyFrame
|
||||||
|
{
|
||||||
|
Cue = new Cue(0.0)
|
||||||
|
};
|
||||||
|
{
|
||||||
|
var opacitySetter = new Setter
|
||||||
|
{
|
||||||
|
Property = Visual.OpacityProperty,
|
||||||
|
Value = 0.0
|
||||||
|
};
|
||||||
|
startFrame.Setters.Add(opacitySetter);
|
||||||
|
|
||||||
|
var transformSetter = new Setter
|
||||||
|
{
|
||||||
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
|
Value = MotionFactory.BuildScaleTransform(0.0, 0.0)
|
||||||
|
};
|
||||||
|
startFrame.Setters.Add(transformSetter);
|
||||||
|
}
|
||||||
|
animation.Children.Add(startFrame);
|
||||||
|
|
||||||
|
var endFrame = new KeyFrame
|
||||||
|
{
|
||||||
|
Cue = new Cue(1.0)
|
||||||
|
};
|
||||||
|
{
|
||||||
|
var opacitySetter = new Setter
|
||||||
|
{
|
||||||
|
Property = Visual.OpacityProperty,
|
||||||
|
Value = 1.0
|
||||||
|
};
|
||||||
|
endFrame.Setters.Add(opacitySetter);
|
||||||
|
|
||||||
|
var transformSetter = new Setter
|
||||||
|
{
|
||||||
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
|
Value = MotionFactory.BuildScaleTransform(1.0, 1.0)
|
||||||
|
};
|
||||||
|
endFrame.Setters.Add(transformSetter);
|
||||||
|
}
|
||||||
|
animation.Children.Add(endFrame);
|
||||||
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
|
animations.Add(animation);
|
||||||
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MotionConfigX BuildCountBadgeNoWrapperZoomBadgeOutMotion(TimeSpan duration, Easing? easing = null,
|
||||||
|
FillMode fillMode = FillMode.None)
|
||||||
|
{
|
||||||
|
easing ??= new CircularEaseIn();
|
||||||
|
var animations = new List<Animation>();
|
||||||
|
RelativePoint transformOrigin = default;
|
||||||
|
var animation = new Animation
|
||||||
|
{
|
||||||
|
Duration = duration,
|
||||||
|
Easing = easing,
|
||||||
|
FillMode = fillMode
|
||||||
|
};
|
||||||
|
|
||||||
|
var startFrame = new KeyFrame
|
||||||
|
{
|
||||||
|
Cue = new Cue(0.0)
|
||||||
|
};
|
||||||
|
{
|
||||||
|
var opacitySetter = new Setter
|
||||||
|
{
|
||||||
|
Property = Visual.OpacityProperty,
|
||||||
|
Value = 1.0
|
||||||
|
};
|
||||||
|
startFrame.Setters.Add(opacitySetter);
|
||||||
|
|
||||||
|
var transformSetter = new Setter
|
||||||
|
{
|
||||||
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
|
Value = MotionFactory.BuildScaleTransform(1.0, 1.0)
|
||||||
|
};
|
||||||
|
startFrame.Setters.Add(transformSetter);
|
||||||
|
}
|
||||||
|
animation.Children.Add(startFrame);
|
||||||
|
|
||||||
|
var endFrame = new KeyFrame
|
||||||
|
{
|
||||||
|
Cue = new Cue(1.0)
|
||||||
|
};
|
||||||
|
{
|
||||||
|
var opacitySetter = new Setter
|
||||||
|
{
|
||||||
|
Property = Visual.OpacityProperty,
|
||||||
|
Value = 0.0
|
||||||
|
};
|
||||||
|
endFrame.Setters.Add(opacitySetter);
|
||||||
|
|
||||||
|
var transformSetter = new Setter
|
||||||
|
{
|
||||||
|
Property = MotionActorControl.MotionTransformProperty,
|
||||||
|
Value = MotionFactory.BuildScaleTransform(0.0, 0.0)
|
||||||
|
};
|
||||||
|
endFrame.Setters.Add(transformSetter);
|
||||||
|
}
|
||||||
|
animation.Children.Add(endFrame);
|
||||||
|
transformOrigin = new RelativePoint(0.0, 0.0, RelativeUnit.Relative);
|
||||||
|
|
||||||
|
animations.Add(animation);
|
||||||
|
return new MotionConfigX(transformOrigin, animations);
|
||||||
|
}
|
||||||
|
}
|
@ -62,6 +62,7 @@ internal class BadgeToken : AbstractControlDesignToken
|
|||||||
public Transform? BadgeRibbonCornerTransform { get; set; }
|
public Transform? BadgeRibbonCornerTransform { get; set; }
|
||||||
public int BadgeRibbonCornerDarkenAmount { get; set; }
|
public int BadgeRibbonCornerDarkenAmount { get; set; }
|
||||||
public Thickness BadgeRibbonTextPadding { get; set; }
|
public Thickness BadgeRibbonTextPadding { get; set; }
|
||||||
|
public Thickness DotBadgeLabelMargin { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -90,5 +91,6 @@ internal class BadgeToken : AbstractControlDesignToken
|
|||||||
BadgeRibbonCornerTransform = new ScaleTransform(1, 0.75);
|
BadgeRibbonCornerTransform = new ScaleTransform(1, 0.75);
|
||||||
BadgeRibbonCornerDarkenAmount = 15;
|
BadgeRibbonCornerDarkenAmount = 15;
|
||||||
BadgeRibbonTextPadding = new Thickness(_globalToken.PaddingXS, 0);
|
BadgeRibbonTextPadding = new Thickness(_globalToken.PaddingXS, 0);
|
||||||
|
DotBadgeLabelMargin = new Thickness(_globalToken.MarginXS, 0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -99,8 +99,6 @@ public class CountBadge : Control
|
|||||||
set => SetValue(BadgeIsVisibleProperty, value);
|
set => SetValue(BadgeIsVisibleProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 内部属性定义
|
#region 内部属性定义
|
||||||
|
13
src/AtomUI.Controls/Badge/CountBadgeAdornerTheme.cs
Normal file
13
src/AtomUI.Controls/Badge/CountBadgeAdornerTheme.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using AtomUI.Theme;
|
||||||
|
using AtomUI.Theme.Styling;
|
||||||
|
|
||||||
|
namespace AtomUI.Controls.Badge;
|
||||||
|
|
||||||
|
[ControlThemeProvider]
|
||||||
|
internal class CountBadgeAdornerTheme : BaseControlTheme
|
||||||
|
{
|
||||||
|
public CountBadgeAdornerTheme()
|
||||||
|
: base(typeof(CountBadgeAdorner))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,9 @@
|
|||||||
using AtomUI.Controls.Badge;
|
using AtomUI.Data;
|
||||||
using AtomUI.Controls.MotionScene;
|
|
||||||
using AtomUI.Data;
|
|
||||||
using AtomUI.MotionScene;
|
|
||||||
using AtomUI.Theme.Palette;
|
using AtomUI.Theme.Palette;
|
||||||
using AtomUI.Theme.Styling;
|
|
||||||
using AtomUI.Utils;
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Layout;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Metadata;
|
using Avalonia.Metadata;
|
||||||
|
|
||||||
@ -86,35 +82,15 @@ public class DotBadge : Control
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 内部属性一定
|
|
||||||
|
|
||||||
internal static readonly StyledProperty<TimeSpan> MotionDurationProperty =
|
|
||||||
AvaloniaProperty.Register<CountBadge, TimeSpan>(
|
|
||||||
nameof(MotionDuration));
|
|
||||||
|
|
||||||
internal TimeSpan MotionDuration
|
|
||||||
{
|
|
||||||
get => GetValue(MotionDurationProperty);
|
|
||||||
set => SetValue(MotionDurationProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
private readonly bool _initialized = false;
|
|
||||||
private DotBadgeAdorner? _dotBadgeAdorner;
|
private DotBadgeAdorner? _dotBadgeAdorner;
|
||||||
private AdornerLayer? _adornerLayer;
|
private AdornerLayer? _adornerLayer;
|
||||||
private bool _animating;
|
|
||||||
|
|
||||||
static DotBadge()
|
static DotBadge()
|
||||||
{
|
{
|
||||||
AffectsMeasure<DotBadge>(DecoratedTargetProperty, TextProperty);
|
AffectsMeasure<DotBadge>(DecoratedTargetProperty, TextProperty);
|
||||||
AffectsRender<DotBadge>(DotColorProperty, StatusProperty);
|
AffectsRender<DotBadge>(DotColorProperty, StatusProperty);
|
||||||
}
|
HorizontalAlignmentProperty.OverrideDefaultValue<DotBadge>(HorizontalAlignment.Left);
|
||||||
|
VerticalAlignmentProperty.OverrideDefaultValue<DotBadge>(VerticalAlignment.Top);
|
||||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
|
||||||
{
|
|
||||||
base.OnAttachedToVisualTree(e);
|
|
||||||
PrepareAdorner();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DotBadgeAdorner CreateDotBadgeAdorner()
|
private DotBadgeAdorner CreateDotBadgeAdorner()
|
||||||
@ -135,7 +111,7 @@ public class DotBadge : Control
|
|||||||
|
|
||||||
private void PrepareAdorner()
|
private void PrepareAdorner()
|
||||||
{
|
{
|
||||||
if (_adornerLayer is null && DecoratedTarget is not null)
|
if (DecoratedTarget is not null)
|
||||||
{
|
{
|
||||||
var dotBadgeAdorner = CreateDotBadgeAdorner();
|
var dotBadgeAdorner = CreateDotBadgeAdorner();
|
||||||
_adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
_adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
||||||
@ -145,71 +121,18 @@ public class DotBadge : Control
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AdornerLayer.SetAdornedElement(dotBadgeAdorner, this);
|
dotBadgeAdorner.ApplyToTarget(_adornerLayer, this);
|
||||||
AdornerLayer.SetIsClipEnabled(dotBadgeAdorner, false);
|
|
||||||
_adornerLayer.Children.Add(dotBadgeAdorner);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PrepareAdornerWithMotion()
|
|
||||||
{
|
|
||||||
PrepareAdorner();
|
|
||||||
|
|
||||||
if (VisualRoot is null || _animating)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_animating = true;
|
|
||||||
var director = Director.Instance;
|
|
||||||
var motion = new CountBadgeZoomBadgeIn();
|
|
||||||
motion.ConfigureOpacity(MotionDuration);
|
|
||||||
motion.ConfigureRenderTransform(MotionDuration);
|
|
||||||
_dotBadgeAdorner!.AnimationRenderTransformOrigin = motion.MotionRenderTransformOrigin;
|
|
||||||
var motionActor = new MotionActor(_dotBadgeAdorner, motion);
|
|
||||||
motionActor.DispatchInSceneLayer = false;
|
|
||||||
motionActor.Completed += (sender, args) =>
|
|
||||||
{
|
|
||||||
_dotBadgeAdorner.AnimationRenderTransformOrigin = null;
|
|
||||||
_animating = false;
|
|
||||||
};
|
|
||||||
director?.Schedule(motionActor);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HideAdorner()
|
private void HideAdorner()
|
||||||
{
|
{
|
||||||
// 这里需要抛出异常吗?
|
// 这里需要抛出异常吗?
|
||||||
if (_adornerLayer is null || _dotBadgeAdorner is null)
|
if ( _dotBadgeAdorner is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
_dotBadgeAdorner.DetachFromTarget(_adornerLayer);
|
||||||
_adornerLayer.Children.Remove(_dotBadgeAdorner);
|
|
||||||
_adornerLayer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HideAdornerWithMotion()
|
|
||||||
{
|
|
||||||
if (VisualRoot is null || _animating)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_animating = true;
|
|
||||||
var director = Director.Instance;
|
|
||||||
var motion = new CountBadgeZoomBadgeOut();
|
|
||||||
motion.ConfigureOpacity(MotionDuration);
|
|
||||||
motion.ConfigureRenderTransform(MotionDuration);
|
|
||||||
_dotBadgeAdorner!.AnimationRenderTransformOrigin = motion.MotionRenderTransformOrigin;
|
|
||||||
var motionActor = new MotionActor(_dotBadgeAdorner, motion);
|
|
||||||
motionActor.DispatchInSceneLayer = false;
|
|
||||||
motionActor.Completed += (sender, args) =>
|
|
||||||
{
|
|
||||||
HideAdorner();
|
|
||||||
_dotBadgeAdorner.AnimationRenderTransformOrigin = null;
|
|
||||||
_animating = false;
|
|
||||||
};
|
|
||||||
director?.Schedule(motionActor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
@ -226,8 +149,6 @@ public class DotBadge : Control
|
|||||||
BindUtils.RelayBind(this, TextProperty, _dotBadgeAdorner, DotBadgeAdorner.TextProperty);
|
BindUtils.RelayBind(this, TextProperty, _dotBadgeAdorner, DotBadgeAdorner.TextProperty);
|
||||||
BindUtils.RelayBind(this, OffsetProperty, _dotBadgeAdorner, DotBadgeAdorner.OffsetProperty);
|
BindUtils.RelayBind(this, OffsetProperty, _dotBadgeAdorner, DotBadgeAdorner.OffsetProperty);
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenResourceBinder.CreateTokenBinding(this, MotionDurationProperty, GlobalTokenResourceKey.MotionDurationSlow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleDecoratedTargetChanged()
|
private void HandleDecoratedTargetChanged()
|
||||||
@ -240,7 +161,7 @@ public class DotBadge : Control
|
|||||||
((ISetLogicalParent)_dotBadgeAdorner).SetParent(this);
|
((ISetLogicalParent)_dotBadgeAdorner).SetParent(this);
|
||||||
VisualChildren.Add(_dotBadgeAdorner);
|
VisualChildren.Add(_dotBadgeAdorner);
|
||||||
}
|
}
|
||||||
else if (DecoratedTarget is not null)
|
else
|
||||||
{
|
{
|
||||||
_dotBadgeAdorner.IsAdornerMode = true;
|
_dotBadgeAdorner.IsAdornerMode = true;
|
||||||
VisualChildren.Add(DecoratedTarget);
|
VisualChildren.Add(DecoratedTarget);
|
||||||
@ -256,6 +177,10 @@ public class DotBadge : Control
|
|||||||
{
|
{
|
||||||
CreateDotBadgeAdorner();
|
CreateDotBadgeAdorner();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PrepareAdorner();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||||
@ -280,37 +205,17 @@ public class DotBadge : Control
|
|||||||
}
|
}
|
||||||
else if (e.Property == BadgeIsVisibleProperty)
|
else if (e.Property == BadgeIsVisibleProperty)
|
||||||
{
|
{
|
||||||
var badgeIsVisible = e.GetNewValue<bool>();
|
if (BadgeIsVisible)
|
||||||
if (badgeIsVisible)
|
|
||||||
{
|
|
||||||
if (_adornerLayer is not null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DecoratedTarget is not null)
|
|
||||||
{
|
|
||||||
PrepareAdornerWithMotion();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
PrepareAdorner();
|
PrepareAdorner();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (DecoratedTarget is not null)
|
|
||||||
{
|
|
||||||
HideAdornerWithMotion();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
HideAdorner();
|
HideAdorner();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (_initialized)
|
if (VisualRoot is not null)
|
||||||
{
|
{
|
||||||
if (e.Property == DecoratedTargetProperty)
|
if (e.Property == DecoratedTargetProperty)
|
||||||
{
|
{
|
||||||
@ -342,4 +247,5 @@ public class DotBadge : Control
|
|||||||
_dotBadgeAdorner!.BadgeDotColor = new SolidColorBrush(color);
|
_dotBadgeAdorner!.BadgeDotColor = new SolidColorBrush(color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,21 +1,33 @@
|
|||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Controls.Badge;
|
||||||
|
using AtomUI.MotionScene;
|
||||||
|
using AtomUI.Theme.Styling;
|
||||||
|
using AtomUI.Utils;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
using Avalonia.Animation;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.LogicalTree;
|
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Styling;
|
|
||||||
|
|
||||||
namespace AtomUI.Controls;
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
internal class DotBadgeAdorner : Control
|
internal class DotBadgeAdorner : TemplatedControl
|
||||||
{
|
{
|
||||||
|
public static readonly StyledProperty<IBrush?> BadgeDotColorProperty =
|
||||||
|
AvaloniaProperty.Register<DotBadgeAdorner, IBrush?>(
|
||||||
|
nameof(BadgeDotColor));
|
||||||
|
|
||||||
public static readonly DirectProperty<DotBadgeAdorner, DotBadgeStatus?> StatusProperty =
|
public static readonly DirectProperty<DotBadgeAdorner, DotBadgeStatus?> StatusProperty =
|
||||||
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, DotBadgeStatus?>(
|
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, DotBadgeStatus?>(
|
||||||
nameof(Status),
|
nameof(Status),
|
||||||
o => o.Status,
|
o => o.Status,
|
||||||
(o, v) => o.Status = v);
|
(o, v) => o.Status = v);
|
||||||
|
|
||||||
|
internal IBrush? BadgeDotColor
|
||||||
|
{
|
||||||
|
get => GetValue(BadgeDotColorProperty);
|
||||||
|
set => SetValue(BadgeDotColorProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
private DotBadgeStatus? _status;
|
private DotBadgeStatus? _status;
|
||||||
|
|
||||||
public DotBadgeStatus? Status
|
public DotBadgeStatus? Status
|
||||||
@ -44,30 +56,6 @@ internal class DotBadgeAdorner : Control
|
|||||||
o => o.IsAdornerMode,
|
o => o.IsAdornerMode,
|
||||||
(o, v) => o.IsAdornerMode = v);
|
(o, v) => o.IsAdornerMode = v);
|
||||||
|
|
||||||
internal static readonly StyledProperty<IBrush?> BadgeDotColorProperty =
|
|
||||||
AvaloniaProperty.Register<DotBadgeAdorner, IBrush?>(
|
|
||||||
nameof(BadgeDotColor));
|
|
||||||
|
|
||||||
internal static readonly StyledProperty<double> DotSizeProperty =
|
|
||||||
AvaloniaProperty.Register<DotBadgeAdorner, double>(
|
|
||||||
nameof(DotSize));
|
|
||||||
|
|
||||||
internal static readonly StyledProperty<double> StatusSizeProperty =
|
|
||||||
AvaloniaProperty.Register<DotBadgeAdorner, double>(
|
|
||||||
nameof(StatusSize));
|
|
||||||
|
|
||||||
internal static readonly StyledProperty<IBrush?> BadgeShadowColorProperty =
|
|
||||||
AvaloniaProperty.Register<DotBadgeAdorner, IBrush?>(
|
|
||||||
nameof(BadgeShadowColor));
|
|
||||||
|
|
||||||
private static readonly StyledProperty<double> BadgeShadowSizeProperty =
|
|
||||||
AvaloniaProperty.Register<DotBadgeAdorner, double>(
|
|
||||||
nameof(BadgeShadowSize));
|
|
||||||
|
|
||||||
private static readonly StyledProperty<double> BadgeTextMarginInlineProperty =
|
|
||||||
AvaloniaProperty.Register<DotBadgeAdorner, double>(
|
|
||||||
nameof(BadgeTextMarginInline));
|
|
||||||
|
|
||||||
public static readonly StyledProperty<Point> OffsetProperty =
|
public static readonly StyledProperty<Point> OffsetProperty =
|
||||||
AvaloniaProperty.Register<DotBadgeAdorner, Point>(
|
AvaloniaProperty.Register<DotBadgeAdorner, Point>(
|
||||||
nameof(Offset));
|
nameof(Offset));
|
||||||
@ -86,255 +74,150 @@ internal class DotBadgeAdorner : Control
|
|||||||
set => SetValue(OffsetProperty, value);
|
set => SetValue(OffsetProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double DotSize
|
#region 内部属性定义
|
||||||
|
|
||||||
|
internal static readonly StyledProperty<TimeSpan> MotionDurationProperty =
|
||||||
|
AvaloniaProperty.Register<DotBadgeAdorner, TimeSpan>(
|
||||||
|
nameof(MotionDuration));
|
||||||
|
|
||||||
|
internal TimeSpan MotionDuration
|
||||||
{
|
{
|
||||||
get => GetValue(DotSizeProperty);
|
get => GetValue(MotionDurationProperty);
|
||||||
set => SetValue(DotSizeProperty, value);
|
set => SetValue(MotionDurationProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double StatusSize
|
#endregion
|
||||||
{
|
|
||||||
get => GetValue(StatusSizeProperty);
|
|
||||||
set => SetValue(StatusSizeProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IBrush? BadgeDotColor
|
private MotionActorControl? _indicatorMotionActor;
|
||||||
{
|
private CancellationTokenSource? _motionCancellationTokenSource;
|
||||||
get => GetValue(BadgeDotColorProperty);
|
|
||||||
set => SetValue(BadgeDotColorProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal IBrush? BadgeShadowColor
|
|
||||||
{
|
|
||||||
get => GetValue(BadgeShadowColorProperty);
|
|
||||||
set => SetValue(BadgeShadowColorProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double BadgeShadowSize
|
|
||||||
{
|
|
||||||
get => GetValue(BadgeShadowSizeProperty);
|
|
||||||
set => SetValue(BadgeShadowSizeProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double BadgeTextMarginInline
|
|
||||||
{
|
|
||||||
get => GetValue(BadgeTextMarginInlineProperty);
|
|
||||||
set => SetValue(BadgeTextMarginInlineProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _initialized;
|
|
||||||
private Label? _textLabel;
|
|
||||||
|
|
||||||
private BoxShadows _boxShadows;
|
|
||||||
|
|
||||||
// 不知道为什么这个值会被 AdornerLayer 重写
|
|
||||||
// 非常不优美,但是能工作
|
|
||||||
internal RelativePoint? AnimationRenderTransformOrigin;
|
|
||||||
|
|
||||||
static DotBadgeAdorner()
|
static DotBadgeAdorner()
|
||||||
{
|
{
|
||||||
AffectsMeasure<DotBadge>(TextProperty, IsAdornerModeProperty);
|
AffectsMeasure<DotBadge>(TextProperty, IsAdornerModeProperty);
|
||||||
AffectsRender<DotBadge>(BadgeDotColorProperty, OffsetProperty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed override void ApplyTemplate()
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
{
|
{
|
||||||
base.ApplyTemplate();
|
base.OnApplyTemplate(e);
|
||||||
if (!_initialized)
|
TokenResourceBinder.CreateTokenBinding(this, MotionDurationProperty, GlobalTokenResourceKey.MotionDurationMid);
|
||||||
{
|
SetupBadgeColor();
|
||||||
_textLabel = new Label
|
_indicatorMotionActor = e.NameScope.Get<MotionActorControl>(DotBadgeAdornerTheme.IndicatorMotionActorPart);
|
||||||
{
|
}
|
||||||
Content = Text,
|
|
||||||
HorizontalAlignment = HorizontalAlignment.Left,
|
|
||||||
VerticalAlignment = VerticalAlignment.Center,
|
|
||||||
HorizontalContentAlignment = HorizontalAlignment.Center,
|
|
||||||
VerticalContentAlignment = VerticalAlignment.Center,
|
|
||||||
Padding = new Thickness(0)
|
|
||||||
};
|
|
||||||
|
|
||||||
((ISetLogicalParent)_textLabel).SetParent(this);
|
private void ApplyShowMotion()
|
||||||
VisualChildren.Add(_textLabel);
|
{
|
||||||
BuildBoxShadow();
|
if (_indicatorMotionActor is not null)
|
||||||
_initialized = true;
|
{
|
||||||
|
_indicatorMotionActor.IsVisible = false;
|
||||||
|
var zoomBadgeInMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeInMotion(MotionDuration, null,
|
||||||
|
FillMode.Forward);
|
||||||
|
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeInMotionConfig, () =>
|
||||||
|
{
|
||||||
|
_indicatorMotionActor.IsVisible = true;
|
||||||
|
}, null, _motionCancellationTokenSource!.Token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
private void ApplyHideMotion(Action completedAction)
|
||||||
{
|
{
|
||||||
base.OnAttachedToLogicalTree(e);
|
if (_indicatorMotionActor is not null)
|
||||||
BuildStyles();
|
{
|
||||||
}
|
var zoomBadgeOutMotionConfig = BadgeMotionFactory.BuildBadgeZoomBadgeOutMotion(MotionDuration, null,
|
||||||
|
FillMode.Forward);
|
||||||
|
_motionCancellationTokenSource?.Cancel();
|
||||||
|
_motionCancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
private void BuildStyles()
|
MotionInvoker.Invoke(_indicatorMotionActor, zoomBadgeOutMotionConfig, null, () =>
|
||||||
{
|
{
|
||||||
if (Styles.Count == 0)
|
completedAction();
|
||||||
{
|
}, _motionCancellationTokenSource.Token);
|
||||||
BuildBadgeColorStyle();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildBadgeColorStyle()
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||||
{
|
{
|
||||||
var commonStyle = new Style(selector => selector.OfType<DotBadgeAdorner>());
|
base.OnPropertyChanged(change);
|
||||||
commonStyle.Add(BadgeTextMarginInlineProperty, GlobalTokenResourceKey.MarginXS);
|
if (VisualRoot is not null)
|
||||||
commonStyle.Add(BadgeDotColorProperty, BadgeTokenResourceKey.BadgeColor);
|
{
|
||||||
commonStyle.Add(DotSizeProperty, BadgeTokenResourceKey.DotSize);
|
if (change.Property == StatusProperty)
|
||||||
commonStyle.Add(StatusSizeProperty, BadgeTokenResourceKey.StatusSize);
|
{
|
||||||
commonStyle.Add(BadgeShadowSizeProperty, BadgeTokenResourceKey.BadgeShadowSize);
|
SetupBadgeColor();
|
||||||
commonStyle.Add(BadgeShadowColorProperty, BadgeTokenResourceKey.BadgeShadowColor);
|
|
||||||
|
|
||||||
var errorStatusStyle =
|
|
||||||
new Style(selector => selector.Nesting().PropertyEquals(StatusProperty, DotBadgeStatus.Error));
|
|
||||||
errorStatusStyle.Add(BadgeDotColorProperty, GlobalTokenResourceKey.ColorError);
|
|
||||||
commonStyle.Add(errorStatusStyle);
|
|
||||||
|
|
||||||
var successStatusStyle =
|
|
||||||
new Style(selector => selector.Nesting().PropertyEquals(StatusProperty, DotBadgeStatus.Success));
|
|
||||||
successStatusStyle.Add(BadgeDotColorProperty, GlobalTokenResourceKey.ColorSuccess);
|
|
||||||
commonStyle.Add(successStatusStyle);
|
|
||||||
|
|
||||||
var warningStatusStyle =
|
|
||||||
new Style(selector => selector.Nesting().PropertyEquals(StatusProperty, DotBadgeStatus.Warning));
|
|
||||||
warningStatusStyle.Add(BadgeDotColorProperty, GlobalTokenResourceKey.ColorWarning);
|
|
||||||
commonStyle.Add(warningStatusStyle);
|
|
||||||
|
|
||||||
var defaultStatusStyle =
|
|
||||||
new Style(selector => selector.Nesting().PropertyEquals(StatusProperty, DotBadgeStatus.Default));
|
|
||||||
defaultStatusStyle.Add(BadgeDotColorProperty, GlobalTokenResourceKey.ColorTextPlaceholder);
|
|
||||||
commonStyle.Add(defaultStatusStyle);
|
|
||||||
|
|
||||||
var processingStatusStyle = new Style(selector =>
|
|
||||||
selector.Nesting().PropertyEquals(StatusProperty, DotBadgeStatus.Processing));
|
|
||||||
processingStatusStyle.Add(BadgeDotColorProperty, GlobalTokenResourceKey.ColorInfo);
|
|
||||||
commonStyle.Add(processingStatusStyle);
|
|
||||||
|
|
||||||
Styles.Add(commonStyle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Size MeasureOverride(Size availableSize)
|
|
||||||
{
|
|
||||||
var targetWidth = 0d;
|
|
||||||
var targetHeight = 0d;
|
|
||||||
if (IsAdornerMode)
|
|
||||||
{
|
|
||||||
targetWidth = availableSize.Width;
|
|
||||||
targetHeight = availableSize.Height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var textSize = base.MeasureOverride(availableSize);
|
|
||||||
targetWidth += StatusSize;
|
|
||||||
targetWidth += textSize.Width;
|
|
||||||
targetHeight += Math.Max(textSize.Height, StatusSize);
|
|
||||||
if (textSize.Width > 0)
|
|
||||||
{
|
|
||||||
targetWidth += BadgeTextMarginInline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Size(targetWidth, targetHeight);
|
private void SetupBadgeColor()
|
||||||
|
{
|
||||||
|
if (Status is not null)
|
||||||
|
{
|
||||||
|
if (Status == DotBadgeStatus.Error)
|
||||||
|
{
|
||||||
|
TokenResourceBinder.CreateGlobalTokenBinding(this, BadgeDotColorProperty,
|
||||||
|
GlobalTokenResourceKey.ColorError);
|
||||||
|
}
|
||||||
|
else if (Status == DotBadgeStatus.Success)
|
||||||
|
{
|
||||||
|
TokenResourceBinder.CreateGlobalTokenBinding(this, BadgeDotColorProperty,
|
||||||
|
GlobalTokenResourceKey.ColorSuccess);
|
||||||
|
}
|
||||||
|
else if (Status == DotBadgeStatus.Warning)
|
||||||
|
{
|
||||||
|
TokenResourceBinder.CreateGlobalTokenBinding(this, BadgeDotColorProperty,
|
||||||
|
GlobalTokenResourceKey.ColorWarning);
|
||||||
|
}
|
||||||
|
else if (Status == DotBadgeStatus.Processing)
|
||||||
|
{
|
||||||
|
TokenResourceBinder.CreateGlobalTokenBinding(this, BadgeDotColorProperty,
|
||||||
|
GlobalTokenResourceKey.ColorInfo);
|
||||||
|
}
|
||||||
|
else if (Status == DotBadgeStatus.Default)
|
||||||
|
{
|
||||||
|
TokenResourceBinder.CreateGlobalTokenBinding(this, BadgeDotColorProperty,
|
||||||
|
GlobalTokenResourceKey.ColorTextPlaceholder);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Size ArrangeOverride(Size finalSize)
|
protected override Size ArrangeOverride(Size finalSize)
|
||||||
{
|
{
|
||||||
if (!IsAdornerMode)
|
var size = base.ArrangeOverride(finalSize);
|
||||||
|
if (IsAdornerMode && _indicatorMotionActor is not null)
|
||||||
{
|
{
|
||||||
double textOffsetX = 0;
|
var offsetX = Offset.X;
|
||||||
if (IsAdornerMode)
|
var offsetY = Offset.Y;
|
||||||
{
|
var dotSize = _indicatorMotionActor.Bounds.Size;
|
||||||
textOffsetX += DotSize;
|
offsetX += dotSize.Width / 3;
|
||||||
|
offsetY += dotSize.Height / 3;
|
||||||
|
_indicatorMotionActor.Arrange(new Rect(new Point(offsetX, -offsetY), dotSize));
|
||||||
}
|
}
|
||||||
else
|
return size;
|
||||||
{
|
|
||||||
textOffsetX += StatusSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textOffsetX += BadgeTextMarginInline;
|
internal void ApplyToTarget(AdornerLayer? adornerLayer, Control adorned)
|
||||||
var textRect = new Rect(new Point(textOffsetX, 0), _textLabel!.DesiredSize);
|
{
|
||||||
_textLabel.Arrange(textRect);
|
if (adornerLayer is null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return finalSize;
|
adornerLayer.Children.Remove(this);
|
||||||
|
|
||||||
|
AdornerLayer.SetAdornedElement(this, adorned);
|
||||||
|
AdornerLayer.SetIsClipEnabled(this, false);
|
||||||
|
adornerLayer.Children.Add(this);
|
||||||
|
|
||||||
|
_motionCancellationTokenSource?.Cancel();
|
||||||
|
_motionCancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
ApplyShowMotion();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
internal void DetachFromTarget(AdornerLayer? adornerLayer)
|
||||||
{
|
{
|
||||||
base.OnPropertyChanged(e);
|
if (adornerLayer is null)
|
||||||
if (e.Property == IsAdornerModeProperty)
|
|
||||||
{
|
{
|
||||||
var newValue = e.GetNewValue<bool>();
|
return;
|
||||||
if (_textLabel is not null)
|
}
|
||||||
{
|
ApplyHideMotion(() => adornerLayer.Children.Remove(this));
|
||||||
_textLabel.IsVisible = !newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (e.Property == BadgeShadowSizeProperty ||
|
|
||||||
e.Property == BadgeShadowColorProperty)
|
|
||||||
{
|
|
||||||
BuildBoxShadow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Render(DrawingContext context)
|
|
||||||
{
|
|
||||||
var dotSize = 0d;
|
|
||||||
if (IsAdornerMode)
|
|
||||||
{
|
|
||||||
dotSize = DotSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dotSize = StatusSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
var offsetX = 0d;
|
|
||||||
var offsetY = 0d;
|
|
||||||
if (IsAdornerMode)
|
|
||||||
{
|
|
||||||
offsetX = DesiredSize.Width - dotSize / 2;
|
|
||||||
offsetY = -dotSize / 2;
|
|
||||||
offsetX -= Offset.X;
|
|
||||||
offsetY += Offset.Y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offsetY = (DesiredSize.Height - dotSize) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
var dotRect = new Rect(new Point(offsetX, offsetY), new Size(dotSize, dotSize));
|
|
||||||
|
|
||||||
if (RenderTransform is not null)
|
|
||||||
{
|
|
||||||
Point origin;
|
|
||||||
if (AnimationRenderTransformOrigin.HasValue)
|
|
||||||
{
|
|
||||||
origin = AnimationRenderTransformOrigin.Value.ToPixels(dotRect.Size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
origin = RenderTransformOrigin.ToPixels(dotRect.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
var offset = Matrix.CreateTranslation(new Point(origin.X + offsetX, origin.Y + offsetY));
|
|
||||||
var renderTransform = -offset * RenderTransform.Value * offset;
|
|
||||||
context.PushTransform(renderTransform);
|
|
||||||
}
|
|
||||||
|
|
||||||
context.DrawRectangle(BadgeDotColor, null, dotRect, dotSize, dotSize, _boxShadows);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void BuildBoxShadow()
|
|
||||||
{
|
|
||||||
if (BadgeShadowColor is not null)
|
|
||||||
{
|
|
||||||
_boxShadows = new BoxShadows(new BoxShadow
|
|
||||||
{
|
|
||||||
OffsetX = 0,
|
|
||||||
OffsetY = 0,
|
|
||||||
Blur = 0,
|
|
||||||
Spread = BadgeShadowSize,
|
|
||||||
Color = ((SolidColorBrush)BadgeShadowColor).Color
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
105
src/AtomUI.Controls/Badge/DotBadgeAdornerTheme.cs
Normal file
105
src/AtomUI.Controls/Badge/DotBadgeAdornerTheme.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using AtomUI.MotionScene;
|
||||||
|
using AtomUI.Theme;
|
||||||
|
using AtomUI.Theme.Styling;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
using Avalonia.Data;
|
||||||
|
using Avalonia.Data.Converters;
|
||||||
|
using Avalonia.Layout;
|
||||||
|
using Avalonia.Styling;
|
||||||
|
|
||||||
|
namespace AtomUI.Controls.Badge;
|
||||||
|
|
||||||
|
[ControlThemeProvider]
|
||||||
|
internal class DotBadgeAdornerTheme : BaseControlTheme
|
||||||
|
{
|
||||||
|
internal const string IndicatorMotionActorPart = "PART_IndicatorMotionActor";
|
||||||
|
internal const string IndicatorPart = "PART_Indicator";
|
||||||
|
internal const string LabelPart = "PART_Label";
|
||||||
|
internal const string RootLayoutPart = "PART_RootLayout";
|
||||||
|
|
||||||
|
public DotBadgeAdornerTheme()
|
||||||
|
: base(typeof(DotBadgeAdorner))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override IControlTemplate? BuildControlTemplate()
|
||||||
|
{
|
||||||
|
return new FuncControlTemplate<DotBadgeAdorner>((adorner, scope) =>
|
||||||
|
{
|
||||||
|
var layout = new DockPanel()
|
||||||
|
{
|
||||||
|
Name = RootLayoutPart,
|
||||||
|
LastChildFill = true,
|
||||||
|
ClipToBounds = false
|
||||||
|
};
|
||||||
|
BuildIndicator(layout, scope);
|
||||||
|
BuildLabel(layout, scope);
|
||||||
|
return layout;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildIndicator(DockPanel layout, INameScope scope)
|
||||||
|
{
|
||||||
|
var indicatorMotionActor = new MotionActorControl()
|
||||||
|
{
|
||||||
|
Name = IndicatorMotionActorPart,
|
||||||
|
ClipToBounds = false,
|
||||||
|
UseRenderTransform = true
|
||||||
|
};
|
||||||
|
indicatorMotionActor.RegisterInNameScope(scope);
|
||||||
|
var indicator = new DotBadgeIndicator()
|
||||||
|
{
|
||||||
|
Name = IndicatorPart
|
||||||
|
};
|
||||||
|
indicator.RegisterInNameScope(scope);
|
||||||
|
DockPanel.SetDock(indicatorMotionActor, Dock.Left);
|
||||||
|
|
||||||
|
CreateTemplateParentBinding(indicator, DotBadgeIndicator.BadgeDotColorProperty, DotBadgeAdorner.BadgeDotColorProperty);
|
||||||
|
indicatorMotionActor.Child = indicator;
|
||||||
|
layout.Children.Add(indicatorMotionActor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildLabel(DockPanel layout, INameScope scope)
|
||||||
|
{
|
||||||
|
var label = new Label()
|
||||||
|
{
|
||||||
|
Name = LabelPart
|
||||||
|
};
|
||||||
|
label.RegisterInNameScope(scope);
|
||||||
|
CreateTemplateParentBinding(label, Label.ContentProperty, DotBadgeAdorner.TextProperty);
|
||||||
|
CreateTemplateParentBinding(label, Label.IsVisibleProperty, DotBadgeAdorner.IsAdornerModeProperty,
|
||||||
|
BindingMode.Default,
|
||||||
|
BoolConverters.Not);
|
||||||
|
layout.Children.Add(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void BuildStyles()
|
||||||
|
{
|
||||||
|
var commonStyle = new Style(selector => selector.Nesting());
|
||||||
|
commonStyle.Add(DotBadgeAdorner.ClipToBoundsProperty, false);
|
||||||
|
commonStyle.Add(DotBadgeAdorner.BadgeDotColorProperty, BadgeTokenResourceKey.BadgeColor);
|
||||||
|
var inAdornerStyle = new Style(selector => selector.Nesting().PropertyEquals(DotBadgeAdorner.IsAdornerModeProperty, true));
|
||||||
|
var layoutStyle = new Style(selector => selector.Nesting().Template().Name(RootLayoutPart));
|
||||||
|
layoutStyle.Add(DockPanel.HorizontalAlignmentProperty, HorizontalAlignment.Right);
|
||||||
|
layoutStyle.Add(DockPanel.VerticalAlignmentProperty, VerticalAlignment.Top);
|
||||||
|
inAdornerStyle.Add(layoutStyle);
|
||||||
|
commonStyle.Add(inAdornerStyle);
|
||||||
|
|
||||||
|
var labelStyle = new Style(selector => selector.Nesting().Template().Name(LabelPart));
|
||||||
|
labelStyle.Add(Label.HorizontalAlignmentProperty, HorizontalAlignment.Left);
|
||||||
|
labelStyle.Add(Label.VerticalAlignmentProperty, VerticalAlignment.Center);
|
||||||
|
labelStyle.Add(Label.HorizontalContentAlignmentProperty, HorizontalAlignment.Center);
|
||||||
|
labelStyle.Add(Label.VerticalContentAlignmentProperty, VerticalAlignment.Center);
|
||||||
|
labelStyle.Add(Label.MarginProperty, BadgeTokenResourceKey.DotBadgeLabelMargin);
|
||||||
|
commonStyle.Add(labelStyle);
|
||||||
|
|
||||||
|
var indicatorStyle = new Style(selector => selector.Nesting().Template().Name(IndicatorMotionActorPart));
|
||||||
|
|
||||||
|
indicatorStyle.Add(MotionActorControl.WidthProperty, BadgeTokenResourceKey.DotSize);
|
||||||
|
indicatorStyle.Add(MotionActorControl.HeightProperty, BadgeTokenResourceKey.DotSize);
|
||||||
|
commonStyle.Add(indicatorStyle);
|
||||||
|
|
||||||
|
Add(commonStyle);
|
||||||
|
}
|
||||||
|
}
|
90
src/AtomUI.Controls/Badge/DotBadgeIndicator.cs
Normal file
90
src/AtomUI.Controls/Badge/DotBadgeIndicator.cs
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
using AtomUI.Theme.Styling;
|
||||||
|
using AtomUI.Utils;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
|
internal class DotBadgeIndicator : Control
|
||||||
|
{
|
||||||
|
internal static readonly StyledProperty<IBrush?> BadgeDotColorProperty =
|
||||||
|
AvaloniaProperty.Register<DotBadgeIndicator, IBrush?>(
|
||||||
|
nameof(BadgeDotColor));
|
||||||
|
|
||||||
|
internal static readonly StyledProperty<IBrush?> BadgeShadowColorProperty =
|
||||||
|
AvaloniaProperty.Register<DotBadgeIndicator, IBrush?>(
|
||||||
|
nameof(BadgeShadowColor));
|
||||||
|
|
||||||
|
internal static readonly StyledProperty<double> BadgeShadowSizeProperty =
|
||||||
|
AvaloniaProperty.Register<DotBadgeIndicator, double>(
|
||||||
|
nameof(BadgeShadowSize));
|
||||||
|
|
||||||
|
internal IBrush? BadgeDotColor
|
||||||
|
{
|
||||||
|
get => GetValue(BadgeDotColorProperty);
|
||||||
|
set => SetValue(BadgeDotColorProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal IBrush? BadgeShadowColor
|
||||||
|
{
|
||||||
|
get => GetValue(BadgeShadowColorProperty);
|
||||||
|
set => SetValue(BadgeShadowColorProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double BadgeShadowSize
|
||||||
|
{
|
||||||
|
get => GetValue(BadgeShadowSizeProperty);
|
||||||
|
set => SetValue(BadgeShadowSizeProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BoxShadows _boxShadows;
|
||||||
|
|
||||||
|
static DotBadgeIndicator()
|
||||||
|
{
|
||||||
|
AffectsRender<DotBadgeIndicator>(BadgeDotColorProperty, BadgeShadowSizeProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed override void ApplyTemplate()
|
||||||
|
{
|
||||||
|
base.ApplyTemplate();
|
||||||
|
BuildBoxShadow();
|
||||||
|
|
||||||
|
TokenResourceBinder.CreateTokenBinding(this, BadgeShadowSizeProperty, BadgeTokenResourceKey.BadgeShadowSize);
|
||||||
|
TokenResourceBinder.CreateTokenBinding(this, BadgeShadowColorProperty, BadgeTokenResourceKey.BadgeShadowColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnPropertyChanged(e);
|
||||||
|
if (e.Property == BadgeShadowSizeProperty ||
|
||||||
|
e.Property == BadgeShadowColorProperty)
|
||||||
|
{
|
||||||
|
BuildBoxShadow(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Render(DrawingContext context)
|
||||||
|
{
|
||||||
|
context.DrawRectangle(BadgeDotColor, null, new Rect(Bounds.Size), Bounds.Width / 2, Bounds.Height / 2,
|
||||||
|
_boxShadows);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BuildBoxShadow(bool force = false)
|
||||||
|
{
|
||||||
|
if (_boxShadows == default || force)
|
||||||
|
{
|
||||||
|
if (BadgeShadowColor is not null)
|
||||||
|
{
|
||||||
|
_boxShadows = new BoxShadows(new BoxShadow
|
||||||
|
{
|
||||||
|
OffsetX = 0,
|
||||||
|
OffsetY = 0,
|
||||||
|
Blur = 0,
|
||||||
|
Spread = BadgeShadowSize,
|
||||||
|
Color = ((SolidColorBrush)BadgeShadowColor).Color
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using AtomUI.Controls.Utils;
|
||||||
using AtomUI.Controls.Utils;
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Theme.Styling;
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using AtomUI.Controls.Utils;
|
||||||
using AtomUI.Controls.Utils;
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Theme.Data;
|
using AtomUI.Theme.Data;
|
||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Theme.Styling;
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using AtomUI.Controls.Primitives;
|
||||||
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Theme;
|
using AtomUI.Theme;
|
||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Theme.Styling;
|
||||||
using AtomUI.Theme.Utils;
|
using AtomUI.Theme.Utils;
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.AddOnDecoratedInnerBoxTheme());
|
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.AddOnDecoratedInnerBoxTheme());
|
||||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.AlertTheme());
|
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.AlertTheme());
|
||||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.ArrowDecoratedBoxTheme());
|
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.ArrowDecoratedBoxTheme());
|
||||||
|
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.Badge.CountBadgeAdornerTheme());
|
||||||
|
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.Badge.DotBadgeAdornerTheme());
|
||||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.ButtonSpinnerInnerBoxTheme());
|
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.ButtonSpinnerInnerBoxTheme());
|
||||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.ButtonSpinnerTheme());
|
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.ButtonSpinnerTheme());
|
||||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.DefaultButtonTheme());
|
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.DefaultButtonTheme());
|
||||||
|
@ -64,6 +64,7 @@ namespace AtomUI.Theme.Styling
|
|||||||
public static readonly TokenResourceKey BadgeRibbonCornerTransform = new TokenResourceKey("Badge.BadgeRibbonCornerTransform", "AtomUI.Token");
|
public static readonly TokenResourceKey BadgeRibbonCornerTransform = new TokenResourceKey("Badge.BadgeRibbonCornerTransform", "AtomUI.Token");
|
||||||
public static readonly TokenResourceKey BadgeRibbonCornerDarkenAmount = new TokenResourceKey("Badge.BadgeRibbonCornerDarkenAmount", "AtomUI.Token");
|
public static readonly TokenResourceKey BadgeRibbonCornerDarkenAmount = new TokenResourceKey("Badge.BadgeRibbonCornerDarkenAmount", "AtomUI.Token");
|
||||||
public static readonly TokenResourceKey BadgeRibbonTextPadding = new TokenResourceKey("Badge.BadgeRibbonTextPadding", "AtomUI.Token");
|
public static readonly TokenResourceKey BadgeRibbonTextPadding = new TokenResourceKey("Badge.BadgeRibbonTextPadding", "AtomUI.Token");
|
||||||
|
public static readonly TokenResourceKey DotBadgeLabelMargin = new TokenResourceKey("Badge.DotBadgeLabelMargin", "AtomUI.Token");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ButtonSpinnerTokenResourceKey
|
public static class ButtonSpinnerTokenResourceKey
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using AtomUI.Icon;
|
||||||
using AtomUI.Controls.Utils;
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Icon;
|
|
||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Theme.Styling;
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using AtomUI.Controls.Primitives;
|
||||||
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Theme;
|
using AtomUI.Theme;
|
||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Theme.Styling;
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using AtomUI.Controls.Primitives;
|
||||||
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Theme.Styling;
|
||||||
using AtomUI.Theme.Utils;
|
using AtomUI.Theme.Utils;
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using AtomUI.Controls.Primitives;
|
|
||||||
using AtomUI.Controls.Utils;
|
|
||||||
using AtomUI.Data;
|
using AtomUI.Data;
|
||||||
using AtomUI.Icon;
|
using AtomUI.Icon;
|
||||||
using AtomUI.Input;
|
using AtomUI.Input;
|
||||||
using AtomUI.Media;
|
using AtomUI.Media;
|
||||||
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Theme.Styling;
|
||||||
using AtomUI.Theme.Utils;
|
using AtomUI.Theme.Utils;
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
@ -21,7 +20,6 @@ using Avalonia.Data;
|
|||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.LogicalTree;
|
using Avalonia.LogicalTree;
|
||||||
using Avalonia.Media.Transformation;
|
|
||||||
using Avalonia.Rendering;
|
using Avalonia.Rendering;
|
||||||
using Avalonia.VisualTree;
|
using Avalonia.VisualTree;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Controls.Utils;
|
|
||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Theme.Styling;
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
@ -241,7 +240,7 @@ public class NotificationCard : ContentControl
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionConfig? motionConfig;
|
MotionConfigX? motionConfig;
|
||||||
if (Position == NotificationPosition.TopLeft || Position == NotificationPosition.BottomLeft)
|
if (Position == NotificationPosition.TopLeft || Position == NotificationPosition.BottomLeft)
|
||||||
{
|
{
|
||||||
motionConfig = MotionFactory.BuildMoveLeftInMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseOut(),
|
motionConfig = MotionFactory.BuildMoveLeftInMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseOut(),
|
||||||
@ -276,7 +275,7 @@ public class NotificationCard : ContentControl
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MotionConfig? motionConfig;
|
MotionConfigX? motionConfig;
|
||||||
if (Position == NotificationPosition.TopLeft || Position == NotificationPosition.BottomLeft)
|
if (Position == NotificationPosition.TopLeft || Position == NotificationPosition.BottomLeft)
|
||||||
{
|
{
|
||||||
motionConfig = MotionFactory.BuildMoveLeftOutMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseIn(),
|
motionConfig = MotionFactory.BuildMoveLeftOutMotion(AnimationMaxOffsetX, _openCloseMotionDuration, new CubicEaseIn(),
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using AtomUI.Controls.Primitives;
|
using AtomUI.Controls.Primitives;
|
||||||
using AtomUI.Controls.Utils;
|
using AtomUI.Controls.Utils;
|
||||||
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Theme;
|
using AtomUI.Theme;
|
||||||
using AtomUI.Theme.Styling;
|
using AtomUI.Theme.Styling;
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
|
@ -246,7 +246,7 @@ public class Separator : AvaloniaSeparator
|
|||||||
if (lineMinWidth > remainWidth)
|
if (lineMinWidth > remainWidth)
|
||||||
{
|
{
|
||||||
// 字过多
|
// 字过多
|
||||||
titleWidth = finalSize.Width - lineMinWidth;
|
titleWidth = Math.Max(finalSize.Width - lineMinWidth, lineMinWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理完成之后,字的宽度一定在 width 范围内
|
// 处理完成之后,字的宽度一定在 width 范围内
|
||||||
@ -267,7 +267,7 @@ public class Separator : AvaloniaSeparator
|
|||||||
var rightDelta = titleRect.Right - finalSize.Width;
|
var rightDelta = titleRect.Right - finalSize.Width;
|
||||||
if (MathUtils.GreaterThan(rightDelta, 0))
|
if (MathUtils.GreaterThan(rightDelta, 0))
|
||||||
{
|
{
|
||||||
titleRect = titleRect.WithWidth(finalSize.Width - titleRect.Left);
|
titleRect = titleRect.WithWidth(Math.Max(finalSize.Width - titleRect.Left, lineMinWidth));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (TitlePosition == SeparatorTitlePosition.Right)
|
else if (TitlePosition == SeparatorTitlePosition.Right)
|
||||||
@ -297,7 +297,6 @@ public class Separator : AvaloniaSeparator
|
|||||||
new Size(titleWidth, finalSize.Height));
|
new Size(titleWidth, finalSize.Height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return titleRect;
|
return titleRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AtomUI.Controls.Utils;
|
using AtomUI.Controls.Utils;
|
||||||
|
using AtomUI.MotionScene;
|
||||||
using AtomUI.Theme;
|
using AtomUI.Theme;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Animation;
|
using Avalonia.Animation;
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Reflection;
|
|
||||||
using AtomUI.Controls.MotionScene;
|
|
||||||
using AtomUI.MotionScene;
|
|
||||||
using AtomUI.Utils;
|
using AtomUI.Utils;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
@ -279,7 +276,6 @@ internal class ThemeManager : Styles, IThemeManager
|
|||||||
|
|
||||||
internal void Configure()
|
internal void Configure()
|
||||||
{
|
{
|
||||||
RegisterServices();
|
|
||||||
RegisterControlThemes();
|
RegisterControlThemes();
|
||||||
BuildLanguageResources();
|
BuildLanguageResources();
|
||||||
}
|
}
|
||||||
@ -331,12 +327,6 @@ internal class ThemeManager : Styles, IThemeManager
|
|||||||
ControlTokenTypes.Add(tokenType);
|
ControlTokenTypes.Add(tokenType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RegisterServices()
|
|
||||||
{
|
|
||||||
var motionDirector = new Director();
|
|
||||||
AvaloniaLocator.CurrentMutable.Bind<IDirector>()
|
|
||||||
.ToConstant(motionDirector);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ThemeOperateEventArgs : EventArgs
|
public class ThemeOperateEventArgs : EventArgs
|
||||||
|
Loading…
Reference in New Issue
Block a user