Browse Source

Merge pull request #5950 from MarchingCube/devtools-layout-alignment

Allow for easily changing layout alignment
release/0.10.5
Dan Walmsley 5 years ago
parent
commit
bd77de553b
  1. 87
      src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.axaml
  2. 14
      src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs
  3. 25
      src/Avalonia.Diagnostics/Diagnostics/Converters/EnumToCheckedConverter.cs
  4. 4
      src/Avalonia.Diagnostics/Diagnostics/DevToolsOptions.cs
  5. 101
      src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs
  6. 353
      src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml
  7. 109
      src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml.cs
  8. 210
      src/Avalonia.Diagnostics/Diagnostics/Views/LayoutExplorerView.axaml
  9. 128
      src/Avalonia.Diagnostics/Diagnostics/Views/LayoutExplorerView.axaml.cs
  10. 1
      src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml
  11. 2
      src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml

87
src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.axaml

@ -0,0 +1,87 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Avalonia.Diagnostics.Controls">
<Styles.Resources>
<SolidColorBrush x:Key="HighlightBorderBrush" Color="CornflowerBlue" />
<SolidColorBrush x:Key="ThicknessBorderBrush" Color="#666666" />
</Styles.Resources>
<Style Selector="controls|ThicknessEditor">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{StaticResource ThicknessBorderBrush}" />
<Setter Property="Template">
<ControlTemplate>
<Panel>
<Rectangle x:Name="PART_Background"
Classes.no-content-pointerover="{Binding !#PART_ContentPresenter.IsPointerOver}" />
<Border
x:Name="PART_Border"
Classes.no-content-pointerover="{Binding !#PART_ContentPresenter.IsPointerOver}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid RowDefinitions="Auto,*,Auto" ColumnDefinitions="Auto,*,Auto">
<Grid.Styles>
<Style Selector="TextBox.thickness-edit">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="2" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="(ScrollViewer.HorizontalScrollBarVisibility)"
Value="Disabled" />
<Setter Property="(ScrollViewer.VerticalScrollBarVisibility)" Value="Disabled" />
<Setter Property="IsVisible"
Value="{Binding $parent[controls:ThicknessEditor].IsPresent}" />
</Style>
</Grid.Styles>
<TextBlock IsVisible="{TemplateBinding IsPresent}" Margin="4,0,0,0"
Text="{TemplateBinding Header}" Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="2" />
<TextBox Grid.Row="1" Grid.Column="0"
Text="{Binding Left, RelativeSource={RelativeSource TemplatedParent}}"
Classes="thickness-edit" />
<TextBox x:Name="Right" Grid.Row="0" Grid.Column="1"
Text="{Binding Top, RelativeSource={RelativeSource TemplatedParent}}"
Classes="thickness-edit" />
<TextBox Grid.Row="1" Grid.Column="2"
Text="{Binding Right, RelativeSource={RelativeSource TemplatedParent}}"
Classes="thickness-edit" />
<TextBox Grid.Row="2" Grid.Column="1"
Text="{Binding Bottom, RelativeSource={RelativeSource TemplatedParent}}"
Classes="thickness-edit" />
<ContentPresenter Grid.Row="1" Grid.Column="1"
Name="PART_ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Grid>
</Border>
</Panel>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="controls|ThicknessEditor[IsPresent=False]">
<Setter Property="BorderThickness" Value="0" />
</Style>
<Style Selector="controls|ThicknessEditor /template/ Rectangle#PART_Background">
<Setter Property="Fill" Value="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}" />
</Style>
<Style Selector="controls|ThicknessEditor:pointerover /template/ Rectangle#PART_Background.no-content-pointerover">
<Setter Property="Fill" Value="{Binding Highlight, RelativeSource={RelativeSource TemplatedParent}}" />
</Style>
<Style Selector="controls|ThicknessEditor:pointerover /template/ Border#PART_Border.no-content-pointerover">
<Setter Property="BorderBrush" Value="{StaticResource HighlightBorderBrush}" />
</Style>
</Styles>

14
src/Avalonia.Diagnostics/Diagnostics/Views/ThicknessEditor.cs → src/Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.cs

@ -2,7 +2,7 @@ using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Media;
namespace Avalonia.Diagnostics.Views
namespace Avalonia.Diagnostics.Controls
{
internal class ThicknessEditor : ContentControl
{
@ -35,12 +35,6 @@ namespace Avalonia.Diagnostics.Views
public static readonly StyledProperty<IBrush> HighlightProperty =
AvaloniaProperty.Register<ThicknessEditor, IBrush>(nameof(Highlight));
public IBrush Highlight
{
get => GetValue(HighlightProperty);
set => SetValue(HighlightProperty, value);
}
private Thickness _thickness;
private string _header;
private bool _isPresent = true;
@ -92,6 +86,12 @@ namespace Avalonia.Diagnostics.Views
set => SetAndRaise(BottomProperty, ref _bottom, value);
}
public IBrush Highlight
{
get => GetValue(HighlightProperty);
set => SetValue(HighlightProperty, value);
}
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);

25
src/Avalonia.Diagnostics/Diagnostics/Converters/EnumToCheckedConverter.cs

@ -0,0 +1,25 @@
using System;
using System.Globalization;
using Avalonia.Data;
using Avalonia.Data.Converters;
namespace Avalonia.Diagnostics.Converters
{
internal class EnumToCheckedConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return Equals(value, parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool isChecked && isChecked)
{
return parameter;
}
return BindingOperations.DoNothing;
}
}
}

4
src/Avalonia.Diagnostics/Diagnostics/DevToolsOptions.cs

