Skip to content

Commit ae3f7c4

Browse files
author
Aytackydln
committed
add coler coded borders to properties in overrides panel
1 parent 920862c commit ae3f7c4

6 files changed

Lines changed: 176 additions & 43 deletions

File tree

Project-Aurora/Project-Aurora/Settings/Layers/Layer.cs

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
using System.Collections.Generic;
33
using System.ComponentModel;
44
using System.Drawing;
5+
using System.Linq;
56
using System.Threading.Tasks;
67
using System.Windows.Controls;
78
using AuroraRgb.Bitmaps;
89
using AuroraRgb.EffectsEngine;
910
using AuroraRgb.Profiles;
1011
using AuroraRgb.Settings.Layers.Exceptions;
12+
using AuroraRgb.Settings.Overrides;
1113
using AuroraRgb.Settings.Overrides.Logic;
1214
using AuroraRgb.Utils.Json;
1315
using Newtonsoft.Json;
@@ -18,7 +20,7 @@ namespace AuroraRgb.Settings.Layers;
1820
/// <summary>
1921
/// A class representing a default settings layer
2022
/// </summary>
21-
public class Layer : INotifyPropertyChanged, ICloneable, IDisposable
23+
public partial class Layer : INotifyPropertyChanged, ICloneable, IDisposable
2224
{
2325
[DoNotNotify, JsonIgnore]
2426
public Application? AssociatedApplication { get; private set; }
@@ -36,8 +38,14 @@ public class Layer : INotifyPropertyChanged, ICloneable, IDisposable
3638
public Dictionary<string, IOverrideLogic> OverrideLogic { get; set; } = [];
3739
// private void OnOverrideLogicChanged() => // Make the logic collection changed event trigger a property change to ensure it gets saved?
3840

41+
internal List<LayerPropertyViewModel> CachedPropertyList { get; private set; }
42+
3943
#region Constructors
40-
public Layer() { }
44+
45+
public Layer()
46+
{
47+
CachedPropertyList = CreateOverridablePropertiesInternal();
48+
}
4149

4250
public Layer(string name, ILayerHandler? handler = null) : this() {
4351
Name = name;
@@ -50,14 +58,28 @@ private Layer(string name, ILayerHandler handler, Dictionary<string, IOverrideLo
5058

5159
public Layer(string name, ILayerHandler handler, OverrideLogicBuilder builder) : this(name, handler, new Dictionary<string, IOverrideLogic>(builder.Create())) { }
5260
#endregion
53-
54-
public event PropertyChangedEventHandler? PropertyChanged;
5561

5662
[JsonIgnore]
5763
public bool Error { get; private set; }
5864

5965
private int _renderErrors;
6066

67+
private List<LayerPropertyViewModel> CreateOverridablePropertiesInternal()
68+
{
69+
// Get a list of any members that should be ignored as per the LogicOverrideIgnorePropertyAttribute on the properties class
70+
var ignoredProperties = GetType().GetCustomAttributes(typeof(LogicOverrideIgnorePropertyAttribute), false)
71+
.Cast<LogicOverrideIgnorePropertyAttribute>()
72+
.Select(attr => attr.PropertyName);
73+
74+
return Handler.Properties.GetType()
75+
.GetProperties() // Get all properties on the layer handler's property list
76+
.Where(prop => prop.GetCustomAttributes(typeof(LogicOverridableAttribute), true).Length > 0) // Filter to only return the PropertyInfos that have Overridable
77+
.Where(prop => !ignoredProperties.Contains(prop.Name)) // Only select things that are NOT on the ignored properties list
78+
.Select(prop => new LayerPropertyViewModel(prop, this))
79+
.OrderBy(tup => tup.DisplayName)
80+
.ToList();
81+
}
82+
6183
private static readonly Dictionary<Type, Action<Layer, IGameState, string, IOverrideLogic>> OverrideTypeFuncs = new()
6284
{
6385
{
@@ -105,6 +127,7 @@ private Layer(string name, ILayerHandler handler, Dictionary<string, IOverrideLo
105127
private void OnHandlerChanged() {
106128
if (AssociatedApplication != null)
107129
Handler.SetApplication(AssociatedApplication);
130+
CachedPropertyList = CreateOverridablePropertiesInternal();
108131
}
109132

110133
public EffectLayer Render(IGameState gs)
@@ -199,6 +222,23 @@ public object Clone() {
199222

200223
public void SetGameState(IGameState newGameState) => Handler.SetGameState(newGameState);
201224
public void Dispose() => Handler.Dispose();
225+
226+
public void RemoveOverrideLogic(string propertyName)
227+
{
228+
OverrideLogic.Remove(propertyName);
229+
Handler.Properties.SetOverride(propertyName, null);
230+
231+
// fire property changed
232+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OverrideLogic)));
233+
}
234+
235+
public void SetOverrideLogic(string propertyName, IOverrideLogic overrideLogic)
236+
{
237+
OverrideLogic[propertyName] = overrideLogic;
238+
239+
// fire property changed
240+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OverrideLogic)));
241+
}
202242
}
203243

