Browse Source

Create FilterTextBox

pull/5991/head
Max Katz 5 years ago
parent
commit
0efda32774
  1. 88
      src/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.axaml
  2. 54
      src/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.cs
  3. 18
      src/Avalonia.Diagnostics/Diagnostics/ViewModels/FilterViewModel.cs
  4. 28
      src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml
  5. 1
      src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml

88
src/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.axaml

@ -0,0 +1,88 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Avalonia.Diagnostics.Controls"
x:CompileBindings="True"
x:DataType="controls:FilterTextBox">
<Design.PreviewWith>
<Border Padding="10">
<controls:FilterTextBox Width="200" Text="Hello World" />
</Border>
</Design.PreviewWith>
<Style Selector="TextBox.filter-text-box">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="InnerRightContent">
<Template>
<StackPanel Orientation="Horizontal" Spacing="1">
<Button Margin="0,0,2,0"
Classes="textBoxClearButton"
Command="{ReflectionBinding $parent[TextBox].Clear}"
Opacity="0.5" />
<ToggleButton Classes="filter-text-box-toggle" IsChecked="{Binding $parent[controls:FilterTextBox].UseCaseSensitiveFilter}">
<Image>
<DrawingImage>
<GeometryDrawing Brush="{Binding $parent[ToggleButton].Foreground}">
M7.495 9.052L8.386 11.402H9.477L6.237 3H5.217L2 11.402H3.095L3.933 9.052H7.495ZM5.811 4.453L5.855 4.588L7.173 8.162H4.255L5.562 4.588L5.606 4.453L5.644 4.297L5.676 4.145L5.697 4.019H5.72L5.744 4.145L5.773 4.297L5.811 4.453ZM13.795 10.464V11.4H14.755V7.498C14.755 6.779 14.575 6.226 14.216 5.837C13.857 5.448 13.327 5.254 12.628 5.254C12.429 5.254 12.227 5.273 12.022 5.31C11.817 5.347 11.622 5.394 11.439 5.451C11.256 5.508 11.091 5.569 10.944 5.636C10.797 5.703 10.683 5.765 10.601 5.824V6.808C10.867 6.578 11.167 6.397 11.505 6.268C11.843 6.139 12.194 6.075 12.557 6.075C12.745 6.075 12.915 6.103 13.07 6.16C13.225 6.217 13.357 6.306 13.466 6.427C13.575 6.548 13.659 6.706 13.718 6.899C13.777 7.092 13.806 7.326 13.806 7.599L11.995 7.851C11.651 7.898 11.355 7.977 11.107 8.088C10.859 8.199 10.654 8.339 10.492 8.507C10.33 8.675 10.21 8.868 10.132 9.087C10.054 9.306 10.015 9.546 10.015 9.808C10.015 10.054 10.057 10.283 10.139 10.496C10.221 10.709 10.342 10.893 10.502 11.047C10.662 11.201 10.862 11.323 11.1 11.413C11.338 11.503 11.613 11.548 11.926 11.548C12.328 11.548 12.686 11.456 13.001 11.27C13.316 11.084 13.573 10.816 13.772 10.464H13.795ZM11.667 8.721C11.843 8.657 12.068 8.607 12.341 8.572L13.806 8.367V8.976C13.806 9.222 13.765 9.451 13.683 9.664C13.601 9.877 13.486 10.063 13.34 10.221C13.194 10.379 13.019 10.503 12.816 10.593C12.613 10.683 12.39 10.728 12.148 10.728C11.961 10.728 11.795 10.703 11.653 10.652C11.511 10.601 11.392 10.53 11.296 10.441C11.2 10.352 11.127 10.247 11.076 10.125C11.025 10.003 11 9.873 11 9.732C11 9.568 11.018 9.421 11.055 9.292C11.092 9.163 11.16 9.051 11.257 8.958C11.354 8.865 11.491 8.785 11.667 8.721Z
</GeometryDrawing>
</DrawingImage>
</Image>
</ToggleButton>
<ToggleButton Classes="filter-text-box-toggle" IsChecked="{Binding $parent[controls:FilterTextBox].UseWholeWordFilter}">
<Image>
<DrawingImage>
<GeometryDrawing Brush="{Binding $parent[ToggleButton].Foreground}">
M1 2H15V3H1V2ZM14 4H13V12H14V4ZM11.272 8.387C11.194 8.088 11.073 7.825 10.912 7.601C10.751 7.377 10.547 7.2 10.303 7.071C10.059 6.942 9.769 6.878 9.437 6.878C9.239 6.878 9.057 6.902 8.89 6.951C8.725 7 8.574 7.068 8.437 7.156C8.301 7.244 8.18 7.35 8.072 7.474L7.893 7.732V4.578H7V12H7.893V11.425L8.019 11.6C8.106 11.702 8.208 11.79 8.323 11.869C8.44 11.947 8.572 12.009 8.721 12.055C8.87 12.101 9.035 12.123 9.219 12.123C9.572 12.123 9.885 12.052 10.156 11.911C10.428 11.768 10.655 11.573 10.838 11.325C11.021 11.075 11.159 10.782 11.252 10.446C11.345 10.108 11.392 9.743 11.392 9.349C11.391 9.007 11.352 8.686 11.272 8.387ZM9.793 7.78C9.944 7.851 10.075 7.956 10.183 8.094C10.292 8.234 10.377 8.407 10.438 8.611C10.489 8.785 10.52 8.982 10.527 9.198L10.52 9.323C10.52 9.65 10.487 9.943 10.42 10.192C10.353 10.438 10.259 10.645 10.142 10.806C10.025 10.968 9.882 11.091 9.721 11.172C9.399 11.334 8.961 11.338 8.652 11.187C8.499 11.112 8.366 11.012 8.259 10.891C8.174 10.795 8.103 10.675 8.041 10.524C8.041 10.524 7.862 10.077 7.862 9.577C7.862 9.077 8.041 8.575 8.041 8.575C8.103 8.398 8.177 8.257 8.265 8.145C8.379 8.002 8.521 7.886 8.689 7.8C8.857 7.714 9.054 7.671 9.276 7.671C9.466 7.671 9.64 7.708 9.793 7.78ZM15 13H1V14H15V13ZM2.813 10L2.085 12.031H1L1.025 11.959L3.466 4.87305H4.407L6.892 12.031H5.81L5.032 10H2.813ZM3.934 6.42205H3.912L3.007 9.17505H4.848L3.934 6.42205Z
</GeometryDrawing>
</DrawingImage>
</Image>
</ToggleButton>
<ToggleButton Classes="filter-text-box-toggle" IsChecked="{Binding $parent[controls:FilterTextBox].UseRegexFilter}">
<Image>
<DrawingImage>
<GeometryDrawing Brush="{Binding $parent[ToggleButton].Foreground}">
M10.0122 2H10.9879V5.11346L13.5489 3.55609L14.034 4.44095L11.4702 6L14.034 7.55905L13.5489 8.44391L10.9879 6.88654V10H10.0122V6.88654L7.45114 8.44391L6.96606 7.55905L9.5299 6L6.96606 4.44095L7.45114 3.55609L10.0122 5.11346V2ZM2 10H6V14H2V10Z
</GeometryDrawing>
</DrawingImage>
</Image>
</ToggleButton>
</StackPanel>
</Template>
</Setter>
</Style>
<Style Selector="TextBox.filter-text-box Button.textBoxClearButton">
<Setter Property="IsVisible" Value="False" />
</Style>
<Style Selector="TextBox.filter-text-box[AcceptsReturn=False][IsReadOnly=False]:focus:not(TextBox:empty) Button.textBoxClearButton">
<Setter Property="IsVisible" Value="True" />
</Style>
<Style Selector="ToggleButton.filter-text-box-toggle > Image">
<Setter Property="Width" Value="16" />
<Setter Property="Height" Value="16" />
<Setter Property="Opacity" Value="0.5" />
</Style>
<Style Selector="ToggleButton.filter-text-box-toggle:pointerover > Image">
<Setter Property="Opacity" Value="0.7" />
</Style>
<Style Selector="ToggleButton.filter-text-box-toggle:pressed > Image, ToggleButton.filter-text-box-toggle:checked > Image">
<Setter Property="Opacity" Value="0.7" />
</Style>
<Style Selector="ToggleButton.filter-text-box-toggle">
<Setter Property="Padding" Value="0,1" />
<Setter Property="Width" Value="24" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
<Style Selector="ToggleButton.filter-text-box-toggle /template/ ContentPresenter">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="CornerRadius" Value="0" />
</Style>
<Style Selector="ToggleButton.filter-text-box-toggle:pressed /template/ ContentPresenter, ToggleButton.filter-text-box-toggle:checked /template/ ContentPresenter">
<Setter Property="BorderBrush" Value="{DynamicResource ThemeAccentColor}" />
<Setter Property="Background" Value="{DynamicResource ThemeAccentColor4}" />
</Style>
</Styles>