@ -19,8 +19,8 @@ namespace Avalonia.Diagnostics
public bool ShowAsChildWindow { get; set; } = true;
/// <summary>
/// Gets or sets the initial size of the DevTools window. The default value is 1024x512.
/// Gets or sets the initial size of the DevTools window. The default value is 1280x720.
/// </summary>
public Size Size { get; set; } = new Size(1024, 512);
public Size Size { get; set; } = new Size(1280, 720);
}
}

101
src/Avalonia.Diagnostics/Diagnostics/ViewModels/ControlLayoutViewModel.cs

@ -10,27 +10,58 @@ namespace Avalonia.Diagnostics.ViewModels
internal class ControlLayoutViewModel : ViewModelBase
{
private readonly IVisual _control;
private Thickness _marginThickness;
private Thickness _borderThickness;
private Thickness _paddingThickness;
private double _width;
private double _height;
private string _widthConstraint;
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;
@ -61,35 +92,21 @@ namespace Avalonia.Diagnostics.ViewModels
private set => RaiseAndSetIfChanged(ref _heightConstraint, value);
}
public bool HasPadding { get; }
public bool HasBorder { get; }
public ControlLayoutViewModel(IVisual control)
public HorizontalAlignment HorizontalAlignment
{
_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);
get => _horizontalAlignment;
private set => RaiseAndSetIfChanged(ref _horizontalAlignment, value);
}
if (HasPadding)
{
PaddingThickness = ao.GetValue(Decorator.PaddingProperty);
}
public VerticalAlignment VerticalAlignment
{
get => _verticalAlignment;
private set => RaiseAndSetIfChanged(ref _verticalAlignment, value);
}
if (HasBorder)
{
BorderThickness = ao.GetValue(Border.BorderThicknessProperty);
}
}
public bool HasPadding { get; }
UpdateSize();
UpdateSizeConstraints();
}
public bool HasBorder { get; }
private void UpdateSizeConstraints()
{
@ -151,6 +168,14 @@ namespace Avalonia.Diagnostics.ViewModels
{
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);
}
}
}
@ -171,15 +196,15 @@ namespace Avalonia.Diagnostics.ViewModels
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 ||
@ -187,6 +212,14 @@ namespace Avalonia.Diagnostics.ViewModels
{
UpdateSizeConstraints();
}
else if (e.Property == Layoutable.HorizontalAlignmentProperty)
{
HorizontalAlignment = ao.GetValue(Layoutable.HorizontalAlignmentProperty);
}
else if (e.Property == Layoutable.VerticalAlignmentProperty)
{
VerticalAlignment = ao.GetValue(Layoutable.VerticalAlignmentProperty);
}
}
}
}

353
src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml

