Browse Source

feat(DevTools): Can be edit Brush if is Property is Null

pull/11690/head
Giuseppe Lippolis 3 years ago
parent
commit
f6b4c8ef0d
  1. 21
      src/Avalonia.Diagnostics/Diagnostics/Controls/BrushEditor.axaml
  2. 131
      src/Avalonia.Diagnostics/Diagnostics/Controls/BrushEditor.axaml.cs
  3. 94
      src/Avalonia.Diagnostics/Diagnostics/Controls/BrushEditor.cs
  4. 1
      src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml

21
src/Avalonia.Diagnostics/Diagnostics/Controls/BrushEditor.axaml

@ -0,0 +1,21 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Avalonia.Diagnostics.Controls"
x:ClassModifier="internal">
<Design.PreviewWith>
<controls:BrushEditor />
</Design.PreviewWith>
<Style Selector=":is(controls|BrushEditor)">
<Setter Property="Template">
<ControlTemplate>
<Grid>
<Button Theme="{StaticResource SimpleTextBoxClearButtonTheme}"
x:Name="PART_ClearButton"
HorizontalAlignment="Right"
VerticalContentAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter>
</Style>
</Styles>

131
src/Avalonia.Diagnostics/Diagnostics/Controls/BrushEditor.axaml.cs

@ -0,0 +1,131 @@
using System;
using System.Globalization;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Media.Immutable;
namespace Avalonia.Diagnostics.Controls
{
[TemplatePart("PART_ClearButton", typeof(Button))]
partial class BrushEditor : TemplatedControl
{
private readonly EventHandler<RoutedEventArgs> clearHandler;
private Button? _cleraButton = default;
private readonly ColorView _colorView = new()
{
HexInputAlphaPosition = AlphaComponentPosition.Leading, // Always match XAML
};
public BrushEditor()
{
FlyoutBase.SetAttachedFlyout(this, new Flyout { Content = _colorView });
_colorView.ColorChanged += (_, e) => Brush = new ImmutableSolidColorBrush(e.NewColor);
clearHandler = (s, e) => Brush = default;
}
protected override Type StyleKeyOverride => typeof(BrushEditor);
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
if (_cleraButton is not null)
{
_cleraButton.Click -= clearHandler;
}
_cleraButton = e.NameScope.Find<Button>("PART_ClearButton");
if (_cleraButton is Button button)
{
button.Click += clearHandler;
}
}
/// <summary>
/// Defines the <see cref="Brush" /> property.
/// </summary>
public static readonly DirectProperty<BrushEditor, IBrush?> BrushProperty =
AvaloniaProperty.RegisterDirect<BrushEditor, IBrush?>(
nameof(Brush), o => o.Brush, (o, v) => o.Brush = v);
private IBrush? _brush;
public IBrush? Brush
{
get => _brush;
set => SetAndRaise(BrushProperty, ref _brush, value);
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == BrushProperty)
{
if (Brush is ISolidColorBrush scb)
{
_colorView.Color = scb.Color;
}
ToolTip.SetTip(this, Brush?.GetType().Name ?? "(null)");
InvalidateVisual();
}
}
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
FlyoutBase.ShowAttachedFlyout(this);
}
public override void Render(DrawingContext context)
{
base.Render(context);
var brush = Brush ?? Brushes.Black;
context.FillRectangle(brush, Bounds);
var text = (Brush as ISolidColorBrush)?.Color.ToString() ?? "(null)";
var ft = new FormattedText(text,
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
Typeface.Default,
10,
GetTextBrush(brush));
context.DrawText(ft,
new Point(Bounds.Width / 2 - ft.Width / 2, Bounds.Height / 2 - ft.Height / 2));
}
/// <summary>
/// <see cref="https://stackoverflow.com/questions/6763032/how-to-pick-a-background-color-depending-on-font-color-to-have-proper-contrast">How to pick a background color depending on font color to have proper contrast</see>/>
/// </summary>
/// <param name="brush"></param>
/// <returns></returns>
private static IBrush GetTextBrush(IBrush brush)
{
if (brush is ISolidColorBrush solid)
{
var color = solid.Color;
double R = color.R / 255.0;
double G = color.G / 255.0;
double B = color.B / 255.0;
R = Math.Pow((R + 0.055) / 1.055, 2.4);
G = Math.Pow((G + 0.055) / 1.055, 2.4);
B = Math.Pow((B + 0.055) / 1.055, 2.4);
var l = 0.2126 * R + 0.7152 * G + 0.0722 * B;
return l < 0.5 ? Brushes.White : Brushes.Black;
}
return Brushes.White;
}
}
}

94
src/Avalonia.Diagnostics/Diagnostics/Controls/BrushEditor.cs

@ -1,94 +0,0 @@
using System.Globalization;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Media;
using Avalonia.Media.Immutable;
namespace Avalonia.Diagnostics.Controls
{
internal sealed class BrushEditor : Control
{
/// <summary>
/// Defines the <see cref="Brush" /> property.
/// </summary>
public static readonly DirectProperty<BrushEditor, IBrush?> BrushProperty =
AvaloniaProperty.RegisterDirect<BrushEditor, IBrush?>(
nameof(Brush), o => o.Brush, (o, v) => o.Brush = v);
private IBrush? _brush;
public IBrush? Brush
{
get => _brush;
set => SetAndRaise(BrushProperty, ref _brush, value);
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == BrushProperty)
{
switch (Brush)
{
case ISolidColorBrush scb:
{
var colorView = new ColorView
{
HexInputAlphaPosition = AlphaComponentPosition.Leading, // Always match XAML
Color = scb.Color,
};
colorView.ColorChanged += (_, e) => Brush = new ImmutableSolidColorBrush(e.NewColor);
FlyoutBase.SetAttachedFlyout(this, new Flyout { Content = colorView });
ToolTip.SetTip(this, $"{scb.Color} ({Brush.GetType().Name})");
break;
}
default:
FlyoutBase.SetAttachedFlyout(this, null);
ToolTip.SetTip(this, Brush?.GetType().Name ?? "(null)");
break;
}
InvalidateVisual();
}
}
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
FlyoutBase.ShowAttachedFlyout(this);
}
public override void Render(DrawingContext context)
{
base.Render(context);
if (Brush != null)
{
context.FillRectangle(Brush, Bounds);
}
else
{
context.FillRectangle(Brushes.Black, Bounds);
var ft = new FormattedText("(null)",
CultureInfo.CurrentCulture,
FlowDirection.LeftToRight,
Typeface.Default,
10,
Brushes.White);
context.DrawText(ft,
new Point(Bounds.Width / 2 - ft.Width / 2, Bounds.Height / 2 - ft.Height / 2));
}
}
}
}

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

@ -15,6 +15,7 @@
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Simple.xaml"/>
<StyleInclude Source="avares://Avalonia.Diagnostics/Diagnostics/Controls/ThicknessEditor.axaml" />
<StyleInclude Source="avares://Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.axaml" />
<StyleInclude Source="avares://Avalonia.Diagnostics/Diagnostics/Controls/BrushEditor.axaml" />
<StyleInclude Source="avares://Avalonia.Controls.ColorPicker/Themes/Simple/Simple.xaml" />
</Window.Styles>
<Window.KeyBindings>

Loading…
Cancel
Save