54
src/Avalonia.Diagnostics/Diagnostics/Controls/FilterTextBox.cs

@ -0,0 +1,54 @@
using System;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Styling;
namespace Avalonia.Diagnostics.Controls
{
internal class FilterTextBox : TextBox, IStyleable
{
public static readonly DirectProperty<FilterTextBox, bool> UseRegexFilterProperty =
AvaloniaProperty.RegisterDirect<FilterTextBox, bool>(nameof(UseRegexFilter),
o => o.UseRegexFilter, (o, v) => o.UseRegexFilter = v,
defaultBindingMode: BindingMode.TwoWay);
public static readonly DirectProperty<FilterTextBox, bool> UseCaseSensitiveFilterProperty =
AvaloniaProperty.RegisterDirect<FilterTextBox, bool>(nameof(UseCaseSensitiveFilter),
o => o.UseCaseSensitiveFilter, (o, v) => o.UseCaseSensitiveFilter = v,
defaultBindingMode: BindingMode.TwoWay);
public static readonly DirectProperty<FilterTextBox, bool> UseWholeWordFilterProperty =
AvaloniaProperty.RegisterDirect<FilterTextBox, bool>(nameof(UseWholeWordFilter),
o => o.UseWholeWordFilter, (o, v) => o.UseWholeWordFilter = v,
defaultBindingMode: BindingMode.TwoWay);
private bool _useRegexFilter, _useCaseSensitiveFilter, _useWholeWordFilter;
public FilterTextBox()
{
Classes.Add("filter-text-box");
}
public bool UseRegexFilter
{
get => _useRegexFilter;
set => SetAndRaise(UseRegexFilterProperty, ref _useRegexFilter, value);
}
public bool UseCaseSensitiveFilter
{
get => _useCaseSensitiveFilter;
set => SetAndRaise(UseCaseSensitiveFilterProperty, ref _useCaseSensitiveFilter, value);
}
public bool UseWholeWordFilter
{
get => _useWholeWordFilter;
set => SetAndRaise(UseWholeWordFilterProperty, ref _useWholeWordFilter, value);
}
Type IStyleable.StyleKey => typeof(TextBox);
}
}