@ -7,88 +7,10 @@
x:Name="Main">
<UserControl.Resources>
<SolidColorBrush x:Key="ThicknessBorderBrush" Color="#666666" />
<SolidColorBrush x:Key="HighlightBorderBrush" Color="CornflowerBlue" />
<SolidColorBrush x:Key="SizeGuidelineBrush" Color="#333333" />
<SolidColorBrush x:Key="MarginBackgroundBrush" Color="#D78965" />
<SolidColorBrush x:Key="MarginHighlightBrush" Color="#EA966F" />
<SolidColorBrush x:Key="BorderBackgroundBrush" Color="#E3C381" />
<SolidColorBrush x:Key="BorderHighlightBrush" Color="#EFCD88" />
<SolidColorBrush x:Key="PaddingBackgroundBrush" Color="#B8C47F" />
<SolidColorBrush x:Key="PaddingHighlightBrush" Color="#CEDA8E" />
<SolidColorBrush x:Key="SizeBackgroundBrush" Color="#88B2BD" />
<SolidColorBrush x:Key="SizeHighlightBrush" Color="#9ED0DC" />
<conv:BoolToOpacityConverter x:Key="BoolToOpacity" Opacity="0.6"/>
</UserControl.Resources>
<UserControl.Styles>
<Style Selector="local|ThicknessEditor">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="{StaticResource ThicknessBorderBrush}" />
<Setter Property="Template">
<ControlTemplate>
<Panel>
<Rectangle x:Name="PART_Background" Classes.no-content-pointerover="{Binding !#PART_ContentPresenter.IsPointerOver}" />
<Border
x:Name="PART_Border"
Classes.no-content-pointerover="{Binding !#PART_ContentPresenter.IsPointerOver}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid RowDefinitions="Auto,*,Auto" ColumnDefinitions="Auto,*,Auto">
<Grid.Styles>
<Style Selector="TextBox.thickness-edit">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="2" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="(ScrollViewer.HorizontalScrollBarVisibility)" Value="Disabled" />
<Setter Property="(ScrollViewer.VerticalScrollBarVisibility)" Value="Disabled" />
<Setter Property="IsVisible" Value="{Binding $parent[local:ThicknessEditor].IsPresent}" />
</Style>
</Grid.Styles>
<TextBlock IsVisible="{TemplateBinding IsPresent}" Margin="4,0,0,0" Text="{TemplateBinding Header}" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" />
<TextBox Grid.Row="1" Grid.Column="0" Text="{Binding Left, RelativeSource={RelativeSource TemplatedParent}}" Classes="thickness-edit" />
<TextBox x:Name="Right" Grid.Row="0" Grid.Column="1" Text="{Binding Top, RelativeSource={RelativeSource TemplatedParent}}" Classes="thickness-edit" />
<TextBox Grid.Row="1" Grid.Column="2" Text="{Binding Right, RelativeSource={RelativeSource TemplatedParent}}" Classes="thickness-edit" />
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Bottom, RelativeSource={RelativeSource TemplatedParent}}" Classes="thickness-edit" />
<ContentPresenter Grid.Row="1" Grid.Column="1"
Name="PART_ContentPresenter"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Grid>
</Border>
</Panel>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="local|ThicknessEditor /template/ Rectangle#PART_Background">
<Setter Property="Fill" Value="{Binding Background, RelativeSource={RelativeSource TemplatedParent}}" />
</Style>
<Style Selector="local|ThicknessEditor:pointerover /template/ Rectangle#PART_Background.no-content-pointerover">
<Setter Property="Fill" Value="{Binding Highlight, RelativeSource={RelativeSource TemplatedParent}}" />
</Style>
<Style Selector="local|ThicknessEditor:pointerover /template/ Border#PART_Border.no-content-pointerover">
<Setter Property="BorderBrush" Value="{StaticResource HighlightBorderBrush}" />
</Style>
<Style Selector="local|ThicknessEditor[IsPresent=False]">
<Setter Property="BorderThickness" Value="0" />
</Style>
</UserControl.Styles>
<Grid ColumnDefinitions="*,Auto,280">
<Grid ColumnDefinitions="*,Auto,320">
<Grid Grid.Column="0" ColumnDefinitions="*,Auto,Auto,Auto" RowDefinitions="Auto,*">
@ -130,184 +52,133 @@
<GridSplitter Grid.Column="1" />
<Grid Grid.Column="2" RowDefinitions="Auto,*, Auto,*,Auto" >
<TextBlock Grid.Row="0" Text="Layout Visualizer" Margin="4" />
<Grid Grid.Column="2" RowDefinitions="*,Auto,*" >
<Viewbox Grid.Row="1" StretchDirection="DownOnly" >
<Grid Grid.Row="1" x:Name="LayoutRoot" Margin="8,0,8,8" RowDefinitions="Auto,Auto" ColumnDefinitions="Auto,Auto">
<Grid.Styles>
<Style Selector="TextBlock.with-constraint">
<Setter Property="TextDecorations" Value="Underline" />
</Style>
<Grid RowDefinitions="Auto,*" Grid.Row="0">
<TextBlock FontWeight="Bold" Grid.Row="0" Text="Layout Visualizer" Margin="4" />
<local:LayoutExplorerView Grid.Row="1" DataContext="{Binding Layout}" />
</Grid>
</Grid.Styles>
<GridSplitter Grid.Row="1" />
<Border x:Name="VerticalSize" Grid.Row="0" Grid.Column="1" >
<TextBlock VerticalAlignment="Center" FontWeight="Bold"
Classes.with-constraint="{Binding Layout.HeightConstraint, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
Text="{Binding Layout.Height}"
ToolTip.Tip="{Binding Layout.HeightConstraint}" />
</Border>
<Grid RowDefinitions="Auto,*,Auto" Grid.Row="2">
<Border x:Name="HorizontalSize" Grid.Row="1" Grid.Column="0" >
<TextBlock HorizontalAlignment="Center" FontWeight="Bold"
Classes.with-constraint="{Binding Layout.WidthConstraint, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
Text="{Binding Layout.Width}"
ToolTip.Tip="{Binding Layout.WidthConstraint}" />
</Border>
<Grid Grid.Row="0" Margin="4" RowDefinitions="Auto,Auto">
<local:ThicknessEditor Grid.Row="0" Grid.Column="0" Header="margin" VerticalAlignment="Top" HorizontalAlignment="Center" Background="{StaticResource MarginBackgroundBrush}" Highlight="{StaticResource MarginHighlightBrush}" Thickness="{Binding Layout.MarginThickness}">
<local:ThicknessEditor x:Name="BorderArea" Header="border" Background="{StaticResource BorderBackgroundBrush}" Highlight="{StaticResource BorderHighlightBrush}" Thickness="{Binding Layout.BorderThickness}" IsPresent="{Binding Layout.HasBorder}">
<local:ThicknessEditor x:Name="PaddingArea" Header="padding" Background="{StaticResource PaddingBackgroundBrush}" Highlight="{StaticResource PaddingHighlightBrush}" Thickness="{Binding Layout.PaddingThickness}" IsPresent="{Binding Layout.HasPadding}">
<Border x:Name="ContentArea" BorderThickness="1" MinWidth="100" MinHeight="16" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Border.Styles>
<Style Selector="Border">
<Setter Property="Background" Value="{StaticResource SizeBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource ThicknessBorderBrush}" />
</Style>
<Style Selector="Border:pointerover">
<Setter Property="Background" Value="{StaticResource SizeHighlightBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource HighlightBorderBrush}" />
</Style>
</Border.Styles>
<TextBlock Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center" Text="content" />
</Border>
</local:ThicknessEditor>
</local:ThicknessEditor>
</local:ThicknessEditor>
<Grid Grid.Row="0" Margin="2" ColumnDefinitions="Auto,*,Auto,Auto">
<TextBlock FontWeight="Bold" Grid.Column="0" Text="{Binding StyleStatus}" VerticalAlignment="Center" />
<CheckBox Margin="2,0,0,0" Grid.Column="2" Content="Show inactive" IsChecked="{Binding ShowInactiveStyles}" ToolTip.Tip="Show styles that are currently inactive" />
<ToggleButton Margin="2,0,0,0" Grid.Column="3" ToolTip.Tip="Snapshot current styles (Alt+S/Alt+D to enable/disable within debugged window)" Content="Snapshot" IsChecked="{Binding SnapshotStyles}" />
</Grid>
<Canvas Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2">
<Canvas.Styles>
<Style Selector="Rectangle">
<Setter Property="StrokeDashArray" Value="1,3" />
<Setter Property="Stroke" Value="{StaticResource SizeGuidelineBrush}" />
<Setter Property="StrokeThickness" Value="1" />
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</Canvas.Styles>
<Rectangle x:Name="HorizontalSizeBegin" />
<Rectangle x:Name="HorizontalSizeEnd" />
<Rectangle x:Name="VerticalSizeBegin" />
<Rectangle x:Name="VerticalSizeEnd" />
</Canvas>
<TextBox Grid.Row="1" Margin="2" Grid.Column="0" Watermark="Filter" Text="{Binding StyleFilter}" />
</Grid>
</Viewbox>
<Grid Grid.Row="2" Margin="4" RowDefinitions="Auto,Auto">
<Grid Grid.Row="0" Margin="2" ColumnDefinitions="Auto,*,Auto,Auto">
<TextBlock FontWeight="Bold" Grid.Column="0" Text="{Binding StyleStatus}" VerticalAlignment="Center" />
<CheckBox Margin="2,0,0,0" Grid.Column="2" Content="Show inactive" IsChecked="{Binding ShowInactiveStyles}" ToolTip.Tip="Show styles that are currently inactive" />
<ToggleButton Margin="2,0,0,0" Grid.Column="3" ToolTip.Tip="Snapshot current styles (Alt+S/Alt+D to enable/disable within debugged window)" Content="Snapshot" IsChecked="{Binding SnapshotStyles}" />
</Grid>
<TextBox Grid.Row="1" Margin="2" Grid.Column="0" Watermark="Filter" Text="{Binding StyleFilter}" />
</Grid>
<ScrollViewer Grid.Row="3" HorizontalScrollBarVisibility="Disabled">
<ItemsControl Items="{Binding AppliedStyles}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="#6C6C6C" Opacity="{Binding IsActive, Converter={StaticResource BoolToOpacity}}">
<Border.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<MultiBinding Converter="{x:Static BoolConverters.Or}" >
<Binding Path="IsActive" />
<Binding Path="#Main.DataContext.ShowInactiveStyles" />
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Disabled">
<ItemsControl Items="{Binding AppliedStyles}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="#6C6C6C" Opacity="{Binding IsActive, Converter={StaticResource BoolToOpacity}}">
<Border.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<MultiBinding Converter="{x:Static BoolConverters.Or}" >
<Binding Path="IsActive" />
<Binding Path="#Main.DataContext.ShowInactiveStyles" />
</MultiBinding>
<Binding Path="IsVisible" />
</MultiBinding>
<Binding Path="IsVisible" />
</MultiBinding>
</Border.IsVisible>
<Expander IsExpanded="True" Margin="0" Padding="8,0" ContentTransition="{x:Null}" >
<Expander.Header>
<TextBlock Grid.Row="0" Text="{Binding Name}" />
</Expander.Header>
<ItemsControl Margin="20,0,0,0" Grid.Row="1" Items="{Binding Setters}">
<ItemsControl.DataTemplates>
<DataTemplate DataType="IBrush">
<StackPanel Orientation="Horizontal" Spacing="2">
<Border BorderThickness="1" BorderBrush="Black" Background="{Binding}" Width="8" Height="8"/>
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</Border.IsVisible>
<Expander IsExpanded="True" Margin="0" Padding="8,0" ContentTransition="{x:Null}" >
<Expander.Header>
<TextBlock Grid.Row="0" Text="{Binding Name}" />
</Expander.Header>
<DataTemplate DataType="Color">
<StackPanel Orientation="Horizontal" Spacing="2">
<Border BorderThickness="1" BorderBrush="Black" Width="8" Height="8">
<Border.Background>
<SolidColorBrush Color="{Binding}" />
</Border.Background>
</Border>
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
<ItemsControl Margin="20,0,0,0" Grid.Row="1" Items="{Binding Setters}">
<ItemsControl.DataTemplates>
<DataTemplate DataType="vm:ResourceSetterViewModel">
<Panel Opacity="{Binding IsActive, Converter={StaticResource BoolToOpacity}}" IsVisible="{Binding IsVisible}" HorizontalAlignment="Left">
<Panel.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy property name" Command="{Binding CopyPropertyName} "/>
<MenuItem Header="Copy value" Command="{Binding CopyValue} "/>
<MenuItem Header="Copy resource key" Command="{Binding CopyResourceKey}" />
</ContextMenu>
</Panel.ContextMenu>
<StackPanel Orientation="Horizontal" Spacing="2" HorizontalAlignment="Left">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" />
<TextBlock Text=":" />
<ContentControl Content="{Binding Value}"/>
<TextBlock>(</TextBlock>
<Ellipse Height="8" Width="8" VerticalAlignment="Center" Fill="{Binding Tint}"/>
<TextBlock FontStyle="Italic" Text="{Binding Key}" />
<TextBlock>)</TextBlock>
<DataTemplate DataType="IBrush">
<StackPanel Orientation="Horizontal" Spacing="2">
<Border BorderThickness="1" BorderBrush="Black" Background="{Binding}" Width="8" Height="8"/>
<TextBlock Text="{Binding}" />
</StackPanel>
<Rectangle Height="1" Fill="#6C6C6C" IsVisible="{Binding !IsActive}" />
</Panel>
</DataTemplate>
</DataTemplate>
<DataTemplate DataType="vm:SetterViewModel">
<Panel Opacity="{Binding IsActive, Converter={StaticResource BoolToOpacity}}" IsVisible="{Binding IsVisible}" HorizontalAlignment="Left">
<Panel.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy property name" Command="{Binding CopyPropertyName} "/>
<MenuItem Header="Copy value" Command="{Binding CopyValue} "/>
</ContextMenu>
</Panel.ContextMenu>
<DataTemplate DataType="Color">
<StackPanel Orientation="Horizontal" Spacing="2">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" />
<TextBlock Text=":" />
<ContentControl Content="{Binding Value}"/>
<Border BorderThickness="1" BorderBrush="Black" Width="8" Height="8">
<Border.Background>
<SolidColorBrush Color="{Binding}" />
</Border.Background>
</Border>
<TextBlock Text="{Binding}" />
</StackPanel>
<Rectangle Height="1" Fill="#6C6C6C" VerticalAlignment="Center" IsVisible="{Binding !IsActive}" />
</Panel>
</DataTemplate>
</ItemsControl.DataTemplates>
</ItemsControl>
</Expander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DataTemplate>
<DataTemplate DataType="vm:ResourceSetterViewModel">
<Panel Opacity="{Binding IsActive, Converter={StaticResource BoolToOpacity}}" IsVisible="{Binding IsVisible}" HorizontalAlignment="Left">
<Panel.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy property name" Command="{Binding CopyPropertyName} "/>
<MenuItem Header="Copy value" Command="{Binding CopyValue} "/>
<MenuItem Header="Copy resource key" Command="{Binding CopyResourceKey}" />
</ContextMenu>
</Panel.ContextMenu>
<StackPanel Orientation="Horizontal" Spacing="2" HorizontalAlignment="Left">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" />
<TextBlock Text=":" />
<ContentControl Content="{Binding Value}"/>
<TextBlock>(</TextBlock>
<Ellipse Height="8" Width="8" VerticalAlignment="Center" Fill="{Binding Tint}"/>
<TextBlock FontStyle="Italic" Text="{Binding Key}" />
<TextBlock>)</TextBlock>
</StackPanel>
<Rectangle Height="1" Fill="#6C6C6C" IsVisible="{Binding !IsActive}" />
</Panel>
</DataTemplate>
<DataTemplate DataType="vm:SetterViewModel">
<Panel Opacity="{Binding IsActive, Converter={StaticResource BoolToOpacity}}" IsVisible="{Binding IsVisible}" HorizontalAlignment="Left">
<Panel.ContextMenu>
<ContextMenu>
<MenuItem Header="Copy property name" Command="{Binding CopyPropertyName} "/>
<MenuItem Header="Copy value" Command="{Binding CopyValue} "/>
</ContextMenu>
</Panel.ContextMenu>
<StackPanel Orientation="Horizontal" Spacing="2">
<TextBlock Text="{Binding Name}" FontWeight="SemiBold" />
<TextBlock Text=":" />
<ContentControl Content="{Binding Value}"/>
</StackPanel>
<Rectangle Height="1" Fill="#6C6C6C" VerticalAlignment="Center" IsVisible="{Binding !IsActive}" />
</Panel>
</DataTemplate>
</ItemsControl.DataTemplates>
</ItemsControl>
</Expander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<Expander Header="Pseudo Classes" Grid.Row="2">
<ItemsControl Items="{Binding PseudoClasses}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Margin="2" Content="{Binding Name}" IsChecked="{Binding IsActive, Mode=TwoWay}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander>
<Expander Header="Pseudo Classes" Grid.Row="4">
<ItemsControl Items="{Binding PseudoClasses}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Margin="2" Content="{Binding Name}" IsChecked="{Binding IsActive, Mode=TwoWay}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Expander>
</Grid>
</Grid>
</Grid>

