Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pin properties dev tool update #12315

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion nukebuild/Numerge
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Globalization;
using Avalonia.Data.Converters;

namespace Avalonia.Diagnostics.Converters
{
internal class PinnedToBoolConverter : IValueConverter
{
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is string status)
{
return status.Equals("Pinned", StringComparison.OrdinalIgnoreCase);
}

return false;
}

public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is bool isPinned)
{
return isPinned ? "Pinned" : "Unpinned";
}

return "Unknown";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ internal class AvaloniaPropertyViewModel : PropertyViewModel
private string _priority;
private string _group;
private readonly Type _propertyType;
private enum PinnedStatus
{
Pinned,
Unpinned
}
private PinnedStatus _isPinned;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why define this as an enum? The "Is" name prefix implies it is a bool. If you keep it as a bool you can avoid the converter entirely, correct?


#nullable disable
// Remove "nullable disable" after MemberNotNull will work on our CI.
Expand All @@ -19,6 +25,7 @@ public AvaloniaPropertyViewModel(AvaloniaObject o, AvaloniaProperty property)
{
_target = o;
Property = property;
_isPinned = PinnedStatus.Unpinned;

Name = property.IsAttached ?
$"[{property.OwnerType.Name}.{property.Name}]" :
Expand All @@ -33,6 +40,21 @@ public AvaloniaPropertyViewModel(AvaloniaObject o, AvaloniaProperty property)
public override string Name { get; }
public override bool? IsAttached => Property.IsAttached;
public override string Priority => _priority;
public override string IsPinned
{
get => _isPinned.ToString();
set
{
try
{
if (Enum.TryParse(value, out PinnedStatus pinState))
{
_isPinned = pinState;
}
}
catch { }
}
Comment on lines +45 to +56
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is bad convention to be changing the data type in the property accessors. Whatever the underlying type is really should stay exposed as the property type.

}
public override Type AssignedType => _assignedType;

public override object? Value
Expand All @@ -55,7 +77,6 @@ public override object? Value
public override Type PropertyType => _propertyType;
public override bool IsReadonly => Property.IsReadOnly;

// [MemberNotNull(nameof(_type), nameof(_group), nameof(_priority))]
public override void Update()
{
if (Property.IsDirect)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ internal class ClrPropertyViewModel : PropertyViewModel
private Type _assignedType;
private object? _value;
private readonly Type _propertyType;
private enum PinnedStatus
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this enum can go away. Still, you shouldn't have two of the exact same enum defined.

{
Pinned,
Unpinned
}
private PinnedStatus _isPinned;

#nullable disable
// Remove "nullable disable" after MemberNotNull will work on our CI.
Expand All @@ -17,6 +23,7 @@ public ClrPropertyViewModel(object o, PropertyInfo property)
{
_target = o;
Property = property;
_isPinned = PinnedStatus.Unpinned;

if (property.DeclaringType == null || !property.DeclaringType.IsInterface)
{
Expand All @@ -42,6 +49,22 @@ public ClrPropertyViewModel(object o, PropertyInfo property)
public override Type PropertyType => _propertyType;
public override bool IsReadonly => !Property.CanWrite;

//determines if property is pinned to top in dev tools
public override string IsPinned
{
get => _isPinned.ToString();
set
{
try
{
if (Enum.TryParse(value, out PinnedStatus pinState))
{
_isPinned = pinState;
}
}
catch { }
}
}
public override object? Value
{
get => _value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@
using Avalonia.Data;
using Avalonia.Markup.Xaml.MarkupExtensions;
using Avalonia.Styling;
using Avalonia.VisualTree;

namespace Avalonia.Diagnostics.ViewModels
{
internal class ControlDetailsViewModel : ViewModelBase, IDisposable, IClassesChangedListener
{
private readonly AvaloniaObject _avaloniaObject;
private int _floatingGridHeight;
private List<PropertyViewModel> _properties;
private DataGridCollectionView? _propertiesView;
private IDictionary<object, PropertyViewModel[]>? _propertyIndex;
private PropertyViewModel? _selectedProperty;
private DataGridCollectionView? _propertiesView;
private bool _snapshotStyles;
private bool _showInactiveStyles;
private string? _styleStatus;
Expand All @@ -32,6 +33,8 @@ internal class ControlDetailsViewModel : ViewModelBase, IDisposable, IClassesCha
public ControlDetailsViewModel(TreePageViewModel treePage, AvaloniaObject avaloniaObject)
{
_avaloniaObject = avaloniaObject;
_floatingGridHeight = 0;
_properties = new List<PropertyViewModel>();

TreePage = treePage;
Layout = avaloniaObject is Visual visual
Expand Down Expand Up @@ -160,6 +163,12 @@ public DataGridCollectionView? PropertiesView
private set => RaiseAndSetIfChanged(ref _propertiesView, value);
}

public int FloatingGridHeight
{
get => _floatingGridHeight;
private set => RaiseAndSetIfChanged(ref _floatingGridHeight, value);
}

public ObservableCollection<StyleViewModel> AppliedStyles { get; }

public ObservableCollection<PseudoClassViewModel> PseudoClasses { get; }
Expand Down Expand Up @@ -481,7 +490,6 @@ public void NavigateToSelectedProperty()

RaisePropertyChanged(nameof(CanNavigateToParentProperty));
}

public void NavigateToParentProperty()
{
if (_selectedEntitiesStack.Count > 0)
Expand All @@ -492,7 +500,7 @@ public void NavigateToParentProperty()
RaisePropertyChanged(nameof(CanNavigateToParentProperty));
}
}

protected void NavigateToProperty(object o, string? entityName)
{
var oldSelectedEntity = SelectedEntity;
Expand All @@ -518,12 +526,14 @@ protected void NavigateToProperty(object o, string? entityName)
.ThenBy(x => x.Name)
.ToArray();

_propertyIndex = properties
_properties = properties.ToList();

_propertyIndex = _properties
.GroupBy(x => x.Key)
.ToDictionary(x => x.Key, x => x.ToArray());


var view = new DataGridCollectionView(properties);
view.GroupDescriptions.Add(new DataGridPathGroupDescription(nameof(AvaloniaPropertyViewModel.IsPinned)));
view.GroupDescriptions.Add(new DataGridPathGroupDescription(nameof(AvaloniaPropertyViewModel.Group)));
view.Filter = FilterProperty;
PropertiesView = view;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ internal abstract class PropertyViewModel : ViewModelBase
public abstract string Name { get; }
public abstract string Group { get; }
public abstract Type AssignedType { get; }
public abstract string IsPinned { get; set; }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So... three type? Bool in ConvertBack, String here and also the Enum?... should be just one as mentioned before. Am I missing something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, when it was only a bool passing it in as a groupdescription would have the groups titled true and false rather than pinned and unpinned.
The enum was just an attempt to avoid hardcoding the strings.

If there is another way to have the group descriptions renamed I will implement that but, I wasn't able to find anything. Even just hiding the name of the group would be a good option if possible.

public abstract Type? DeclaringType { get; }
public abstract object? Value { get; set; }
public abstract string Priority { get; }
Expand Down
82 changes: 45 additions & 37 deletions src/Avalonia.Diagnostics/Diagnostics/Views/ControlDetailsView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<UserControl.Resources>
<conv:BoolToOpacityConverter x:Key="BoolToOpacity" Opacity="0.6"/>
<conv:GetTypeNameConverter x:Key="GetTypeName"/>
<conv:PinnedToBoolConverter x:Key="PinnedToBool"/>
</UserControl.Resources>

<Grid>
Expand All @@ -28,7 +29,7 @@
<ColumnDefinition Width="320" lb:ColumnDefinition.IsVisible="{Binding Layout, Converter={x:Static ObjectConverters.IsNotNull}}" />
</Grid.ColumnDefinitions>

<Grid Grid.Column="0" RowDefinitions="Auto,Auto,*">
<Grid Grid.Column="0" RowDefinitions="Auto,Auto,Auto,*">

<Grid ColumnDefinitions="Auto, *" RowDefinitions="Auto, Auto">
<Button Grid.Column="0" Grid.RowSpan="2" Content="^"
Expand All @@ -40,7 +41,7 @@
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding SelectedEntityType}" FontStyle="Italic" />
</Grid>

<controls:FilterTextBox Grid.Row="1"
<controls:FilterTextBox Grid.Row="0"
BorderThickness="0"
DataContext="{Binding TreePage.PropertiesFilter}"
Text="{Binding FilterString}"
Expand All @@ -49,49 +50,56 @@
UseWholeWordFilter="{Binding UseWholeWordFilter}"
UseRegexFilter="{Binding UseRegexFilter}"/>

<DataGrid
x:Name="DataGrid"
ItemsSource="{Binding PropertiesView}"
Grid.Row="2"
BorderThickness="0"
RowBackground="Transparent"
SelectedItem="{Binding SelectedProperty, Mode=TwoWay}"
CanUserResizeColumns="true"
DoubleTapped="PropertiesGrid_OnDoubleTapped">
<DataGrid.Columns>
<DataGridTextColumn Header="Property" Binding="{Binding Name}" IsReadOnly="True" x:DataType="vm:PropertyViewModel" />
<DataGridTemplateColumn Header="Value" Width="100">
<Grid RowDefinitions="Auto,*" Grid.Row="2">
<DataGrid
x:Name="DataGrid"
ItemsSource="{Binding PropertiesView}"
Grid.Row="1"
BorderThickness="0"
RowBackground="Transparent"
SelectedItem="{Binding SelectedProperty, Mode=TwoWay}"
CanUserResizeColumns="true"
DoubleTapped="PropertiesGrid_OnDoubleTapped"
Height="1080"
VerticalAlignment="Stretch">
<DataGrid.Columns>
<DataGridCheckBoxColumn Header="Pin" Binding="{Binding IsPinned, Converter={StaticResource PinnedToBool}}" x:DataType="vm:PropertyViewModel"/>
<DataGridTextColumn Header="Property" Binding="{Binding Name}" IsReadOnly="True" x:DataType="vm:PropertyViewModel" Width="100"/>
<DataGridTemplateColumn Header="Value" Width="200">
<DataTemplate>
<local:PropertyValueEditorView />
</DataTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Header="Type" Binding="{Binding Type}"
IsReadOnly="True"
IsVisible="{Binding !$parent[UserControl;2].((vm:MainViewModel)DataContext).ShowDetailsPropertyType}"
x:DataType="vm:PropertyViewModel"
</DataGridTemplateColumn>
<DataGridTextColumn Header="Type" Binding="{Binding Type}"
IsReadOnly="True"
IsVisible="{Binding !$parent[UserControl;2].((vm:MainViewModel)DataContext).ShowDetailsPropertyType}"
x:DataType="vm:PropertyViewModel"
Width="200"
/>
<DataGridTextColumn Header="Assigned Type" Binding="{Binding AssignedType, Converter={StaticResource GetTypeName}}"
IsReadOnly="True"
IsVisible="{Binding $parent[UserControl;2].((vm:MainViewModel)DataContext).ShowDetailsPropertyType}"
x:DataType="vm:PropertyViewModel"
<DataGridTextColumn Header="Assigned Type" Binding="{Binding AssignedType, Converter={StaticResource GetTypeName}}"
IsReadOnly="True"
IsVisible="{Binding $parent[UserControl;2].((vm:MainViewModel)DataContext).ShowDetailsPropertyType}"
x:DataType="vm:PropertyViewModel"
Width="100"
/>
<DataGridTextColumn Header="Property Type" Binding="{Binding PropertyType, Converter={StaticResource GetTypeName}}"
IsReadOnly="True"
IsVisible="{Binding $parent[UserControl;2].((vm:MainViewModel)DataContext).ShowDetailsPropertyType}"
x:DataType="vm:PropertyViewModel"
<DataGridTextColumn Header="Property Type" Binding="{Binding PropertyType, Converter={StaticResource GetTypeName}}"
IsReadOnly="True"
IsVisible="{Binding $parent[UserControl;2].((vm:MainViewModel)DataContext).ShowDetailsPropertyType}"
x:DataType="vm:PropertyViewModel"
Width="300"
/>
<DataGridTextColumn Header="Priority" Binding="{Binding Priority}" IsReadOnly="True" x:DataType="vm:PropertyViewModel" />
</DataGrid.Columns>

<DataGrid.Styles>
<Style Selector="DataGridRow TextBox">
<Setter Property="SelectionBrush" Value="LightBlue" />
</Style>
</DataGrid.Styles>
</DataGrid>
<DataGridTextColumn Header="Priority" Binding="{Binding Priority}" IsReadOnly="True" x:DataType="vm:PropertyViewModel" Width="100"/>
</DataGrid.Columns>

<DataGrid.Styles>
<Style Selector="DataGridRow TextBox">
<Setter Property="SelectionBrush" Value="LightBlue" />
</Style>
</DataGrid.Styles>
</DataGrid>
</Grid>
</Grid>

<GridSplitter Grid.Column="1"/>

<Grid Grid.Column="2" RowDefinitions="*,Auto,*"
Expand Down