204244
/// <summary>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<UserControl x:Class="AuroraRgb.Settings.Overrides.Control_LayerPropertyListItem"
2+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
5+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
6+
xmlns:overrides="clr-namespace:AuroraRgb.Settings.Overrides"
7+
mc:Ignorable="d"
8+
d:DataContext="{d:DesignInstance Type=overrides:LayerPropertyViewModel, IsDesignTimeCreatable=True}"
9+
d:DesignHeight="300" d:DesignWidth="300">
10+
<UserControl.Resources>
11+
<overrides:PrettyTypeNameConverter x:Key="PrettyTypeNameConv" />
12+
<overrides:TypeToIconConverter x:Key="TypeToIconConv" />
13+
<overrides:OverrideTypeToColorConverter x:Key="OverrideTypeToColorConverter" />
14+
</UserControl.Resources>
15+
<Grid>
16+
<Grid.ColumnDefinitions>
17+
<ColumnDefinition Width="Auto"></ColumnDefinition>
18+
<ColumnDefinition Width="Auto"></ColumnDefinition>
19+
<ColumnDefinition Width="*"></ColumnDefinition>
20+
</Grid.ColumnDefinitions>
21+
<Border Width="8" Background="{Binding OverrideType, Converter={StaticResource OverrideTypeToColorConverter}}" />
22+
<Image Source="{Binding PropertyType, Converter={StaticResource TypeToIconConv}}"
23+
ToolTip="{Binding PropertyType, Converter={StaticResource PrettyTypeNameConv}, Mode=OneTime}"
24+
Width="30" Height="30" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="4"
25+
Grid.Column="1" />
26+
<TextBlock Text="{Binding PropertyName, Mode=OneTime}" Margin="8,1,0,0"
27+
Grid.Column="2" />
28+
<TextBlock Text="{Binding PropertyType, Converter={StaticResource PrettyTypeNameConv}, Mode=OneTime}" Margin="8,16,0,0" Opacity="0.3"
29+
Grid.Column="2" />
30+
</Grid>
31+
</UserControl>
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Globalization;
4+
using System.Windows.Data;
5+
using System.Windows.Media;
6+
using AuroraRgb.Settings.Overrides.Logic;
7+
8+
namespace AuroraRgb.Settings.Overrides;
9+
10+
public partial class Control_LayerPropertyListItem
11+
{
12+
public Control_LayerPropertyListItem()
13+
{
14+
InitializeComponent();
15+
16+
// init design time data
17+
if (DesignerProperties.GetIsInDesignMode(this))
18+
{
19+
DataContext = new LayerPropertyViewModel("PropertyName", "Display Name", typeof(int));
20+
}
21+
}
22+
}
23+
24+
25+
public class OverrideTypeToColorConverter : IValueConverter
26+
{
27+
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
28+
{
29+
if ((Type)value! == typeof(OverrideDynamicValue))
30+
return Brushes.MediumPurple;
31+
if ((Type)value! == typeof(OverrideLookupTable))
32+
return Brushes.Teal;
33+
return Brushes.DimGray;
34+
}
35+
36+
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
37+
{
38+
throw new NotImplementedException();
39+
}
40+
}

Project-Aurora/Project-Aurora/Settings/Overrides/Control_OverridesEditor.xaml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
mc:Ignorable="d"
1010
d:DesignHeight="520" d:DesignWidth="920">
1111
<UserControl.Resources>
12-
<overrides:PrettyTypeNameConverter x:Key="PrettyTypeNameConv" />
13-
<overrides:TypeToIconConverter x:Key="TypeToIconConv" />
1412
<overrides:HasValueToBoolConverter x:Key="HasValToBoolConv" />
1513
</UserControl.Resources>
1614

@@ -28,11 +26,7 @@
2826
<ListBox ItemsSource="{Binding AvailableLayerProperties}" SelectedItem="{Binding SelectedProperty}" Margin="0,0,0,8">
2927
<ListBox.ItemTemplate>
3028
<DataTemplate>
31-
<Grid>
32-
<Image Source="{Binding Item3, Converter={StaticResource TypeToIconConv}}" ToolTip="{Binding Item3, Converter={StaticResource PrettyTypeNameConv}, Mode=OneTime}" Width="30" Height="30" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="4" />
33-
<TextBlock Text="{Binding Item2, Mode=OneTime}" Margin="38,1,0,0" />
34-
<TextBlock Text="{Binding Item3, Converter={StaticResource PrettyTypeNameConv}, Mode=OneTime}" Margin="38,16,0,0" Opacity="0.3" />
35-
</Grid>
29+
<overrides:Control_LayerPropertyListItem />
3630
</DataTemplate>
3731
</ListBox.ItemTemplate>
3832
</ListBox>