109
src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml.cs

@ -1,24 +1,10 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Markup.Xaml;
using Avalonia.VisualTree;
namespace Avalonia.Diagnostics.Views
{
internal class ControlDetailsView : UserControl
{
private ThicknessEditor _borderArea;
private ThicknessEditor _paddingArea;
private Rectangle _horizontalSizeBegin;
private Rectangle _horizontalSizeEnd;
private Rectangle _verticalSizeBegin;
private Rectangle _verticalSizeEnd;
private Grid _layoutRoot;
private Border _horizontalSize;
private Border _verticalSize;
private Border _contentArea;
public ControlDetailsView()
{
InitializeComponent();
@ -27,101 +13,6 @@ namespace Avalonia.Diagnostics.Views
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
_borderArea = this.FindControl<ThicknessEditor>("BorderArea");
_paddingArea = this.FindControl<ThicknessEditor>("PaddingArea");
_horizontalSizeBegin = this.FindControl<Rectangle>("HorizontalSizeBegin");
_horizontalSizeEnd = this.FindControl<Rectangle>("HorizontalSizeEnd");
_verticalSizeBegin = this.FindControl<Rectangle>("VerticalSizeBegin");
_verticalSizeEnd = this.FindControl<Rectangle>("VerticalSizeEnd");
_horizontalSize = this.FindControl<Border>("HorizontalSize");
_verticalSize = this.FindControl<Border>("VerticalSize");
_contentArea = this.FindControl<Border>("ContentArea");
_layoutRoot = this.FindControl<Grid>("LayoutRoot");
void SubscribeToBounds(Visual visual)
{
visual.GetPropertyChangedObservable(TransformedBoundsProperty)
.Subscribe(UpdateSizeGuidelines);
}
SubscribeToBounds(_borderArea);
SubscribeToBounds(_paddingArea);
SubscribeToBounds(_contentArea);
}
private void UpdateSizeGuidelines(AvaloniaPropertyChangedEventArgs e)
{
void UpdateGuidelines(Visual area)
{
if (area.TransformedBounds is TransformedBounds bounds)
{
// Horizontal guideline
{
var sizeArea = TranslateToRoot((_horizontalSize.TransformedBounds ?? default).Bounds.BottomLeft,
_horizontalSize);
var start = TranslateToRoot(bounds.Bounds.BottomLeft, area);
SetPosition(_horizontalSizeBegin, start);
var end = TranslateToRoot(bounds.Bounds.BottomRight, area);
SetPosition(_horizontalSizeEnd, end.WithX(end.X - 1));
var height = sizeArea.Y - start.Y + 2;
_horizontalSizeBegin.Height = height;
_horizontalSizeEnd.Height = height;
}
// Vertical guideline
{
var sizeArea = TranslateToRoot((_verticalSize.TransformedBounds ?? default).Bounds.TopRight, _verticalSize);
var start = TranslateToRoot(bounds.Bounds.TopRight, area);
SetPosition(_verticalSizeBegin, start);
var end = TranslateToRoot(bounds.Bounds.BottomRight, area);
SetPosition(_verticalSizeEnd, end.WithY(end.Y - 1));
var width = sizeArea.X - start.X + 2;
_verticalSizeBegin.Width = width;
_verticalSizeEnd.Width = width;
}
}
}
Point TranslateToRoot(Point point, IVisual from)
{
return from.TranslatePoint(point, _layoutRoot) ?? default;
}
static void SetPosition(Rectangle rect, Point start)
{
Canvas.SetLeft(rect, start.X);
Canvas.SetTop(rect, start.Y);
}
if (_borderArea.IsPresent)
{
UpdateGuidelines(_borderArea);
}
else if (_paddingArea.IsPresent)
{
UpdateGuidelines(_paddingArea);
}
else
{
UpdateGuidelines(_contentArea);
}
}
}
}

