mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-29 18:38:16 +08:00
Refactor ArrowDecoratedBox
This commit is contained in:
parent
e0fb335357
commit
9d219301f2
@ -23,4 +23,5 @@
|
|||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002EMemberReordering_002EMigrations_002ECSharpFileLayoutPatternRemoveIsAttributeUpgrade/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@ -117,6 +117,9 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
internal static readonly StyledProperty<double> ArrowSizeProperty
|
internal static readonly StyledProperty<double> ArrowSizeProperty
|
||||||
= AvaloniaProperty.Register<ArrowDecoratedBox, double>(nameof(ArrowSize));
|
= AvaloniaProperty.Register<ArrowDecoratedBox, double>(nameof(ArrowSize));
|
||||||
|
|
||||||
|
internal static readonly StyledProperty<Direction> ArrowDirectionProperty
|
||||||
|
= AvaloniaProperty.Register<ArrowDecoratedBox, Direction>(nameof(ArrowDirection));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 箭头的大小
|
/// 箭头的大小
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -125,7 +128,13 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
get => GetValue(ArrowSizeProperty);
|
get => GetValue(ArrowSizeProperty);
|
||||||
set => SetValue(ArrowSizeProperty, value);
|
set => SetValue(ArrowSizeProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal Direction ArrowDirection
|
||||||
|
{
|
||||||
|
get => GetValue(ArrowDirectionProperty);
|
||||||
|
set => SetValue(ArrowDirectionProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
// 指针最顶点位置
|
// 指针最顶点位置
|
||||||
@ -133,13 +142,19 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
private (double, double) _arrowVertexPoint;
|
private (double, double) _arrowVertexPoint;
|
||||||
internal (double, double) ArrowVertexPoint => GetArrowVertexPoint();
|
internal (double, double) ArrowVertexPoint => GetArrowVertexPoint();
|
||||||
private Geometry? _arrowGeometry;
|
private Geometry? _arrowGeometry;
|
||||||
private Rect _contentRect;
|
|
||||||
private Rect _arrowRect;
|
private Rect _arrowRect;
|
||||||
private bool _needGenerateArrowVertexPoint = true;
|
private bool _needGenerateArrowVertexPoint = true;
|
||||||
|
private Border? _contentDecorator;
|
||||||
|
|
||||||
static ArrowDecoratedBox()
|
static ArrowDecoratedBox()
|
||||||
{
|
{
|
||||||
AffectsMeasure<ArrowDecoratedBox>(ArrowPositionProperty, IsShowArrowProperty);
|
AffectsMeasure<ArrowDecoratedBox>(IsShowArrowProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrowDecoratedBox()
|
||||||
|
{
|
||||||
|
IsShowArrow = true;
|
||||||
|
ArrowPosition = ArrowPosition.BottomEdgeAlignedLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Direction GetDirection(ArrowPosition arrowPosition)
|
public static Direction GetDirection(ArrowPosition arrowPosition)
|
||||||
@ -179,17 +194,19 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
|
|
||||||
public Rect GetMaskBounds()
|
public Rect GetMaskBounds()
|
||||||
{
|
{
|
||||||
return GetContentRect(DesiredSize).Deflate(0.5);
|
if (_contentDecorator is not null)
|
||||||
|
{
|
||||||
|
return _contentDecorator.Bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnApplyTemplate(e);
|
base.OnApplyTemplate(e);
|
||||||
HandleTemplateApplied(e.NameScope);
|
_contentDecorator = e.NameScope.Get<Border>(ArrowDecoratedBoxTheme.ContentDecoratorPart);
|
||||||
}
|
|
||||||
|
|
||||||
private void HandleTemplateApplied(INameScope scope)
|
|
||||||
{
|
|
||||||
if (IsShowArrow)
|
if (IsShowArrow)
|
||||||
{
|
{
|
||||||
BuildGeometry(true);
|
BuildGeometry(true);
|
||||||
@ -219,14 +236,22 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
{
|
{
|
||||||
// 当开启的时候,但是还没有加入的渲染树,这个时候我们取不到 Token 需要在取值的时候重新生成一下
|
// 当开启的时候,但是还没有加入的渲染树,这个时候我们取不到 Token 需要在取值的时候重新生成一下
|
||||||
_needGenerateArrowVertexPoint = true;
|
_needGenerateArrowVertexPoint = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (VisualRoot is not null)
|
if (VisualRoot is not null)
|
||||||
{
|
{
|
||||||
BuildGeometry(true);
|
BuildGeometry(true);
|
||||||
_arrowRect = GetArrowRect(DesiredSize);
|
_arrowRect = GetArrowRect(DesiredSize);
|
||||||
|
|
||||||
|
InvalidateArrange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (e.Property == ArrowPositionProperty)
|
||||||
|
{
|
||||||
|
ArrowDirection = GetDirection(ArrowPosition);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildGeometry(bool force = false)
|
private void BuildGeometry(bool force = false)
|
||||||
@ -241,9 +266,10 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
{
|
{
|
||||||
if (IsShowArrow)
|
if (IsShowArrow)
|
||||||
{
|
{
|
||||||
|
|
||||||
var direction = GetDirection(ArrowPosition);
|
var direction = GetDirection(ArrowPosition);
|
||||||
var matrix = Matrix.CreateTranslation(-ArrowSize / 2, -ArrowSize / 2);
|
var matrix = Matrix.CreateTranslation(-ArrowSize / 2, -ArrowSize / 2);
|
||||||
|
|
||||||
if (direction == Direction.Right)
|
if (direction == Direction.Right)
|
||||||
{
|
{
|
||||||
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(90));
|
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(90));
|
||||||
@ -263,97 +289,12 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(180));
|
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(180));
|
||||||
matrix *= Matrix.CreateTranslation(ArrowSize / 2, ArrowSize / 2);
|
matrix *= Matrix.CreateTranslation(ArrowSize / 2, ArrowSize / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
matrix *= Matrix.CreateTranslation(_arrowRect.X, _arrowRect.Y);
|
matrix *= Matrix.CreateTranslation(_arrowRect.X, _arrowRect.Y);
|
||||||
_arrowGeometry!.Transform = new MatrixTransform(matrix);
|
_arrowGeometry!.Transform = new MatrixTransform(matrix);
|
||||||
context.DrawGeometry(Background, null, _arrowGeometry);
|
context.DrawGeometry(Background, null, _arrowGeometry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Size MeasureOverride(Size availableSize)
|
|
||||||
{
|
|
||||||
var size = base.MeasureOverride(availableSize);
|
|
||||||
var targetWidth = size.Width;
|
|
||||||
var targetHeight = size.Height;
|
|
||||||
targetHeight = Math.Max(MinHeight, targetHeight);
|
|
||||||
|
|
||||||
if (IsShowArrow)
|
|
||||||
{
|
|
||||||
BuildGeometry();
|
|
||||||
var realArrowSize = Math.Min(_arrowGeometry!.Bounds.Size.Height, _arrowGeometry!.Bounds.Size.Width);
|
|
||||||
var direction = GetDirection(ArrowPosition);
|
|
||||||
if (direction == Direction.Left || direction == Direction.Right)
|
|
||||||
{
|
|
||||||
targetWidth += realArrowSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
targetHeight += realArrowSize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetSize = new Size(targetWidth, targetHeight);
|
|
||||||
_arrowRect = GetArrowRect(targetSize);
|
|
||||||
return targetSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Size ArrangeOverride(Size finalSize)
|
|
||||||
{
|
|
||||||
var visualChildren = VisualChildren;
|
|
||||||
var visualCount = visualChildren.Count;
|
|
||||||
_contentRect = GetContentRect(finalSize);
|
|
||||||
for (var i = 0; i < visualCount; ++i)
|
|
||||||
{
|
|
||||||
var child = visualChildren[i];
|
|
||||||
if (child is Layoutable layoutable)
|
|
||||||
{
|
|
||||||
layoutable.Arrange(_contentRect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return finalSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal Rect GetContentRect(Size finalSize)
|
|
||||||
{
|
|
||||||
var offsetX = 0d;
|
|
||||||
var offsetY = 0d;
|
|
||||||
var targetWidth = finalSize.Width;
|
|
||||||
var targetHeight = finalSize.Height;
|
|
||||||
if (IsShowArrow)
|
|
||||||
{
|
|
||||||
var arrowSize = Math.Min(_arrowGeometry!.Bounds.Size.Height, _arrowGeometry!.Bounds.Size.Width) + 0.5;
|
|
||||||
var direction = GetDirection(ArrowPosition);
|
|
||||||
if (direction == Direction.Left || direction == Direction.Right)
|
|
||||||
{
|
|
||||||
targetWidth -= arrowSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
targetHeight -= arrowSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (direction == Direction.Right)
|
|
||||||
{
|
|
||||||
offsetX = 0.5;
|
|
||||||
}
|
|
||||||
else if (direction == Direction.Bottom)
|
|
||||||
{
|
|
||||||
offsetY = 0.5;
|
|
||||||
}
|
|
||||||
else if (direction == Direction.Top)
|
|
||||||
{
|
|
||||||
offsetY = arrowSize - 0.5;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
offsetX = arrowSize - 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Rect(offsetX, offsetY, targetWidth, targetHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Rect GetArrowRect(Size finalSize)
|
private Rect GetArrowRect(Size finalSize)
|
||||||
{
|
{
|
||||||
var offsetX = 0d;
|
var offsetX = 0d;
|
||||||
@ -371,6 +312,7 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
position == ArrowPosition.LeftEdgeAlignedTop ||
|
position == ArrowPosition.LeftEdgeAlignedTop ||
|
||||||
position == ArrowPosition.LeftEdgeAlignedBottom)
|
position == ArrowPosition.LeftEdgeAlignedBottom)
|
||||||
{
|
{
|
||||||
|
offsetX = 0.5d;
|
||||||
targetWidth = minValue;
|
targetWidth = minValue;
|
||||||
targetHeight = maxValue;
|
targetHeight = maxValue;
|
||||||
if (position == ArrowPosition.Left)
|
if (position == ArrowPosition.Left)
|
||||||
@ -404,6 +346,7 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
position == ArrowPosition.TopEdgeAlignedLeft ||
|
position == ArrowPosition.TopEdgeAlignedLeft ||
|
||||||
position == ArrowPosition.TopEdgeAlignedRight)
|
position == ArrowPosition.TopEdgeAlignedRight)
|
||||||
{
|
{
|
||||||
|
offsetY = 0.5d;
|
||||||
if (position == ArrowPosition.TopEdgeAlignedLeft)
|
if (position == ArrowPosition.TopEdgeAlignedLeft)
|
||||||
{
|
{
|
||||||
offsetX = maxValue;
|
offsetX = maxValue;
|
||||||
@ -424,7 +367,7 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
position == ArrowPosition.RightEdgeAlignedTop ||
|
position == ArrowPosition.RightEdgeAlignedTop ||
|
||||||
position == ArrowPosition.RightEdgeAlignedBottom)
|
position == ArrowPosition.RightEdgeAlignedBottom)
|
||||||
{
|
{
|
||||||
offsetX = finalSize.Width - minValue;
|
offsetX = finalSize.Width - minValue - 1.0d;
|
||||||
if (position == ArrowPosition.Right)
|
if (position == ArrowPosition.Right)
|
||||||
{
|
{
|
||||||
offsetY = (finalSize.Height - maxValue) / 2;
|
offsetY = (finalSize.Height - maxValue) / 2;
|
||||||
@ -457,7 +400,7 @@ public class ArrowDecoratedBox : ContentControl,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
offsetY = finalSize.Height - minValue;
|
offsetY = finalSize.Height - minValue - 1.0d;
|
||||||
targetWidth = maxValue;
|
targetWidth = maxValue;
|
||||||
targetHeight = minValue;
|
targetHeight = minValue;
|
||||||
if (position == ArrowPosition.BottomEdgeAlignedLeft)
|
if (position == ArrowPosition.BottomEdgeAlignedLeft)
|
||||||
|
@ -6,6 +6,7 @@ using Avalonia.Controls.Presenters;
|
|||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
|
using Avalonia.Media;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
|
||||||
namespace AtomUI.Controls;
|
namespace AtomUI.Controls;
|
||||||
@ -13,8 +14,10 @@ namespace AtomUI.Controls;
|
|||||||
[ControlThemeProvider]
|
[ControlThemeProvider]
|
||||||
internal class ArrowDecoratedBoxTheme : BaseControlTheme
|
internal class ArrowDecoratedBoxTheme : BaseControlTheme
|
||||||
{
|
{
|
||||||
public const string DecoratorPart = "PART_Decorator";
|
public const string ContentDecoratorPart = "PART_ContentDecorator";
|
||||||
|
public const string ContentLayoutPart = "PART_ContentLayout";
|
||||||
public const string ContentPresenterPart = "PART_ContentPresenter";
|
public const string ContentPresenterPart = "PART_ContentPresenter";
|
||||||
|
public const string ArrowContentPart = "PART_ArrowContent";
|
||||||
|
|
||||||
public ArrowDecoratedBoxTheme() : this(typeof(ArrowDecoratedBox))
|
public ArrowDecoratedBoxTheme() : this(typeof(ArrowDecoratedBox))
|
||||||
{
|
{
|
||||||
@ -28,32 +31,48 @@ internal class ArrowDecoratedBoxTheme : BaseControlTheme
|
|||||||
{
|
{
|
||||||
return new FuncControlTemplate<ArrowDecoratedBox>((box, scope) =>
|
return new FuncControlTemplate<ArrowDecoratedBox>((box, scope) =>
|
||||||
{
|
{
|
||||||
var decorator = new Border
|
var contentLayout = new DockPanel()
|
||||||
{
|
{
|
||||||
Name = DecoratorPart,
|
Name = ContentLayoutPart,
|
||||||
Margin = new Thickness(0)
|
LastChildFill = true
|
||||||
};
|
};
|
||||||
|
|
||||||
decorator.RegisterInNameScope(scope);
|
var arrowContent = new Control()
|
||||||
|
{
|
||||||
decorator.Child = BuildContent(scope);
|
Name = ArrowContentPart
|
||||||
|
};
|
||||||
CreateTemplateParentBinding(decorator, Border.BackgroundSizingProperty,
|
CreateTemplateParentBinding(arrowContent, Border.IsVisibleProperty,
|
||||||
|
ArrowDecoratedBox.IsShowArrowProperty);
|
||||||
|
contentLayout.Children.Add(arrowContent);
|
||||||
|
arrowContent.RegisterInNameScope(scope);
|
||||||
|
|
||||||
|
var content = BuildContent(scope);
|
||||||
|
var contentDecorator = new Border
|
||||||
|
{
|
||||||
|
Name = ContentDecoratorPart,
|
||||||
|
Margin = new Thickness(0)
|
||||||
|
};
|
||||||
|
contentDecorator.RegisterInNameScope(scope);
|
||||||
|
; CreateTemplateParentBinding(contentDecorator, Border.BackgroundSizingProperty,
|
||||||
TemplatedControl.BackgroundSizingProperty);
|
TemplatedControl.BackgroundSizingProperty);
|
||||||
CreateTemplateParentBinding(decorator, Border.BackgroundProperty, TemplatedControl.BackgroundProperty);
|
CreateTemplateParentBinding(contentDecorator, Border.BackgroundProperty, TemplatedControl.BackgroundProperty);
|
||||||
CreateTemplateParentBinding(decorator, Border.CornerRadiusProperty, TemplatedControl.CornerRadiusProperty);
|
CreateTemplateParentBinding(contentDecorator, Border.CornerRadiusProperty, TemplatedControl.CornerRadiusProperty);
|
||||||
CreateTemplateParentBinding(decorator, Decorator.PaddingProperty, TemplatedControl.PaddingProperty);
|
CreateTemplateParentBinding(contentDecorator, Decorator.PaddingProperty, TemplatedControl.PaddingProperty);
|
||||||
|
|
||||||
return decorator;
|
contentDecorator.Child = content;
|
||||||
|
|
||||||
|
contentLayout.Children.Add(contentDecorator);
|
||||||
|
return contentLayout;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual Control BuildContent(INameScope scope)
|
protected virtual Control BuildContent(INameScope scope)
|
||||||
{
|
{
|
||||||
var contentPresenter = new ContentPresenter
|
var contentPresenter = new ContentPresenter
|
||||||
{
|
{
|
||||||
Name = ContentPresenterPart
|
Name = ContentPresenterPart
|
||||||
};
|
};
|
||||||
|
|
||||||
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, ContentControl.ContentProperty);
|
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, ContentControl.ContentProperty);
|
||||||
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty,
|
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty,
|
||||||
ContentControl.ContentTemplateProperty);
|
ContentControl.ContentTemplateProperty);
|
||||||
@ -69,6 +88,43 @@ internal class ArrowDecoratedBoxTheme : BaseControlTheme
|
|||||||
commonStyle.Add(TemplatedControl.PaddingProperty, ArrowDecoratedBoxTokenResourceKey.Padding);
|
commonStyle.Add(TemplatedControl.PaddingProperty, ArrowDecoratedBoxTokenResourceKey.Padding);
|
||||||
commonStyle.Add(ArrowDecoratedBox.ArrowSizeProperty, ArrowDecoratedBoxTokenResourceKey.ArrowSize);
|
commonStyle.Add(ArrowDecoratedBox.ArrowSizeProperty, ArrowDecoratedBoxTokenResourceKey.ArrowSize);
|
||||||
commonStyle.Add(TemplatedControl.CornerRadiusProperty, GlobalTokenResourceKey.BorderRadius);
|
commonStyle.Add(TemplatedControl.CornerRadiusProperty, GlobalTokenResourceKey.BorderRadius);
|
||||||
|
BuildArrowDirectionStyle(commonStyle);
|
||||||
Add(commonStyle);
|
Add(commonStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BuildArrowDirectionStyle(Style commonStyle)
|
||||||
|
{
|
||||||
|
var topDirectionStyle = new Style(selector => selector.Nesting().PropertyEquals(ArrowDecoratedBox.ArrowDirectionProperty, Direction.Top));
|
||||||
|
{
|
||||||
|
var arrowContentStyle = new Style(selector => selector.Nesting().Template().Name(ArrowContentPart));
|
||||||
|
arrowContentStyle.Add(DockPanel.DockProperty, Dock.Top);
|
||||||
|
arrowContentStyle.Add(Control.HeightProperty, ArrowDecoratedBoxTokenResourceKey.ArrowContentThickness);
|
||||||
|
topDirectionStyle.Add(arrowContentStyle);
|
||||||
|
}
|
||||||
|
commonStyle.Add(topDirectionStyle);
|
||||||
|
var rightDirectionStyle = new Style(selector => selector.Nesting().PropertyEquals(ArrowDecoratedBox.ArrowDirectionProperty, Direction.Right));
|
||||||
|
{
|
||||||
|
var arrowContentStyle = new Style(selector => selector.Nesting().Template().Name(ArrowContentPart));
|
||||||
|
arrowContentStyle.Add(DockPanel.DockProperty, Dock.Right);
|
||||||
|
arrowContentStyle.Add(Control.WidthProperty, ArrowDecoratedBoxTokenResourceKey.ArrowContentThickness);
|
||||||
|
rightDirectionStyle.Add(arrowContentStyle);
|
||||||
|
}
|
||||||
|
commonStyle.Add(rightDirectionStyle);
|
||||||
|
var bottomDirectionStyle = new Style(selector => selector.Nesting().PropertyEquals(ArrowDecoratedBox.ArrowDirectionProperty, Direction.Bottom));
|
||||||
|
{
|
||||||
|
var arrowContentStyle = new Style(selector => selector.Nesting().Template().Name(ArrowContentPart));
|
||||||
|
arrowContentStyle.Add(DockPanel.DockProperty, Dock.Bottom);
|
||||||
|
arrowContentStyle.Add(Control.HeightProperty, ArrowDecoratedBoxTokenResourceKey.ArrowContentThickness);
|
||||||
|
bottomDirectionStyle.Add(arrowContentStyle);
|
||||||
|
}
|
||||||
|
commonStyle.Add(bottomDirectionStyle);
|
||||||
|
var leftDirectionStyle = new Style(selector => selector.Nesting().PropertyEquals(ArrowDecoratedBox.ArrowDirectionProperty, Direction.Left));
|
||||||
|
{
|
||||||
|
var arrowContentStyle = new Style(selector => selector.Nesting().Template().Name(ArrowContentPart));
|
||||||
|
arrowContentStyle.Add(DockPanel.DockProperty, Dock.Left);
|
||||||
|
arrowContentStyle.Add(Control.WidthProperty, ArrowDecoratedBoxTokenResourceKey.ArrowContentThickness);
|
||||||
|
leftDirectionStyle.Add(arrowContentStyle);
|
||||||
|
}
|
||||||
|
commonStyle.Add(leftDirectionStyle);
|
||||||
|
}
|
||||||
}
|
}
|
@ -12,6 +12,11 @@ public class ArrowDecoratedBoxToken : AbstractControlDesignToken
|
|||||||
/// 箭头三角形大小
|
/// 箭头三角形大小
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double ArrowSize { get; set; }
|
public double ArrowSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 绘制箭头的厚度,跟位置有关
|
||||||
|
/// </summary>
|
||||||
|
public double ArrowContentThickness { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 默认的内边距
|
/// 默认的内边距
|
||||||
@ -26,7 +31,8 @@ public class ArrowDecoratedBoxToken : AbstractControlDesignToken
|
|||||||
internal override void CalculateFromAlias()
|
internal override void CalculateFromAlias()
|
||||||
{
|
{
|
||||||
base.CalculateFromAlias();
|
base.CalculateFromAlias();
|
||||||
ArrowSize = _globalToken.SeedToken.SizePopupArrow / 1.3;
|
ArrowSize = _globalToken.SeedToken.SizePopupArrow / 1.3;
|
||||||
Padding = new Thickness(_globalToken.PaddingXS);
|
ArrowContentThickness = ArrowSize / 2;
|
||||||
|
Padding = new Thickness(_globalToken.PaddingXS);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,6 +6,7 @@ using AtomUI.Utils;
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives.PopupPositioning;
|
using Avalonia.Controls.Primitives.PopupPositioning;
|
||||||
|
using Avalonia.Data;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Metadata;
|
using Avalonia.Metadata;
|
||||||
@ -149,9 +150,9 @@ public class Flyout : PopupFlyoutBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var placement = Placement;
|
var placement = popup.Placement;
|
||||||
var anchor = PlacementAnchor;
|
var anchor = popup.PlacementAnchor;
|
||||||
var gravity = PlacementGravity;
|
var gravity = popup.PlacementGravity;
|
||||||
|
|
||||||
if (flyoutPresenter is not null)
|
if (flyoutPresenter is not null)
|
||||||
{
|
{
|
||||||
@ -178,11 +179,11 @@ public class Flyout : PopupFlyoutBase
|
|||||||
protected internal override void NotifyPopupCreated(Popup popup)
|
protected internal override void NotifyPopupCreated(Popup popup)
|
||||||
{
|
{
|
||||||
base.NotifyPopupCreated(popup);
|
base.NotifyPopupCreated(popup);
|
||||||
BindUtils.RelayBind(this, PlacementProperty, popup, Avalonia.Controls.Primitives.Popup.PlacementProperty);
|
BindUtils.RelayBind(this, PlacementProperty, popup, Popup.PlacementProperty);
|
||||||
BindUtils.RelayBind(this, PlacementAnchorProperty, popup,
|
BindUtils.RelayBind(this, PlacementAnchorProperty, popup,
|
||||||
Avalonia.Controls.Primitives.Popup.PlacementAnchorProperty);
|
Popup.PlacementAnchorProperty);
|
||||||
BindUtils.RelayBind(this, PlacementGravityProperty, popup,
|
BindUtils.RelayBind(this, PlacementGravityProperty, popup,
|
||||||
Avalonia.Controls.Primitives.Popup.PlacementGravityProperty);
|
Popup.PlacementGravityProperty);
|
||||||
BindUtils.RelayBind(this, MaskShadowsProperty, popup, Popup.MaskShadowsProperty);
|
BindUtils.RelayBind(this, MaskShadowsProperty, popup, Popup.MaskShadowsProperty);
|
||||||
SetupArrowPosition(popup);
|
SetupArrowPosition(popup);
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ public class MenuFlyoutPresenter : MenuBase, IShadowMaskInfoProvider
|
|||||||
{
|
{
|
||||||
if (_arrowDecoratedBox is not null)
|
if (_arrowDecoratedBox is not null)
|
||||||
{
|
{
|
||||||
var contentRect = _arrowDecoratedBox.GetContentRect(Bounds.Size);
|
var contentRect = _arrowDecoratedBox.GetMaskBounds();
|
||||||
var adjustedPos = _arrowDecoratedBox.TranslatePoint(contentRect.Position, this) ?? default;
|
var adjustedPos = _arrowDecoratedBox.TranslatePoint(contentRect.Position, this) ?? default;
|
||||||
return new Rect(adjustedPos, contentRect.Size);
|
return new Rect(adjustedPos, contentRect.Size);
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ namespace AtomUI.Theme.Styling
|
|||||||
public static class ArrowDecoratedBoxTokenResourceKey
|
public static class ArrowDecoratedBoxTokenResourceKey
|
||||||
{
|
{
|
||||||
public static readonly TokenResourceKey ArrowSize = new TokenResourceKey("ArrowDecoratedBox.ArrowSize", "AtomUI.Token");
|
public static readonly TokenResourceKey ArrowSize = new TokenResourceKey("ArrowDecoratedBox.ArrowSize", "AtomUI.Token");
|
||||||
|
public static readonly TokenResourceKey ArrowContentThickness = new TokenResourceKey("ArrowDecoratedBox.ArrowContentThickness", "AtomUI.Token");
|
||||||
public static readonly TokenResourceKey Padding = new TokenResourceKey("ArrowDecoratedBox.Padding", "AtomUI.Token");
|
public static readonly TokenResourceKey Padding = new TokenResourceKey("ArrowDecoratedBox.Padding", "AtomUI.Token");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ public class Popup : AvaloniaPopup
|
|||||||
private bool _initialized;
|
private bool _initialized;
|
||||||
private ManagedPopupPositionerInfo? _managedPopupPositioner;
|
private ManagedPopupPositionerInfo? _managedPopupPositioner;
|
||||||
protected bool _animating;
|
protected bool _animating;
|
||||||
|
private bool _isNeedFlip = true;
|
||||||
|
|
||||||
// 当鼠标移走了,但是打开动画还没完成,我们需要记录下来这个信号
|
// 当鼠标移走了,但是打开动画还没完成,我们需要记录下来这个信号
|
||||||
internal bool RequestCloseWhereAnimationCompleted { get; set; }
|
internal bool RequestCloseWhereAnimationCompleted { get; set; }
|
||||||
@ -147,11 +148,14 @@ public class Popup : AvaloniaPopup
|
|||||||
"Unable to create shadow layer, top level for PlacementTarget is null.");
|
"Unable to create shadow layer, top level for PlacementTarget is null.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Placement != PlacementMode.Pointer && Placement != PlacementMode.Center)
|
if (_isNeedFlip)
|
||||||
{
|
{
|
||||||
AdjustPopupHostPosition(placementTarget);
|
if (Placement != PlacementMode.Pointer && Placement != PlacementMode.Center)
|
||||||
|
{
|
||||||
|
AdjustPopupHostPosition(placementTarget!);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_animating)
|
if (!_animating)
|
||||||
{
|
{
|
||||||
CreateShadowLayer();
|
CreateShadowLayer();
|
||||||
@ -291,8 +295,6 @@ public class Popup : AvaloniaPopup
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 在这里处理翻转问题
|
/// 在这里处理翻转问题
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="popupHost"></param>
|
|
||||||
/// <param name="placementTarget"></param>
|
|
||||||
internal void AdjustPopupHostPosition(Control placementTarget)
|
internal void AdjustPopupHostPosition(Control placementTarget)
|
||||||
{
|
{
|
||||||
var offsetX = HorizontalOffset;
|
var offsetX = HorizontalOffset;
|
||||||
@ -307,8 +309,7 @@ public class Popup : AvaloniaPopup
|
|||||||
var direction = PopupUtils.GetDirection(Placement);
|
var direction = PopupUtils.GetDirection(Placement);
|
||||||
var topLevel = TopLevel.GetTopLevel(placementTarget)!;
|
var topLevel = TopLevel.GetTopLevel(placementTarget)!;
|
||||||
|
|
||||||
if (Placement != PlacementMode.Center &&
|
if (Placement != PlacementMode.Center && Placement != PlacementMode.Pointer)
|
||||||
Placement != PlacementMode.Pointer)
|
|
||||||
{
|
{
|
||||||
// 计算是否 flip
|
// 计算是否 flip
|
||||||
var parameters = new PopupPositionerParameters();
|
var parameters = new PopupPositionerParameters();
|
||||||
@ -422,16 +423,22 @@ public class Popup : AvaloniaPopup
|
|||||||
|
|
||||||
_animating = true;
|
_animating = true;
|
||||||
|
|
||||||
|
var placementTarget = GetEffectivePlacementTarget();
|
||||||
|
|
||||||
Open();
|
Open();
|
||||||
|
if (Placement != PlacementMode.Pointer && Placement != PlacementMode.Center)
|
||||||
|
{
|
||||||
|
AdjustPopupHostPosition(placementTarget!);
|
||||||
|
_isNeedFlip = false;
|
||||||
|
}
|
||||||
var popupRoot = (Host as PopupRoot)!;
|
var popupRoot = (Host as PopupRoot)!;
|
||||||
// 获取 popup 的具体位置,这个就是非常准确的位置,还有大小
|
// 获取 popup 的具体位置,这个就是非常准确的位置,还有大小
|
||||||
// TODO 暂时只支持 WindowBase popup
|
// TODO 暂时只支持 WindowBase popup
|
||||||
popupRoot.Hide();
|
popupRoot.Hide();
|
||||||
var popupOffset = popupRoot.PlatformImpl!.Position;
|
var popupOffset = popupRoot.PlatformImpl!.Position;
|
||||||
var offset = new Point(popupOffset.X, popupOffset.Y);
|
var offset = new Point(popupOffset.X, popupOffset.Y);
|
||||||
var placementTarget = GetEffectivePlacementTarget();
|
var topLevel = TopLevel.GetTopLevel(placementTarget);
|
||||||
var topLevel = TopLevel.GetTopLevel(placementTarget);
|
var scaling = topLevel?.RenderScaling ?? 1.0;
|
||||||
var scaling = topLevel?.RenderScaling ?? 1.0;
|
|
||||||
|
|
||||||
// 调度动画
|
// 调度动画
|
||||||
var director = Director.Instance;
|
var director = Director.Instance;
|
||||||
|
Loading…
Reference in New Issue
Block a user