A cross-platform UI framework for .NET
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.
 
 
 

240 lines
8.2 KiB

using System;
using System.ComponentModel;
using System.Text;
using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.VisualTree;
namespace Avalonia.Diagnostics.ViewModels
{
internal class ControlLayoutViewModel : ViewModelBase
{
private readonly IVisual _control;
private Thickness _borderThickness;
private double _height;
private string? _heightConstraint;
private HorizontalAlignment _horizontalAlignment;
private Thickness _marginThickness;
private Thickness _paddingThickness;
private bool _updatingFromControl;
private VerticalAlignment _verticalAlignment;
private double _width;
private string? _widthConstraint;
public ControlLayoutViewModel(IVisual control)
{
_control = control;
HasPadding = AvaloniaPropertyRegistry.Instance.IsRegistered(control, Decorator.PaddingProperty);
HasBorder = AvaloniaPropertyRegistry.Instance.IsRegistered(control, Border.BorderThicknessProperty);
if (control is AvaloniaObject ao)
{
MarginThickness = ao.GetValue(Layoutable.MarginProperty);
if (HasPadding)
{
PaddingThickness = ao.GetValue(Decorator.PaddingProperty);
}
if (HasBorder)
{
BorderThickness = ao.GetValue(Border.BorderThicknessProperty);
}
HorizontalAlignment = ao.GetValue(Layoutable.HorizontalAlignmentProperty);
VerticalAlignment = ao.GetValue(Layoutable.VerticalAlignmentProperty);
}
UpdateSize();
UpdateSizeConstraints();
}
public Thickness MarginThickness
{
get => _marginThickness;
set => RaiseAndSetIfChanged(ref _marginThickness, value);
}
public Thickness BorderThickness
{
get => _borderThickness;
set => RaiseAndSetIfChanged(ref _borderThickness, value);
}
public Thickness PaddingThickness
{
get => _paddingThickness;
set => RaiseAndSetIfChanged(ref _paddingThickness, value);
}
public double Width
{
get => _width;
private set => RaiseAndSetIfChanged(ref _width, value);
}
public double Height
{
get => _height;
private set => RaiseAndSetIfChanged(ref _height, value);
}
public string? WidthConstraint
{
get => _widthConstraint;
private set => RaiseAndSetIfChanged(ref _widthConstraint, value);
}
public string? HeightConstraint
{
get => _heightConstraint;
private set => RaiseAndSetIfChanged(ref _heightConstraint, value);
}
public HorizontalAlignment HorizontalAlignment
{
get => _horizontalAlignment;
private set => RaiseAndSetIfChanged(ref _horizontalAlignment, value);
}
public VerticalAlignment VerticalAlignment
{
get => _verticalAlignment;
private set => RaiseAndSetIfChanged(ref _verticalAlignment, value);
}
public bool HasPadding { get; }
public bool HasBorder { get; }
private void UpdateSizeConstraints()
{
if (_control is IAvaloniaObject ao)
{
string? CreateConstraintInfo(StyledProperty<double> minProperty, StyledProperty<double> maxProperty)
{
bool hasMin = ao.IsSet(minProperty);
bool hasMax = ao.IsSet(maxProperty);
if (hasMin || hasMax)
{
var builder = new StringBuilder();
if (hasMin)
{
var minValue = ao.GetValue(minProperty);
builder.AppendFormat("Min: {0}", Math.Round(minValue, 2));
builder.AppendLine();
}
if (hasMax)
{
var maxValue = ao.GetValue(maxProperty);
builder.AppendFormat("Max: {0}", Math.Round(maxValue, 2));
}
return builder.ToString();
}
return null;
}
WidthConstraint = CreateConstraintInfo(Layoutable.MinWidthProperty, Layoutable.MaxWidthProperty);
HeightConstraint = CreateConstraintInfo(Layoutable.MinHeightProperty, Layoutable.MaxHeightProperty);
}
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (_updatingFromControl)
{
return;
}
if (_control is AvaloniaObject ao)
{
if (e.PropertyName == nameof(MarginThickness))
{
ao.SetValue(Layoutable.MarginProperty, MarginThickness);
}
else if (HasPadding && e.PropertyName == nameof(PaddingThickness))
{
ao.SetValue(Decorator.PaddingProperty, PaddingThickness);
}
else if (HasBorder && e.PropertyName == nameof(BorderThickness))
{
ao.SetValue(Border.BorderThicknessProperty, BorderThickness);
}
else if (e.PropertyName == nameof(HorizontalAlignment))
{
ao.SetValue(Layoutable.HorizontalAlignmentProperty, HorizontalAlignment);
}
else if (e.PropertyName == nameof(VerticalAlignment))
{
ao.SetValue(Layoutable.VerticalAlignmentProperty, VerticalAlignment);
}
}
}
public void ControlPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{
try
{
_updatingFromControl = true;
if (e.Property == Visual.BoundsProperty)
{
UpdateSize();
}
else
{
if (_control is IAvaloniaObject ao)
{
if (e.Property == Layoutable.MarginProperty)
{
MarginThickness = ao.GetValue(Layoutable.MarginProperty);
}
else if (e.Property == Decorator.PaddingProperty)
{
PaddingThickness = ao.GetValue(Decorator.PaddingProperty);
}
else if (e.Property == Border.BorderThicknessProperty)
{
BorderThickness = ao.GetValue(Border.BorderThicknessProperty);
}
else if (e.Property == Layoutable.MinWidthProperty ||
e.Property == Layoutable.MaxWidthProperty ||
e.Property == Layoutable.MinHeightProperty ||
e.Property == Layoutable.MaxHeightProperty)
{
UpdateSizeConstraints();
}
else if (e.Property == Layoutable.HorizontalAlignmentProperty)
{
HorizontalAlignment = ao.GetValue(Layoutable.HorizontalAlignmentProperty);
}
else if (e.Property == Layoutable.VerticalAlignmentProperty)
{
VerticalAlignment = ao.GetValue(Layoutable.VerticalAlignmentProperty);
}
}
}
}
finally
{
_updatingFromControl = false;
}
}
private void UpdateSize()
{
var size = _control.Bounds;
Width = Math.Round(size.Width, 2);
Height = Math.Round(size.Height, 2);
}
}
}