210
src/Avalonia.Diagnostics/Diagnostics/Views/LayoutExplorerView.axaml

@ -0,0 +1,210 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Avalonia.Diagnostics.Views.LayoutExplorerView"
xmlns:local="clr-namespace:Avalonia.Diagnostics.Views"
xmlns:controls="clr-namespace:Avalonia.Diagnostics.Controls"
xmlns:converters="clr-namespace:Avalonia.Diagnostics.Converters">
<UserControl.Resources>
<SolidColorBrush x:Key="SizeGuidelineBrush" Color="#333333" />
<SolidColorBrush x:Key="MarginBackgroundBrush" Color="#D78965" />
<SolidColorBrush x:Key="MarginHighlightBrush" Color="#EA966F" />
<SolidColorBrush x:Key="BorderBackgroundBrush" Color="#E3C381" />
<SolidColorBrush x:Key="BorderHighlightBrush" Color="#EFCD88" />
<SolidColorBrush x:Key="PaddingBackgroundBrush" Color="#B8C47F" />
<SolidColorBrush x:Key="PaddingHighlightBrush" Color="#CEDA8E" />
<SolidColorBrush x:Key="SizeBackgroundBrush" Color="#88B2BD" />
<SolidColorBrush x:Key="SizeHighlightBrush" Color="#9ED0DC" />
</UserControl.Resources>
<Grid RowDefinitions="*,Auto">
<Viewbox Grid.Row="0" StretchDirection="DownOnly">
<Grid x:Name="LayoutRoot" Margin="8,0,8,8" RowDefinitions="Auto,Auto"
ColumnDefinitions="Auto,Auto">
<Grid.Styles>
<Style Selector="TextBlock.with-constraint">
<Setter Property="TextDecorations" Value="Underline" />
</Style>
</Grid.Styles>
<Border x:Name="VerticalSize" Grid.Row="0" Grid.Column="1">
<TextBlock VerticalAlignment="Center" FontWeight="Bold"
Classes.with-constraint="{Binding HeightConstraint, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
Text="{Binding Height}"
ToolTip.Tip="{Binding HeightConstraint}" />
</Border>
<Border x:Name="HorizontalSize" Grid.Row="1" Grid.Column="0">
<TextBlock HorizontalAlignment="Center" FontWeight="Bold"
Classes.with-constraint="{Binding WidthConstraint, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
Text="{Binding Width}"
ToolTip.Tip="{Binding WidthConstraint}" />
</Border>
<controls:ThicknessEditor Grid.Row="0" Grid.Column="0" Header="margin" VerticalAlignment="Top"
HorizontalAlignment="Center"
Background="{StaticResource MarginBackgroundBrush}"
Highlight="{StaticResource MarginHighlightBrush}"
Thickness="{Binding MarginThickness}">
<controls:ThicknessEditor x:Name="BorderArea" Header="border"
Background="{StaticResource BorderBackgroundBrush}"
Highlight="{StaticResource BorderHighlightBrush}"
Thickness="{Binding BorderThickness}"
IsPresent="{Binding HasBorder}">
<controls:ThicknessEditor x:Name="PaddingArea" Header="padding"
Background="{StaticResource PaddingBackgroundBrush}"
Highlight="{StaticResource PaddingHighlightBrush}"
Thickness="{Binding PaddingThickness}"
IsPresent="{Binding HasPadding}">
<Border x:Name="ContentArea" BorderThickness="1" MinWidth="100" MinHeight="16"
VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Border.Styles>
<Style Selector="Border">
<Setter Property="Background" Value="{StaticResource SizeBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource ThicknessBorderBrush}" />
</Style>
<Style Selector="Border:pointerover">
<Setter Property="Background" Value="{StaticResource SizeHighlightBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource HighlightBorderBrush}" />
</Style>
</Border.Styles>
<TextBlock Margin="2" HorizontalAlignment="Center" VerticalAlignment="Center"
Text="content" />
</Border>
</controls:ThicknessEditor>
</controls:ThicknessEditor>
</controls:ThicknessEditor>
<Canvas Grid.Row="0" Grid.Column="0" Grid.RowSpan="2" Grid.ColumnSpan="2">
<Canvas.Styles>
<Style Selector="Rectangle">
<Setter Property="StrokeDashArray" Value="1,3" />
<Setter Property="Stroke" Value="{StaticResource SizeGuidelineBrush}" />
<Setter Property="StrokeThickness" Value="1" />
<Setter Property="IsHitTestVisible" Value="False" />
</Style>
</Canvas.Styles>
<Rectangle x:Name="HorizontalSizeBegin" />
<Rectangle x:Name="HorizontalSizeEnd" />
<Rectangle x:Name="VerticalSizeBegin" />
<Rectangle x:Name="VerticalSizeEnd" />
</Canvas>
</Grid>
</Viewbox>
<StackPanel Orientation="Vertical" Grid.Column="0" Grid.Row="1" Spacing="4"
Margin="4" HorizontalAlignment="Stretch">
<StackPanel.Resources>
<converters:EnumToCheckedConverter x:Key="AlignmentConverter" />
</StackPanel.Resources>
<StackPanel.Styles>
<Style Selector="RadioButton">
<Setter Property="Template">
<ControlTemplate>
<Border
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Padding="{TemplateBinding Padding}">
<Path x:Name="PART_Path" Fill="Black" Width="16" Height="16" Stretch="Uniform" />
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="RadioButton">
<Setter Property="Background" Value="WhiteSmoke" />
<Setter Property="Padding" Value="2" />
</Style>
<Style Selector="RadioButton:pointerover">
<Setter Property="Background" Value="{DynamicResource ThemeControlHighlightMidBrush}" />
</Style>
<Style Selector="RadioButton:checked">
<Setter Property="Background" Value="{DynamicResource ThemeAccentBrush4}" />
</Style>
</StackPanel.Styles>
<DockPanel HorizontalAlignment="Stretch" LastChildFill="True">
<DockPanel.Styles>
<Style Selector="RadioButton.h-left /template/ Path#PART_Path">
<Setter Property="Data" Value="M22 13V19H6V13H22M6 5V11H16V5H6M2 2V22H4V2H2" />
</Style>
<Style Selector="RadioButton.h-center /template/ Path#PART_Path">
<Setter Property="Data"
Value="M20 19H13V22H11V19H4V13H11V11H7V5H11V2H13V5H17V11H13V13H20V19Z" />
</Style>
<Style Selector="RadioButton.h-right /template/ Path#PART_Path">
<Setter Property="Data" Value="M18 13V19H2V13H18M8 5V11H18V5H8M20 2V22H22V2H20Z" />
</Style>
<Style Selector="RadioButton.h-stretch /template/ Path#PART_Path">
<Setter Property="Data" Value="M4,22H2V2h2V22z M22,2h-2v20h2V2z M13.5,7h-3v10h3V7z" />
</Style>
</DockPanel.Styles>
<Label DockPanel.Dock="Left" Content="Horizontal Alignment" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<RadioButton GroupName="HAlignment" Classes="h-left"
ToolTip.Tip="Left"
IsChecked="{Binding HorizontalAlignment, Converter={StaticResource AlignmentConverter}, ConverterParameter={x:Static HorizontalAlignment.Left}}" />
<RadioButton GroupName="HAlignment" Classes="h-center" BorderThickness="0,1,1,1"
ToolTip.Tip="Center"
IsChecked="{Binding HorizontalAlignment, Converter={StaticResource AlignmentConverter}, ConverterParameter={x:Static HorizontalAlignment.Center}}" />
<RadioButton GroupName="HAlignment" Classes="h-right" BorderThickness="0,1,1,1"
ToolTip.Tip="Right"
IsChecked="{Binding HorizontalAlignment, Converter={StaticResource AlignmentConverter}, ConverterParameter={x:Static HorizontalAlignment.Right}}" />
<RadioButton GroupName="HAlignment" Classes="h-stretch"
ToolTip.Tip="Stretch"
IsChecked="{Binding HorizontalAlignment, Converter={StaticResource AlignmentConverter}, ConverterParameter={x:Static HorizontalAlignment.Stretch}}" />
</StackPanel>
</DockPanel>
<DockPanel HorizontalAlignment="Stretch" LastChildFill="True">
<DockPanel.Styles>
<Style Selector="RadioButton.v-top /template/ Path#PART_Path">
<Setter Property="Data" Value="M11 22H5V6H11V22M19 6H13V16H19V6M22 2H2V4H22V2Z" />
</Style>
<Style Selector="RadioButton.v-center /template/ Path#PART_Path">
<Setter Property="Data"
Value="M5 20V13H2V11H5V4H11V11H13V7H19V11H22V13H19V17H13V13H11V20H5Z" />
</Style>
<Style Selector="RadioButton.v-bottom /template/ Path#PART_Path">
<Setter Property="Data" Value="M11 18H5V2H11V18M19 8H13V18H19V8M22 20H2V22H22V20Z" />
</Style>
<Style Selector="RadioButton.v-stretch /template/ Path#PART_Path">
<Setter Property="Data" Value="M22,2v2H2V2H22z M7,10.5v3h10v-3H7z M2,20v2h20v-2H2z" />
</Style>
</DockPanel.Styles>
<Label DockPanel.Dock="Left" Content="Vertical Alignment" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<RadioButton GroupName="VAlignment" Classes="v-top"
ToolTip.Tip="Top"
IsChecked="{Binding VerticalAlignment, Converter={StaticResource AlignmentConverter}, ConverterParameter={x:Static VerticalAlignment.Top}}" />
<RadioButton GroupName="VAlignment" Classes="v-center" BorderThickness="0,1,1,1"
ToolTip.Tip="Center"
IsChecked="{Binding VerticalAlignment, Converter={StaticResource AlignmentConverter}, ConverterParameter={x:Static VerticalAlignment.Center}}" />
<RadioButton GroupName="VAlignment" Classes="v-bottom" BorderThickness="0,1,1,1"
ToolTip.Tip="Bottom"
IsChecked="{Binding VerticalAlignment, Converter={StaticResource AlignmentConverter}, ConverterParameter={x:Static VerticalAlignment.Bottom}}" />
<RadioButton GroupName="VAlignment" Classes="v-stretch"
ToolTip.Tip="Stretch"
IsChecked="{Binding VerticalAlignment, Converter={StaticResource AlignmentConverter}, ConverterParameter={x:Static VerticalAlignment.Stretch}}" />
</StackPanel>
</DockPanel>
</StackPanel>
</Grid>
</UserControl>

