|
@@ -4,6 +4,7 @@
|
|
|
using System;
|
|
using System;
|
|
|
using Avalonia.Controls.Primitives;
|
|
using Avalonia.Controls.Primitives;
|
|
|
using Avalonia.Controls.Templates;
|
|
using Avalonia.Controls.Templates;
|
|
|
|
|
+using Avalonia.Controls.Utils;
|
|
|
using Avalonia.Layout;
|
|
using Avalonia.Layout;
|
|
|
using Avalonia.LogicalTree;
|
|
using Avalonia.LogicalTree;
|
|
|
using Avalonia.Media;
|
|
using Avalonia.Media;
|
|
@@ -31,7 +32,7 @@ namespace Avalonia.Controls.Presenters
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Defines the <see cref="BorderThickness"/> property.
|
|
/// Defines the <see cref="BorderThickness"/> property.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
- public static readonly StyledProperty<double> BorderThicknessProperty =
|
|
|
|
|
|
|
+ public static readonly StyledProperty<Thickness> BorderThicknessProperty =
|
|
|
Border.BorderThicknessProperty.AddOwner<ContentPresenter>();
|
|
Border.BorderThicknessProperty.AddOwner<ContentPresenter>();
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
@@ -57,7 +58,7 @@ namespace Avalonia.Controls.Presenters
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Defines the <see cref="CornerRadius"/> property.
|
|
/// Defines the <see cref="CornerRadius"/> property.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
- public static readonly StyledProperty<float> CornerRadiusProperty =
|
|
|
|
|
|
|
+ public static readonly StyledProperty<CornerRadius> CornerRadiusProperty =
|
|
|
Border.CornerRadiusProperty.AddOwner<ContentPresenter>();
|
|
Border.CornerRadiusProperty.AddOwner<ContentPresenter>();
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
@@ -76,11 +77,12 @@ namespace Avalonia.Controls.Presenters
|
|
|
/// Defines the <see cref="Padding"/> property.
|
|
/// Defines the <see cref="Padding"/> property.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
public static readonly StyledProperty<Thickness> PaddingProperty =
|
|
public static readonly StyledProperty<Thickness> PaddingProperty =
|
|
|
- Border.PaddingProperty.AddOwner<ContentPresenter>();
|
|
|
|
|
|
|
+ Decorator.PaddingProperty.AddOwner<ContentPresenter>();
|
|
|
|
|
|
|
|
private IControl _child;
|
|
private IControl _child;
|
|
|
private bool _createdChild;
|
|
private bool _createdChild;
|
|
|
private IDataTemplate _dataTemplate;
|
|
private IDataTemplate _dataTemplate;
|
|
|
|
|
+ private readonly BorderRenderHelper _borderRenderer = new BorderRenderHelper();
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Initializes static members of the <see cref="ContentPresenter"/> class.
|
|
/// Initializes static members of the <see cref="ContentPresenter"/> class.
|
|
@@ -120,7 +122,7 @@ namespace Avalonia.Controls.Presenters
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Gets or sets the thickness of the border.
|
|
/// Gets or sets the thickness of the border.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
- public double BorderThickness
|
|
|
|
|
|
|
+ public Thickness BorderThickness
|
|
|
{
|
|
{
|
|
|
get { return GetValue(BorderThicknessProperty); }
|
|
get { return GetValue(BorderThicknessProperty); }
|
|
|
set { SetValue(BorderThicknessProperty, value); }
|
|
set { SetValue(BorderThicknessProperty, value); }
|
|
@@ -157,7 +159,7 @@ namespace Avalonia.Controls.Presenters
|
|
|
/// <summary>
|
|
/// <summary>
|
|
|
/// Gets or sets the radius of the border rounded corners.
|
|
/// Gets or sets the radius of the border rounded corners.
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
- public float CornerRadius
|
|
|
|
|
|
|
+ public CornerRadius CornerRadius
|
|
|
{
|
|
{
|
|
|
get { return GetValue(CornerRadiusProperty); }
|
|
get { return GetValue(CornerRadiusProperty); }
|
|
|
set { SetValue(CornerRadiusProperty, value); }
|
|
set { SetValue(CornerRadiusProperty, value); }
|
|
@@ -277,21 +279,7 @@ namespace Avalonia.Controls.Presenters
|
|
|
/// <inheritdoc/>
|
|
/// <inheritdoc/>
|
|
|
public override void Render(DrawingContext context)
|
|
public override void Render(DrawingContext context)
|
|
|
{
|
|
{
|
|
|
- var background = Background;
|
|
|
|
|
- var borderBrush = BorderBrush;
|
|
|
|
|
- var borderThickness = BorderThickness;
|
|
|
|
|
- var cornerRadius = CornerRadius;
|
|
|
|
|
- var rect = new Rect(Bounds.Size).Deflate(BorderThickness);
|
|
|
|
|
-
|
|
|
|
|
- if (background != null)
|
|
|
|
|
- {
|
|
|
|
|
- context.FillRectangle(background, rect, cornerRadius);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (borderBrush != null && borderThickness > 0)
|
|
|
|
|
- {
|
|
|
|
|
- context.DrawRectangle(new Pen(borderBrush, borderThickness), rect, cornerRadius);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ _borderRenderer.Render(context, Bounds.Size, BorderThickness, CornerRadius, Background, BorderBrush);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
@@ -344,7 +332,11 @@ namespace Avalonia.Controls.Presenters
|
|
|
/// <inheritdoc/>
|
|
/// <inheritdoc/>
|
|
|
protected override Size ArrangeOverride(Size finalSize)
|
|
protected override Size ArrangeOverride(Size finalSize)
|
|
|
{
|
|
{
|
|
|
- return ArrangeOverrideImpl(finalSize, new Vector());
|
|
|
|
|
|
|
+ finalSize = ArrangeOverrideImpl(finalSize, new Vector());
|
|
|
|
|
+
|
|
|
|
|
+ _borderRenderer.Update(finalSize, BorderThickness, CornerRadius);
|
|
|
|
|
+
|
|
|
|
|
+ return finalSize;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
@@ -372,70 +364,69 @@ namespace Avalonia.Controls.Presenters
|
|
|
|
|
|
|
|
internal Size ArrangeOverrideImpl(Size finalSize, Vector offset)
|
|
internal Size ArrangeOverrideImpl(Size finalSize, Vector offset)
|
|
|
{
|
|
{
|
|
|
- if (Child != null)
|
|
|
|
|
- {
|
|
|
|
|
- var padding = Padding;
|
|
|
|
|
- var borderThickness = BorderThickness;
|
|
|
|
|
- var horizontalContentAlignment = HorizontalContentAlignment;
|
|
|
|
|
- var verticalContentAlignment = VerticalContentAlignment;
|
|
|
|
|
- var useLayoutRounding = UseLayoutRounding;
|
|
|
|
|
- var availableSizeMinusMargins = new Size(
|
|
|
|
|
- Math.Max(0, finalSize.Width - padding.Left - padding.Right - borderThickness),
|
|
|
|
|
- Math.Max(0, finalSize.Height - padding.Top - padding.Bottom - borderThickness));
|
|
|
|
|
- var size = availableSizeMinusMargins;
|
|
|
|
|
- var scale = GetLayoutScale();
|
|
|
|
|
- var originX = offset.X + padding.Left + borderThickness;
|
|
|
|
|
- var originY = offset.Y + padding.Top + borderThickness;
|
|
|
|
|
-
|
|
|
|
|
- if (horizontalContentAlignment != HorizontalAlignment.Stretch)
|
|
|
|
|
- {
|
|
|
|
|
- size = size.WithWidth(Math.Min(size.Width, DesiredSize.Width - padding.Left - padding.Right));
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (Child == null) return finalSize;
|
|
|
|
|
|
|
|
- if (verticalContentAlignment != VerticalAlignment.Stretch)
|
|
|
|
|
- {
|
|
|
|
|
- size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - padding.Top - padding.Bottom));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if (useLayoutRounding)
|
|
|
|
|
- {
|
|
|
|
|
- size = new Size(
|
|
|
|
|
- Math.Ceiling(size.Width * scale) / scale,
|
|
|
|
|
- Math.Ceiling(size.Height * scale) / scale);
|
|
|
|
|
- availableSizeMinusMargins = new Size(
|
|
|
|
|
- Math.Ceiling(availableSizeMinusMargins.Width * scale) / scale,
|
|
|
|
|
- Math.Ceiling(availableSizeMinusMargins.Height * scale) / scale);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ var padding = Padding;
|
|
|
|
|
+ var borderThickness = BorderThickness;
|
|
|
|
|
+ var horizontalContentAlignment = HorizontalContentAlignment;
|
|
|
|
|
+ var verticalContentAlignment = VerticalContentAlignment;
|
|
|
|
|
+ var useLayoutRounding = UseLayoutRounding;
|
|
|
|
|
+ var availableSizeMinusMargins = new Size(
|
|
|
|
|
+ Math.Max(0, finalSize.Width - padding.Left - padding.Right - borderThickness.Left - borderThickness.Right),
|
|
|
|
|
+ Math.Max(0, finalSize.Height - padding.Top - padding.Bottom - borderThickness.Top - borderThickness.Bottom));
|
|
|
|
|
+ var size = availableSizeMinusMargins;
|
|
|
|
|
+ var scale = GetLayoutScale();
|
|
|
|
|
+ var originX = offset.X + padding.Left + borderThickness.Left;
|
|
|
|
|
+ var originY = offset.Y + padding.Top + borderThickness.Top;
|
|
|
|
|
+
|
|
|
|
|
+ if (horizontalContentAlignment != HorizontalAlignment.Stretch)
|
|
|
|
|
+ {
|
|
|
|
|
+ size = size.WithWidth(Math.Min(size.Width, DesiredSize.Width - padding.Left - padding.Right));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (verticalContentAlignment != VerticalAlignment.Stretch)
|
|
|
|
|
+ {
|
|
|
|
|
+ size = size.WithHeight(Math.Min(size.Height, DesiredSize.Height - padding.Top - padding.Bottom));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- switch (horizontalContentAlignment)
|
|
|
|
|
- {
|
|
|
|
|
- case HorizontalAlignment.Center:
|
|
|
|
|
- originX += (availableSizeMinusMargins.Width - size.Width) / 2;
|
|
|
|
|
- break;
|
|
|
|
|
- case HorizontalAlignment.Right:
|
|
|
|
|
- originX += availableSizeMinusMargins.Width - size.Width;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (useLayoutRounding)
|
|
|
|
|
+ {
|
|
|
|
|
+ size = new Size(
|
|
|
|
|
+ Math.Ceiling(size.Width * scale) / scale,
|
|
|
|
|
+ Math.Ceiling(size.Height * scale) / scale);
|
|
|
|
|
+ availableSizeMinusMargins = new Size(
|
|
|
|
|
+ Math.Ceiling(availableSizeMinusMargins.Width * scale) / scale,
|
|
|
|
|
+ Math.Ceiling(availableSizeMinusMargins.Height * scale) / scale);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- switch (verticalContentAlignment)
|
|
|
|
|
- {
|
|
|
|
|
- case VerticalAlignment.Center:
|
|
|
|
|
- originY += (availableSizeMinusMargins.Height - size.Height) / 2;
|
|
|
|
|
- break;
|
|
|
|
|
- case VerticalAlignment.Bottom:
|
|
|
|
|
- originY += availableSizeMinusMargins.Height - size.Height;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ switch (horizontalContentAlignment)
|
|
|
|
|
+ {
|
|
|
|
|
+ case HorizontalAlignment.Center:
|
|
|
|
|
+ originX += (availableSizeMinusMargins.Width - size.Width) / 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case HorizontalAlignment.Right:
|
|
|
|
|
+ originX += availableSizeMinusMargins.Width - size.Width;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (useLayoutRounding)
|
|
|
|
|
- {
|
|
|
|
|
- originX = Math.Floor(originX * scale) / scale;
|
|
|
|
|
- originY = Math.Floor(originY * scale) / scale;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ switch (verticalContentAlignment)
|
|
|
|
|
+ {
|
|
|
|
|
+ case VerticalAlignment.Center:
|
|
|
|
|
+ originY += (availableSizeMinusMargins.Height - size.Height) / 2;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case VerticalAlignment.Bottom:
|
|
|
|
|
+ originY += availableSizeMinusMargins.Height - size.Height;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- Child.Arrange(new Rect(originX, originY, size.Width, size.Height));
|
|
|
|
|
|
|
+ if (useLayoutRounding)
|
|
|
|
|
+ {
|
|
|
|
|
+ originX = Math.Floor(originX * scale) / scale;
|
|
|
|
|
+ originY = Math.Floor(originY * scale) / scale;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ Child.Arrange(new Rect(originX, originY, size.Width, size.Height));
|
|
|
|
|
+
|
|
|
return finalSize;
|
|
return finalSize;
|
|
|
}
|
|
}
|
|
|
|
|
|