|
@@ -6,60 +6,91 @@ namespace PixiEditor.ViewModels.SubViewModels.Tools.ToolSettings.Toolbars;
|
|
|
|
|
|
internal static class ToolbarFactory
|
|
|
{
|
|
|
- public static Toolbar Create<T>() where T : ToolViewModel => Create<T, EmptyToolbar>();
|
|
|
+ public static Toolbar Create<T>(T tool) where T : ToolViewModel => Create<T, EmptyToolbar>(tool);
|
|
|
|
|
|
- public static TToolbar Create<T, TToolbar>() where T : ToolViewModel where TToolbar : Toolbar, new()
|
|
|
+ public static TToolbar Create<T, TToolbar>(T tool) where T : ToolViewModel where TToolbar : Toolbar, new()
|
|
|
{
|
|
|
- var tool = typeof(T);
|
|
|
+ var toolType = typeof(T);
|
|
|
var toolbar = new TToolbar();
|
|
|
|
|
|
- foreach (var property in tool.GetProperties())
|
|
|
+ foreach (var property in toolType.GetProperties())
|
|
|
{
|
|
|
var attribute = property.GetCustomAttribute<Settings.SettingsAttribute>();
|
|
|
+ if (attribute == null) continue;
|
|
|
|
|
|
- if (attribute == null)
|
|
|
- continue;
|
|
|
-
|
|
|
var name = attribute.Name ?? property.Name;
|
|
|
+ var label = attribute.LabelKey ?? name;
|
|
|
|
|
|
if (attribute is Settings.InheritedAttribute)
|
|
|
{
|
|
|
- var inherited = toolbar.GetSetting(name);
|
|
|
-
|
|
|
- if (inherited == null)
|
|
|
- {
|
|
|
- throw new NullReferenceException($"There's no inherited setting '{name}' on inherited toolbar of type '{typeof(TToolbar).FullName}' (Tool: {typeof(T).FullName})");
|
|
|
- }
|
|
|
+ ProcessInheritedSetting(toolType, tool, toolbar, property, attribute, name);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ var setting = CreateSetting(property.PropertyType, name, attribute, label);
|
|
|
+ AddValueChangedHandlerIfRequired(toolType, tool, setting, attribute);
|
|
|
+ toolbar.Settings.Add(setting);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (inherited.GetSettingType() != property.PropertyType)
|
|
|
- {
|
|
|
- throw new InvalidCastException($"Inherited setting '{name}' does not match property type '{property.PropertyType}' (Tool: {typeof(T).FullName})");
|
|
|
- }
|
|
|
+ return toolbar;
|
|
|
+ }
|
|
|
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- var label = attribute.LabelKey ?? name;
|
|
|
+ private static void ProcessInheritedSetting(Type toolType, ToolViewModel tool, Toolbar toolbar,
|
|
|
+ PropertyInfo property, Settings.SettingsAttribute attribute, string name)
|
|
|
+ {
|
|
|
+ var inherited = toolbar.GetSetting(name);
|
|
|
+ if (inherited == null || inherited.GetSettingType() != property.PropertyType)
|
|
|
+ {
|
|
|
+ throw new InvalidOperationException(
|
|
|
+ $"Inherited setting '{name}' does not match property type '{property.PropertyType}' (Tool: {toolType.FullName})");
|
|
|
+ }
|
|
|
|
|
|
- var setting = attribute switch
|
|
|
- {
|
|
|
- Settings.BoolAttribute => new BoolSetting(name, (bool)(attribute.DefaultValue ?? false), label),
|
|
|
- Settings.ColorAttribute => new ColorSetting(name, ((Color)(attribute.DefaultValue ?? Colors.White)).ToColor(), label),
|
|
|
- Settings.EnumAttribute => GetEnumSetting(property.PropertyType, name, attribute),
|
|
|
- Settings.FloatAttribute => new FloatSetting(name, (float)(attribute.DefaultValue ?? 0f), attribute.LabelKey),
|
|
|
- Settings.SizeAttribute => new SizeSetting(name, label),
|
|
|
- _ => throw new NotImplementedException($"SettingsAttribute of type '{attribute.GetType().FullName}' has not been implemented")
|
|
|
- };
|
|
|
-
|
|
|
- if (setting.GetSettingType() != property.PropertyType)
|
|
|
+ AddValueChangedHandlerIfRequired(toolType, tool, inherited, attribute);
|
|
|
+ }
|
|
|
+
|
|
|
+ private static Setting CreateSetting(Type propertyType, string name, Settings.SettingsAttribute attribute,
|
|
|
+ string label)
|
|
|
+ {
|
|
|
+ return attribute switch
|
|
|
+ {
|
|
|
+ Settings.BoolAttribute => new BoolSetting(name, (bool)(attribute.DefaultValue ?? false), label),
|
|
|
+ Settings.ColorAttribute => new ColorSetting(name,
|
|
|
+ ((Color)(attribute.DefaultValue ?? Colors.White)).ToColor(), label),
|
|
|
+ Settings.EnumAttribute => GetEnumSetting(propertyType, name, attribute),
|
|
|
+ Settings.FloatAttribute => new FloatSetting(name, (float)(attribute.DefaultValue ?? 0f), label),
|
|
|
+ Settings.SizeAttribute => new SizeSetting(name, label),
|
|
|
+ _ => throw new NotImplementedException(
|
|
|
+ $"SettingsAttribute of type '{attribute.GetType().FullName}' has not been implemented")
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void AddValueChangedHandlerIfRequired(Type toolType, ToolViewModel tool, Setting setting,
|
|
|
+ Settings.SettingsAttribute attribute)
|
|
|
+ {
|
|
|
+ if (attribute.Notify != null)
|
|
|
+ {
|
|
|
+ AddValueChangedHandler(toolType, tool, setting, attribute);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private static void AddValueChangedHandler<T>(Type toolType, T tool, Setting setting,
|
|
|
+ Settings.SettingsAttribute attribute) where T : ToolViewModel
|
|
|
+ {
|
|
|
+ if (attribute.Notify != null)
|
|
|
+ {
|
|
|
+ var method = toolType.GetMethod(attribute.Notify,
|
|
|
+ BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
|
|
|
+ Array.Empty<Type>());
|
|
|
+
|
|
|
+ if (method is null)
|
|
|
{
|
|
|
- throw new InvalidCastException($"Setting '{name}' does not match property type '{property.PropertyType}' (Tool: {typeof(T).FullName})");
|
|
|
+ throw new NullReferenceException(
|
|
|
+ $"No method found with the name '{attribute.Notify}' that does not have any parameters");
|
|
|
}
|
|
|
|
|
|
- toolbar.Settings.Add(setting);
|
|
|
+ setting.ValueChanged += (_, _) => method.Invoke(tool, null);
|
|
|
}
|
|
|
-
|
|
|
- return toolbar;
|
|
|
}
|
|
|
|
|
|
private static Setting GetEnumSetting(Type enumType, string name, Settings.SettingsAttribute attribute)
|