128
src/Avalonia.Diagnostics/Diagnostics/Views/LayoutExplorerView.axaml.cs

@ -0,0 +1,128 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Diagnostics.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.VisualTree;
namespace Avalonia.Diagnostics.Views
{
internal class LayoutExplorerView : UserControl
{
private readonly ThicknessEditor _borderArea;
private readonly ThicknessEditor _paddingArea;
private readonly Rectangle _horizontalSizeBegin;
private readonly Rectangle _horizontalSizeEnd;
private readonly Rectangle _verticalSizeBegin;
private readonly Rectangle _verticalSizeEnd;
private readonly Grid _layoutRoot;
private readonly Border _horizontalSize;
private readonly Border _verticalSize;
private readonly Border _contentArea;
public LayoutExplorerView()
{
InitializeComponent();
_borderArea = this.FindControl<ThicknessEditor>("BorderArea");
_paddingArea = this.FindControl<ThicknessEditor>("PaddingArea");
_horizontalSizeBegin = this.FindControl<Rectangle>("HorizontalSizeBegin");
_horizontalSizeEnd = this.FindControl<Rectangle>("HorizontalSizeEnd");
_verticalSizeBegin = this.FindControl<Rectangle>("VerticalSizeBegin");
_verticalSizeEnd = this.FindControl<Rectangle>("VerticalSizeEnd");
_horizontalSize = this.FindControl<Border>("HorizontalSize");
_verticalSize = this.FindControl<Border>("VerticalSize");
_contentArea = this.FindControl<Border>("ContentArea");
_layoutRoot = this.FindControl<Grid>("LayoutRoot");
void SubscribeToBounds(Visual visual)
{
visual.GetPropertyChangedObservable(TransformedBoundsProperty)
.Subscribe(UpdateSizeGuidelines);
}
SubscribeToBounds(_borderArea);
SubscribeToBounds(_paddingArea);
SubscribeToBounds(_contentArea);
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void UpdateSizeGuidelines(AvaloniaPropertyChangedEventArgs e)
{
void UpdateGuidelines(Visual area)
{
if (area.TransformedBounds is TransformedBounds bounds)
{
// Horizontal guideline
{
var sizeArea = TranslateToRoot((_horizontalSize.TransformedBounds ?? default).Bounds.BottomLeft,
_horizontalSize);
var start = TranslateToRoot(bounds.Bounds.BottomLeft, area);
SetPosition(_horizontalSizeBegin, start);
var end = TranslateToRoot(bounds.Bounds.BottomRight, area);
SetPosition(_horizontalSizeEnd, end.WithX(end.X - 1));
var height = sizeArea.Y - start.Y + 2;
_horizontalSizeBegin.Height = height;
_horizontalSizeEnd.Height = height;
}
// Vertical guideline
{
var sizeArea = TranslateToRoot((_verticalSize.TransformedBounds ?? default).Bounds.TopRight, _verticalSize);
var start = TranslateToRoot(bounds.Bounds.TopRight, area);
SetPosition(_verticalSizeBegin, start);
var end = TranslateToRoot(bounds.Bounds.BottomRight, area);
SetPosition(_verticalSizeEnd, end.WithY(end.Y - 1));
var width = sizeArea.X - start.X + 2;
_verticalSizeBegin.Width = width;
_verticalSizeEnd.Width = width;
}
}
}
Point TranslateToRoot(Point point, IVisual from)
{
return from.TranslatePoint(point, _layoutRoot) ?? default;
}
static void SetPosition(Rectangle rect, Point start)
{
Canvas.SetLeft(rect, start.X);
Canvas.SetTop(rect, start.Y);
}
if (_borderArea.IsPresent)
{
UpdateGuidelines(_borderArea);
}
else if (_paddingArea.IsPresent)
{
UpdateGuidelines(_paddingArea);
}
else
{
UpdateGuidelines(_contentArea);
}
}
}
}

1
src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml

@ -15,6 +15,7 @@
<Style Selector="DataGrid ContextMenu">
<Setter Property="Foreground" Value="Black"/>
</Style>
<StyleInclude Source="avares://Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.axaml" />
</Window.Styles>
<views:MainView/>

2
src/Avalonia.Diagnostics/Diagnostics/Views/TreePageView.xaml

@ -2,7 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:Avalonia.Diagnostics.ViewModels"
x:Class="Avalonia.Diagnostics.Views.TreePageView">
<Grid ColumnDefinitions="0.4*,4,0.6*">
<Grid ColumnDefinitions="0.35*,4,0.65*">
<TreeView Name="tree"
BorderThickness="0"
Items="{Binding Nodes}"

Loading…
Cancel
Save