feat: replace mask with pure rectangle to reduce layout calculation
This commit is contained in:
@@ -9,6 +9,12 @@
|
||||
</ControlTheme>
|
||||
<ControlTheme x:Key="{x:Type u:CustomDialogControl}" TargetType="u:CustomDialogControl">
|
||||
<Setter Property="CornerRadius" Value="12" />
|
||||
<Setter Property="Transitions">
|
||||
<Transitions>
|
||||
<TransformOperationsTransition Duration="0.2" Property="RenderTransform"/>
|
||||
</Transitions>
|
||||
</Setter>
|
||||
<Setter Property="RenderTransform" Value="scale(1.0)"></Setter>
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:CustomDialogControl">
|
||||
<Border
|
||||
@@ -46,6 +52,9 @@
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^[IsClosed=True]">
|
||||
<Setter Property="RenderTransform" Value="scale(0.95)"/>
|
||||
</Style>
|
||||
<Style Selector="^ /template/ Panel#PART_TitleArea">
|
||||
<Setter Property="ContextFlyout">
|
||||
<MenuFlyout>
|
||||
|
||||
@@ -105,7 +105,6 @@ public partial class OverlayDialogHost
|
||||
}
|
||||
else if (_modalDialogs.Contains(control))
|
||||
{
|
||||
_modalDialogs.Remove(control);
|
||||
if (_masks.Count > 0)
|
||||
{
|
||||
var last = _masks.Last();
|
||||
@@ -117,8 +116,9 @@ public partial class OverlayDialogHost
|
||||
_masks.Last().IsVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
_modalDialogs.Remove(control);
|
||||
}
|
||||
|
||||
ResetZIndices();
|
||||
}
|
||||
}
|
||||
@@ -133,10 +133,6 @@ public partial class OverlayDialogHost
|
||||
_masks.Add(mask);
|
||||
_modalDialogs.Add(control);
|
||||
control.SetAsModal(true);
|
||||
for (int i = 0; i < _masks.Count-1; i++)
|
||||
{
|
||||
_masks[i].Opacity = 0.5;
|
||||
}
|
||||
ResetZIndices();
|
||||
this.Children.Add(mask);
|
||||
this.Children.Add(control);
|
||||
@@ -146,6 +142,7 @@ public partial class OverlayDialogHost
|
||||
control.AddHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing);
|
||||
control.AddHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged);
|
||||
_maskAppearAnimation.RunAsync(mask);
|
||||
control.IsClosed = false;
|
||||
}
|
||||
|
||||
// Handle dialog layer change event
|
||||
|
||||
@@ -25,8 +25,8 @@ public partial class OverlayDialogHost
|
||||
this.Children.Add(mask);
|
||||
this.Children.Add(control);
|
||||
control.Measure(this.Bounds.Size);
|
||||
control.Arrange(new Rect(control.DesiredSize));
|
||||
control.Height = this.Bounds.Height;
|
||||
control.Arrange(new Rect(control.DesiredSize).WithHeight(this.Bounds.Height));
|
||||
// control.Height = this.Bounds.Height;
|
||||
control.AddHandler(OverlayFeedbackElement.ClosedEvent, OnDrawerControlClosing);
|
||||
var animation = CreateAnimation(control.Bounds.Width);
|
||||
var animation2 = CreateOpacityAnimation();
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
using Ursa.Controls.OverlayShared;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Styling;
|
||||
using Ursa.Controls.Shapes;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
@@ -14,9 +16,17 @@ public partial class OverlayDialogHost: Canvas
|
||||
{
|
||||
private readonly List<OverlayFeedbackElement> _dialogs = new();
|
||||
private readonly List<OverlayFeedbackElement> _modalDialogs = new();
|
||||
private readonly List<Border> _masks = new();
|
||||
private readonly List<PureRectangle> _masks = new();
|
||||
private static readonly Animation _maskAppearAnimation;
|
||||
private static readonly Animation _maskDisappearAnimation;
|
||||
|
||||
private readonly List<DialogPair> _layers = new List<DialogPair>();
|
||||
|
||||
private struct DialogPair
|
||||
{
|
||||
internal PureRectangle Mask;
|
||||
internal OverlayFeedbackElement Dialog;
|
||||
}
|
||||
|
||||
static OverlayDialogHost()
|
||||
{
|
||||
@@ -29,9 +39,9 @@ public partial class OverlayDialogHost: Canvas
|
||||
{
|
||||
var animation = new Animation();
|
||||
animation.FillMode = FillMode.Forward;
|
||||
var keyFrame1 = new KeyFrame(){ Cue = new Cue(0.0) };
|
||||
var keyFrame1 = new KeyFrame{ Cue = new Cue(0.0) };
|
||||
keyFrame1.Setters.Add(new Setter() { Property = OpacityProperty, Value = appear ? 0.0 : 1.0 });
|
||||
var keyFrame2 = new KeyFrame() { Cue = new Cue(1.0) };
|
||||
var keyFrame2 = new KeyFrame{ Cue = new Cue(1.0) };
|
||||
keyFrame2.Setters.Add(new Setter() { Property = OpacityProperty, Value = appear ? 1.0 : 0.0 });
|
||||
animation.Children.Add(keyFrame1);
|
||||
animation.Children.Add(keyFrame2);
|
||||
@@ -53,27 +63,27 @@ public partial class OverlayDialogHost: Canvas
|
||||
set => SetValue(OverlayMaskBrushProperty, value);
|
||||
}
|
||||
|
||||
private Border CreateOverlayMask(bool canCloseOnClick)
|
||||
private PureRectangle CreateOverlayMask(bool canCloseOnClick)
|
||||
{
|
||||
Border border = new()
|
||||
PureRectangle rec = new()
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
VerticalAlignment = VerticalAlignment.Stretch,
|
||||
Width = this.Bounds.Width,
|
||||
Height = this.Bounds.Height,
|
||||
[!BackgroundProperty] = this[!OverlayMaskBrushProperty],
|
||||
[!Shape.FillProperty] = this[!OverlayMaskBrushProperty],
|
||||
IsVisible = true,
|
||||
};
|
||||
if (canCloseOnClick)
|
||||
{
|
||||
border.AddHandler(PointerReleasedEvent, ClickBorderToCloseDialog);
|
||||
rec.AddHandler(PointerReleasedEvent, ClickBorderToCloseDialog);
|
||||
}
|
||||
return border;
|
||||
return rec;
|
||||
}
|
||||
|
||||
private void ClickBorderToCloseDialog(object sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (sender is Border border)
|
||||
if (sender is PureRectangle border)
|
||||
{
|
||||
int i = _masks.IndexOf(border);
|
||||
if (_modalDialogs[i] is { } element)
|
||||
@@ -139,6 +149,21 @@ public partial class OverlayDialogHost: Canvas
|
||||
(_modalDialogs[i] as Control)!.ZIndex = index;
|
||||
index++;
|
||||
}
|
||||
|
||||
int index2 = 0;
|
||||
for (int i = 0; i < _layers.Count; i++)
|
||||
{
|
||||
if(_layers[i].Mask is { } mask)
|
||||
{
|
||||
mask.ZIndex = index2;
|
||||
index2++;
|
||||
}
|
||||
if(_layers[i].Dialog is { } dialog)
|
||||
{
|
||||
dialog.ZIndex = index2;
|
||||
index2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal IDataTemplate? GetDataTemplate(object? o)
|
||||
|
||||
@@ -8,11 +8,26 @@ namespace Ursa.Controls.OverlayShared;
|
||||
|
||||
public abstract class OverlayFeedbackElement: ContentControl
|
||||
{
|
||||
public static readonly StyledProperty<bool> IsClosedProperty =
|
||||
AvaloniaProperty.Register<OverlayFeedbackElement, bool>(nameof(IsClosed), defaultValue: true);
|
||||
|
||||
public bool IsClosed
|
||||
{
|
||||
get => GetValue(IsClosedProperty);
|
||||
set => SetValue(IsClosedProperty, value);
|
||||
}
|
||||
|
||||
static OverlayFeedbackElement()
|
||||
{
|
||||
DataContextProperty.Changed.AddClassHandler<CustomDialogControl, object?>((o, e) => o.OnDataContextChange(e));
|
||||
ClosedEvent.AddClassHandler<OverlayFeedbackElement>((o,e)=>o.OnClosed(e));
|
||||
}
|
||||
|
||||
|
||||
private void OnClosed(ResultEventArgs arg2)
|
||||
{
|
||||
SetCurrentValue(IsClosedProperty,true);
|
||||
}
|
||||
|
||||
public static readonly RoutedEvent<ResultEventArgs> ClosedEvent = RoutedEvent.Register<DrawerControlBase, ResultEventArgs>(
|
||||
nameof(Closed), RoutingStrategies.Bubble);
|
||||
|
||||
|
||||
35
src/Ursa/Controls/Shapes/PureRectangle.cs
Normal file
35
src/Ursa/Controls/Shapes/PureRectangle.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace Ursa.Controls.Shapes;
|
||||
|
||||
/// <summary>
|
||||
/// A rectangle, with no corner radius.
|
||||
/// </summary>
|
||||
public class PureRectangle: Shape
|
||||
{
|
||||
static PureRectangle()
|
||||
{
|
||||
FocusableProperty.OverrideDefaultValue<PureRectangle>(false);
|
||||
AffectsGeometry<PureRectangle>(BoundsProperty);
|
||||
}
|
||||
protected override Geometry? CreateDefiningGeometry()
|
||||
{
|
||||
StreamGeometry geometry = new StreamGeometry();
|
||||
Rect rect = new Rect(this.Bounds.Size).Deflate(this.StrokeThickness / 2.0);
|
||||
using StreamGeometryContext context = geometry.Open();
|
||||
context.BeginFigure(new Point(rect.Left, rect.Top), true);
|
||||
context.LineTo(new Point(rect.Right, rect.Top));
|
||||
context.LineTo(new Point(rect.Right, rect.Bottom));
|
||||
context.LineTo(new Point(rect.Left, rect.Bottom));
|
||||
context.LineTo(new Point(rect.Left, rect.Top));
|
||||
context.EndFigure(true);
|
||||
return geometry;
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
return new Size(this.StrokeThickness, this.StrokeThickness);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user