18
src/Avalonia.Diagnostics/Diagnostics/ViewModels/FilterViewModel.cs

@ -9,7 +9,7 @@ namespace Avalonia.Diagnostics.ViewModels
internal class FilterViewModel : ViewModelBase, INotifyDataErrorInfo
{
private readonly Dictionary<string, string> _errors = new Dictionary<string, string>();
private string _propertyFilter = string.Empty;
private string _propertyString = string.Empty;
private bool _useRegexFilter, _useCaseSensitiveFilter, _useWholeWordFilter;
private string _processedFilter;
private Regex _filterRegex;
@ -25,13 +25,13 @@ namespace Avalonia.Diagnostics.ViewModels
{
void ClearError()
{
if (_errors.Remove(nameof(PropertyFilter)))
if (_errors.Remove(nameof(FilterString)))
{
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(PropertyFilter)));
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(FilterString)));
}
}
_processedFilter = PropertyFilter.Trim();
_processedFilter = FilterString.Trim();
try
{
@ -52,17 +52,17 @@ namespace Avalonia.Diagnostics.ViewModels
}
catch (Exception exception)
{
_errors[nameof(PropertyFilter)] = exception.Message;
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(PropertyFilter)));
_errors[nameof(FilterString)] = exception.Message;
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(nameof(FilterString)));
}
}
public string PropertyFilter
public string FilterString
{
get => _propertyFilter;
get => _propertyString;
set
{
if (RaiseAndSetIfChanged(ref _propertyFilter, value))
if (RaiseAndSetIfChanged(ref _propertyString, value))
{
UpdateFilterRegex();
RefreshFilter?.Invoke(this, EventArgs.Empty);

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

@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:conv="clr-namespace:Avalonia.Diagnostics.Converters"
xmlns:local="clr-namespace:Avalonia.Diagnostics.Views"
xmlns:controls="clr-namespace:Avalonia.Diagnostics.Controls"
xmlns:vm="clr-namespace:Avalonia.Diagnostics.ViewModels"
x:Class="Avalonia.Diagnostics.Views.ControlDetailsView"
x:Name="Main">
@ -12,24 +13,19 @@
<Grid ColumnDefinitions="*,Auto,320">
<Grid Grid.Column="0" ColumnDefinitions="*,Auto,Auto,Auto" RowDefinitions="Auto,*">
<TextBox Grid.Row="0"
Grid.Column="0"
BorderThickness="0"
Text="{Binding TreePage.PropertyFilter}"
Watermark="Filter properties" />
<CheckBox Grid.Row="0"
Grid.Column="1"
Margin="0,0,4,0"
Content="Regex"
IsChecked="{Binding TreePage.UseRegexFilter}" />
<Grid Grid.Column="0" RowDefinitions="Auto,*">
<controls:FilterTextBox Grid.Row="0"
BorderThickness="0"
DataContext="{Binding TreePage.PropertiesFilter}"
Text="{Binding FilterString}"
Watermark="Filter properties"
UseCaseSensitiveFilter="{Binding UseCaseSensitiveFilter}"
UseWholeWordFilter="{Binding UseWholeWordFilter}"
UseRegexFilter="{Binding UseRegexFilter}" />
<DataGrid Items="{Binding PropertiesView}"
Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
BorderThickness="0"
RowBackground="Transparent"
SelectedItem="{Binding SelectedProperty, Mode=TwoWay}"

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

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

Loading…
Cancel
Save