Project-Aurora/Project-Aurora/Settings/Overrides/Control_OverridesEditor.xaml.cs

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@
33
using System.ComponentModel;
44
using System.Diagnostics;
55
using System.Globalization;
6-
using System.Linq;
76
using System.Windows;
87
using System.Windows.Data;
98
using System.Windows.Media;
109
using System.Windows.Media.Imaging;
1110
using AuroraRgb.Settings.Layers;
1211
using AuroraRgb.Settings.Overrides.Logic;
13-
using AuroraRgb.Utils;
1412
using PropertyChanged;
1513
using Application = AuroraRgb.Profiles.Application;
1614
using Color = System.Drawing.Color;
@@ -44,26 +42,7 @@ protected void OnPropertyChanged(params string[] affectedProperties) {
4442
/// For the given layer, returns a list of all properties on the handler of that layer that have the OverridableAttribute
4543
/// applied (i.e. have been marked overridable for the overrides system).
4644
/// </summary>
47-
public List<Tuple<string, string, Type>> AvailableLayerProperties {
48-
get {
49-
// Get a list of any members that should be ignored as per the LogicOverrideIgnorePropertyAttribute on the properties class
50-
var ignoredProperties = Layer?.Handler.GetType().GetCustomAttributes(typeof(LogicOverrideIgnorePropertyAttribute), false)
51-
.Cast<LogicOverrideIgnorePropertyAttribute>()
52-
.Select(attr => attr.PropertyName);
53-
54-
return Layer?.Handler.Properties.GetType().GetProperties() // Get all properties on the layer handler's property list
55-
.Where(prop => prop.GetCustomAttributes(typeof(LogicOverridableAttribute), true).Length > 0) // Filter to only return the PropertyInfos that have Overridable
56-
.Where(prop => !ignoredProperties.Contains(prop.Name)) // Only select things that are NOT on the ignored properties list
57-
.Select(prop => new Tuple<string, string, Type>( // Return the name and type of these properties.
58-
prop.Name, // The actual C# property name
59-
((LogicOverridableAttribute)prop.GetCustomAttributes(typeof(LogicOverridableAttribute), true)[0]).Name // Get the name specified in the attribute (so it is prettier for the user),
60-
?? prop.Name.TrimStart('_').CamelCaseToSpaceCase(), // but if one wasn't provided, pretty-print the code name
61-
Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType // If the property is a nullable type (e.g. bool?), will instead return the non-nullable type (bool)
62-
))
63-
.OrderBy(tup => tup.Item2)
64-
.ToList();
65-
}
66-
}
45+
public List<LayerPropertyViewModel> AvailableLayerProperties => Layer.CachedPropertyList;
6746

6847
// List of all IOverrideLogic types that the user can select
6948
public Dictionary<string, Type?> OverrideTypes { get; } = new()
@@ -80,8 +59,8 @@ public Layer Layer {
8059
}
8160

8261
// The name of the selected property that is being edited
83-
private Tuple<string, string, Type>? _selectedProperty;
84-
public Tuple<string, string, Type>? SelectedProperty {
62+
private LayerPropertyViewModel? _selectedProperty;
63+
public LayerPropertyViewModel? SelectedProperty {
8564
get => _selectedProperty;
8665
set {
8766
_selectedProperty = value;
@@ -90,9 +69,9 @@ public Tuple<string, string, Type>? SelectedProperty {
9069
}
9170

9271
// The override logic for the currently selected property
93-
public IOverrideLogic? SelectedLogic => _selectedProperty == null || !Layer.OverrideLogic.ContainsKey(_selectedProperty.Item1)
72+
public IOverrideLogic? SelectedLogic => _selectedProperty == null || !Layer.OverrideLogic.ContainsKey(_selectedProperty.PropertyName)
9473
? null // Return nothing if nothing in the list is selected or there is no logic for this property
95-
: Layer.OverrideLogic[_selectedProperty.Item1];
74+
: Layer.OverrideLogic[_selectedProperty.PropertyName];
9675

9776
// The type of logic in use by the selected property
9877
public Type? SelectedLogicType {
@@ -104,10 +83,9 @@ public Type? SelectedLogicType {
10483
// If there is a property selected in the list and the logic type is not set to the same value as it already was
10584
if (_selectedProperty == null || SelectedLogic?.GetType() == value) return;
10685
if (value == null) { // If the value is null, that means the user selected the "None" option, so remove the override for this property. Also force reset the override to null so that it doesn't persist after removing the logic.
107-
Layer.OverrideLogic.Remove(_selectedProperty.Item1);
108-
Layer.Handler.Properties.SetOverride(_selectedProperty.Item1, null);
86+
Layer.RemoveOverrideLogic(_selectedProperty.PropertyName);
10987
} else // Else if the user selected a non-"None" option, create a new instance of that OverrideLogic and assign it to this property
110-
Layer.OverrideLogic[_selectedProperty.Item1] = (IOverrideLogic)Activator.CreateInstance(value, _selectedProperty.Item3);
88+
Layer.SetOverrideLogic(_selectedProperty.PropertyName, (IOverrideLogic)Activator.CreateInstance(value, _selectedProperty.PropertyType));
11189
OnPropertyChanged(nameof(SelectedLogic), nameof(SelectedLogicType), nameof(SelectedLogicControl)); // Raise an event to update the control
11290
}
11391
}
@@ -116,7 +94,7 @@ public Type? SelectedLogicType {
11694
public Visual SelectedLogicControl => SelectedLogic?.GetControl();
11795

11896
// Application context for logic
119-
public Application? Application => Layer?.AssociatedApplication;
97+
public Application? Application => Layer.AssociatedApplication;
12098
#endregion
12199

122100
#region Dependency Objects
@@ -130,14 +108,14 @@ private static void OnLayerChange(DependencyObject overridesEditor, DependencyPr
130108
}
131109

132110
public static readonly DependencyProperty LayerProperty = DependencyProperty.Register(nameof(Layer), typeof(Layer),
133-
typeof(Control_OverridesEditor), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender, OnLayerChange));
111+
typeof(Control_OverridesEditor), new FrameworkPropertyMetadata(new Layer(), FrameworkPropertyMetadataOptions.AffectsRender, OnLayerChange));
134112
#endregion
135113

136114
#region Methods
137115
public void ForcePropertyListUpdate() {
138116
// Inform bindings that the available properties list has changed.
139117
// This may also change the selected property, and therefore the selected logic etc.
140-
OnPropertyChanged("AvailableLayerProperties", "SelectedProperty", "SelectedLogic", "SelectedLogicType", "SelectedLogicControl");
118+
OnPropertyChanged(nameof(AvailableLayerProperties), nameof(SelectedProperty), nameof(SelectedLogic), nameof(SelectedLogicType), nameof(SelectedLogicControl));
141119
}
142120

143121
private void HelpButton_Click(object? sender, RoutedEventArgs e) {
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Linq;
4+
using System.Reflection;
5+
using AuroraRgb.Settings.Layers;
6+
using AuroraRgb.Utils;
7+
8+
namespace AuroraRgb.Settings.Overrides;
9+
10+
public partial class LayerPropertyViewModel : INotifyPropertyChanged
11+
{
12+
public string PropertyName { get; }
13+
public string DisplayName { get; }
14+
public Type PropertyType { get; }
15+
public Type? OverrideType { get; set; }
16+
17+
public LayerPropertyViewModel(PropertyInfo layerPropertyPropertyInfo, Layer layer)
18+
{
19+
// handle change of porperty's override type from layer
20+
layer.PropertyChanged += (sender, args) =>
21+
{
22+
if (args.PropertyName != nameof(Layer.OverrideLogic)) return;
23+
if (layer.OverrideLogic.TryGetValue(layerPropertyPropertyInfo.Name, out var value))
24+
{
25+
if (OverrideType == value.GetType()) return;
26+
OverrideType = value.GetType();
27+
}
28+
else
29+
{
30+
OverrideType = null;
31+
}
32+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(OverrideType)));
33+
};
34+
35+
PropertyName = layerPropertyPropertyInfo.Name;
36+
DisplayName =
37+
layerPropertyPropertyInfo.GetCustomAttributes<LogicOverridableAttribute>(true).FirstOrDefault()
38+
?.Name // Get the name specified in the attribute (so it is prettier for the user),
39+
?? layerPropertyPropertyInfo.Name.TrimStart('_').CamelCaseToSpaceCase(); // but if one wasn't provided, pretty-print the code name
40+
PropertyType = Nullable.GetUnderlyingType(layerPropertyPropertyInfo.PropertyType) ??
41+
layerPropertyPropertyInfo.PropertyType; // If the property is a nullable type (e.g. bool?), will instead return the non-nullable type (bool)
42+
}
43+
44+
public LayerPropertyViewModel(string propertyName, string displayName, Type propertyType)
45+
{
46+
PropertyName = propertyName;
47+
DisplayName = displayName;
48+
PropertyType = propertyType;
49+
}
50+
}

0 commit comments

Comments
 (0)