|
|
|
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)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|