You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.5 KiB
114 lines
3.5 KiB
1 year ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Diagnostics.CodeAnalysis;
|
||
|
using Avalonia;
|
||
|
using Avalonia.Media;
|
||
|
using FluentAvalonia.UI.Controls;
|
||
|
|
||
|
namespace StabilityMatrix.Avalonia.Controls;
|
||
|
|
||
|
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
|
||
|
public class LineDashFrame : Frame
|
||
|
{
|
||
|
protected override Type StyleKeyOverride { get; } = typeof(Frame);
|
||
|
|
||
|
public static readonly StyledProperty<ISolidColorBrush> StrokeProperty =
|
||
|
AvaloniaProperty.Register<LineDashFrame, ISolidColorBrush>("Stroke");
|
||
|
|
||
|
public ISolidColorBrush Stroke
|
||
|
{
|
||
|
get => GetValue(StrokeProperty);
|
||
|
set => SetValue(StrokeProperty, value);
|
||
|
}
|
||
|
|
||
|
public static readonly StyledProperty<double> StrokeThicknessProperty =
|
||
|
AvaloniaProperty.Register<LineDashFrame, double>("StrokeThickness");
|
||
|
|
||
|
public double StrokeThickness
|
||
|
{
|
||
|
get => GetValue(StrokeThicknessProperty);
|
||
|
set => SetValue(StrokeThicknessProperty, value);
|
||
|
}
|
||
|
|
||
|
public static readonly StyledProperty<double> StrokeDashLineProperty =
|
||
|
AvaloniaProperty.Register<LineDashFrame, double>("StrokeDashLine");
|
||
|
|
||
|
public double StrokeDashLine
|
||
|
{
|
||
|
get => GetValue(StrokeDashLineProperty);
|
||
|
set => SetValue(StrokeDashLineProperty, value);
|
||
|
}
|
||
|
|
||
|
public static readonly StyledProperty<double> StrokeDashSpaceProperty =
|
||
|
AvaloniaProperty.Register<LineDashFrame, double>("StrokeDashSpace");
|
||
|
|
||
|
public double StrokeDashSpace
|
||
|
{
|
||
|
get => GetValue(StrokeDashSpaceProperty);
|
||
|
set => SetValue(StrokeDashSpaceProperty, value);
|
||
|
}
|
||
|
|
||
|
public static readonly StyledProperty<ISolidColorBrush> FillProperty =
|
||
|
AvaloniaProperty.Register<LineDashFrame, ISolidColorBrush>("Fill");
|
||
|
|
||
|
public ISolidColorBrush Fill
|
||
|
{
|
||
|
get => GetValue(FillProperty);
|
||
|
set => SetValue(FillProperty, value);
|
||
|
}
|
||
|
|
||
|
public LineDashFrame()
|
||
|
{
|
||
|
UseLayoutRounding = true;
|
||
|
}
|
||
|
|
||
|
/// <inheritdoc />
|
||
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||
|
{
|
||
|
base.OnPropertyChanged(change);
|
||
|
|
||
|
if (
|
||
|
change.Property == StrokeProperty
|
||
|
|| change.Property == StrokeThicknessProperty
|
||
|
|| change.Property == StrokeDashLineProperty
|
||
|
|| change.Property == StrokeDashSpaceProperty
|
||
|
|| change.Property == FillProperty
|
||
|
)
|
||
|
{
|
||
|
InvalidateVisual();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <inheritdoc />
|
||
|
public override void Render(DrawingContext context)
|
||
|
{
|
||
|
base.Render(context);
|
||
|
|
||
|
var width = Bounds.Width;
|
||
|
var height = Bounds.Height;
|
||
|
|
||
|
context.DrawRectangle(Fill, null, new Rect(0, 0, width, height));
|
||
|
|
||
|
var dashPen = new Pen(Stroke, StrokeThickness)
|
||
|
{
|
||
|
DashStyle = new DashStyle(GetDashArray(width), 0)
|
||
|
};
|
||
|
|
||
|
context.DrawLine(dashPen, new Point(0, 0), new Point(width, 0));
|
||
|
context.DrawLine(dashPen, new Point(0, height), new Point(width, height));
|
||
|
context.DrawLine(dashPen, new Point(0, 0), new Point(0, height));
|
||
|
context.DrawLine(dashPen, new Point(width, 0), new Point(width, height));
|
||
|
}
|
||
|
|
||
|
private IEnumerable<double> GetDashArray(double length)
|
||
|
{
|
||
|
var availableLength = length - StrokeDashLine;
|
||
|
var lines = (int)Math.Round(availableLength / (StrokeDashLine + StrokeDashSpace));
|
||
|
availableLength -= lines * StrokeDashLine;
|
||
|
var actualSpacing = availableLength / lines;
|
||
|
|
||
|
yield return StrokeDashLine / StrokeThickness;
|
||
|
yield return actualSpacing / StrokeThickness;
|
||
|
}
|
||
|
}
|