Browse Source

Merge branch 'layout-improvements' into avalonia-rewrite

flabbet 1 year ago
parent
commit
c936f5517a
30 changed files with 331 additions and 265 deletions
  1. 18 0
      src/PixiEditor/Helpers/EnumDescriptionConverter.cs
  2. 0 2
      src/PixiEditor/Models/Handlers/Toolbars/IToolbar.cs
  3. 14 1
      src/PixiEditor/ViewLocator.cs
  4. 0 3
      src/PixiEditor/ViewModels/SubViewModels/ToolsViewModel.cs
  5. 0 45
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/BoolSetting.cs
  6. 22 0
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/BoolSettingViewModel.cs
  7. 0 42
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/ColorSetting.cs
  8. 22 0
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/ColorSettingViewModel.cs
  9. 5 45
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/EnumSettingViewModel.cs
  10. 0 48
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/FloatSetting.cs
  11. 44 0
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/FloatSettingViewModel.cs
  12. 0 10
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/Setting.cs
  13. 0 40
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/SizeSetting.cs
  14. 27 0
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/SizeSettingViewModel.cs
  15. 4 4
      src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/BasicShapeToolbar.cs
  16. 3 3
      src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/BasicToolbar.cs
  17. 0 11
      src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/Toolbar.cs
  18. 5 5
      src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/ToolbarFactory.cs
  19. 5 5
      src/PixiEditor/ViewModels/Tools/Tools/PenToolViewModel.cs
  20. 1 1
      src/PixiEditor/Views/Main/Tools/Toolbar.axaml
  21. 13 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/BoolSettingView.axaml
  22. 14 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/BoolSettingView.axaml.cs
  23. 19 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/ColorSettingView.axaml
  24. 14 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/ColorSettingView.axaml.cs
  25. 26 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/EnumSettingView.axaml
  26. 14 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/EnumSettingView.axaml.cs
  27. 18 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/FloatSettingView.axaml
  28. 14 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/FloatSettingView.axaml.cs
  29. 15 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/SizeSettingView.axaml
  30. 14 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/SizeSettingView.axaml.cs

+ 18 - 0
src/PixiEditor/Helpers/EnumDescriptionConverter.cs

@@ -0,0 +1,18 @@
+using System.Globalization;
+using PixiEditor.Extensions.Helpers;
+using PixiEditor.Helpers.Converters;
+
+namespace PixiEditor.Helpers;
+
+internal class EnumDescriptionConverter : SingleInstanceConverter<EnumDescriptionConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        if (value is Enum enumValue)
+        {
+            return EnumHelpers.GetDescription(enumValue);
+        }
+
+        return value;
+    }
+}

+ 0 - 2
src/PixiEditor/Models/Handlers/Toolbars/IToolbar.cs

@@ -7,8 +7,6 @@ internal interface IToolbar : IHandler
 {
 {
     public Setting GetSetting(string name);
     public Setting GetSetting(string name);
     public ObservableCollection<Setting> Settings { get; set; }
     public ObservableCollection<Setting> Settings { get; set; }
-    public bool SettingsGenerated { get; }
-    public void GenerateSettings();
     public void SaveToolbarSettings();
     public void SaveToolbarSettings();
     public void LoadSharedSettings();
     public void LoadSharedSettings();
 }
 }

+ 14 - 1
src/PixiEditor/ViewLocator.cs

@@ -20,7 +20,8 @@ public class ViewLocator : IDataTemplate
 
 
     public Control Build(object? data)
     public Control Build(object? data)
     {
     {
-        var name = data.GetType().FullName.Replace("ViewModel", "View");
+        Type dataType = data.GetType();
+        var name = dataType.FullName.Replace("ViewModel", "View");
         var type = Type.GetType(name);
         var type = Type.GetType(name);
 
 
         if (type != null)
         if (type != null)
@@ -28,6 +29,18 @@ public class ViewLocator : IDataTemplate
             return (Control)Activator.CreateInstance(type);
             return (Control)Activator.CreateInstance(type);
         }
         }
 
 
+        if (dataType.IsGenericType)
+        {
+            string nameWithoutGeneric = data.GetType().FullName.Split('`')[0];
+            name = nameWithoutGeneric.Replace("ViewModel", "View");
+            type = Type.GetType(name);
+            
+            if (type != null)
+            {
+                return (Control)Activator.CreateInstance(type);
+            }
+        }
+
         type = data?.GetType() ?? typeof(object);
         type = data?.GetType() ?? typeof(object);
         if (ViewBindingsMap.TryGetValue(type, out Type viewType))
         if (ViewBindingsMap.TryGetValue(type, out Type viewType))
         {
         {

+ 0 - 3
src/PixiEditor/ViewModels/SubViewModels/ToolsViewModel.cs

@@ -152,9 +152,6 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
 
 
         ActiveTool?.OnDeselecting();
         ActiveTool?.OnDeselecting();
 
 
-        if (!tool.Toolbar.SettingsGenerated)
-            tool.Toolbar.GenerateSettings();
-
         if (ActiveTool != null) ActiveTool.IsTransient = false;
         if (ActiveTool != null) ActiveTool.IsTransient = false;
         bool shareToolbar = EnableSharedToolbar;
         bool shareToolbar = EnableSharedToolbar;
         if (ActiveTool is not null)
         if (ActiveTool is not null)

+ 0 - 45
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/BoolSetting.cs

@@ -1,45 +0,0 @@
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Controls.Primitives;
-using Avalonia.Data;
-using Avalonia.Layout;
-
-namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
-
-internal sealed class BoolSetting : Setting<bool>
-{
-    public BoolSetting(string name, string label = "")
-        : this(name, false, label)
-    {
-    }
-
-    public BoolSetting(string name, bool isChecked, string label = "")
-        : base(name)
-    {
-        Label = label;
-        Value = isChecked;
-    }
-
-    private Control GenerateCheckBox()
-    {
-        var checkBox = new CheckBox
-        {
-            IsChecked = Value,
-            VerticalAlignment = VerticalAlignment.Center
-        };
-
-        var binding = new Binding("Value")
-        {
-            Mode = BindingMode.TwoWay
-        };
-
-        checkBox.Bind(ToggleButton.IsCheckedProperty, binding);
-
-        return checkBox;
-    }
-
-    public override Control GenerateControl()
-    {
-        return GenerateCheckBox();
-    }
-}

+ 22 - 0
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/BoolSettingViewModel.cs

@@ -0,0 +1,22 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using Avalonia.Data;
+using Avalonia.Layout;
+
+namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
+
+internal sealed class BoolSettingViewModel : Setting<bool>
+{
+    public BoolSettingViewModel(string name, string label = "")
+        : this(name, false, label)
+    {
+    }
+
+    public BoolSettingViewModel(string name, bool isChecked, string label = "")
+        : base(name)
+    {
+        Label = label;
+        Value = isChecked;
+    }
+}

+ 0 - 42
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/ColorSetting.cs

@@ -1,42 +0,0 @@
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Data;
-using Avalonia.Media;
-using Avalonia.Xaml.Interactivity;
-using PixiEditor.Helpers.Behaviours;
-using PixiEditor.Views.Input;
-
-namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
-
-internal sealed class ColorSetting : Setting<Color>
-{
-    public ColorSetting(string name, string label = "") : this(name, Colors.White, label)
-    { }
-    
-    public ColorSetting(string name, Color defaultValue, string label = "")
-        : base(name)
-    {
-        Label = label;
-        Value = defaultValue;
-    }
-
-    private ToolSettingColorPicker GenerateColorPicker()
-    {
-        var picker = new ToolSettingColorPicker();
-
-        var selectedColorBinding = new Binding("Value")
-        {
-            Mode = BindingMode.TwoWay
-        };
-
-        var behavior = new GlobalShortcutFocusBehavior();
-        Interaction.GetBehaviors(picker).Add(behavior);
-        picker.Bind(ToolSettingColorPicker.SelectedColorProperty, selectedColorBinding);
-        return picker;
-    }
-
-    public override Control GenerateControl()
-    {
-        return GenerateColorPicker();
-    }
-}

+ 22 - 0
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/ColorSettingViewModel.cs

@@ -0,0 +1,22 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Data;
+using Avalonia.Media;
+using Avalonia.Xaml.Interactivity;
+using PixiEditor.Helpers.Behaviours;
+using PixiEditor.Views.Input;
+
+namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
+
+internal sealed class ColorSettingViewModel : Setting<Color>
+{
+    public ColorSettingViewModel(string name, string label = "") : this(name, Colors.White, label)
+    { }
+    
+    public ColorSettingViewModel(string name, Color defaultValue, string label = "")
+        : base(name)
+    {
+        Label = label;
+        Value = defaultValue;
+    }
+}

+ 5 - 45
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/EnumSetting.cs → src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/EnumSettingViewModel.cs

@@ -7,7 +7,7 @@ using PixiEditor.Extensions.UI;
 
 
 namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
 namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
 
 
-internal sealed class EnumSetting<TEnum> : Setting<TEnum, ComboBox>
+internal sealed class EnumSettingViewModel<TEnum> : Setting<TEnum, ComboBox>
     where TEnum : struct, Enum
     where TEnum : struct, Enum
 {
 {
     private int selectedIndex;
     private int selectedIndex;
@@ -49,58 +49,18 @@ internal sealed class EnumSetting<TEnum> : Setting<TEnum, ComboBox>
             base.Value = value;
             base.Value = value;
         }
         }
     }
     }
+    
+    public TEnum[] EnumValues { get; } = Enum.GetValues<TEnum>();
 
 
-    public override Control GenerateControl()
-    {
-        return GenerateDropdown();
-    }
-
-    public EnumSetting(string name, string label)
+    public EnumSettingViewModel(string name, string label)
         : base(name)
         : base(name)
     {
     {
         Label = label;
         Label = label;
     }
     }
 
 
-    public EnumSetting(string name, string label, TEnum defaultValue)
+    public EnumSettingViewModel(string name, string label, TEnum defaultValue)
         : this(name, label)
         : this(name, label)
     {
     {
         Value = defaultValue;
         Value = defaultValue;
     }
     }
-
-    private static ComboBox GenerateDropdown()
-    {
-        var combobox = new ComboBox
-        {
-            VerticalAlignment = VerticalAlignment.Center,
-            MinWidth = 85
-        };
-
-        GenerateItems(combobox);
-
-        var binding = new Binding(nameof(SelectedIndex))
-        {
-            Mode = BindingMode.TwoWay
-        };
-
-        combobox.Bind(ComboBox.SelectedIndexProperty, binding);
-
-        return combobox;
-    }
-
-    private static void GenerateItems(ComboBox comboBox)
-    {
-        var values = Enum.GetValues<TEnum>();
-
-        foreach (var value in values)
-        {
-            var item = new ComboBoxItem
-            {
-                Tag = value
-            };
-
-            Translator.SetKey(item, value.GetDescription());
-
-            comboBox.Items.Add(item);
-        }
-    }
 }
 }

+ 0 - 48
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/FloatSetting.cs

@@ -1,48 +0,0 @@
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Data;
-using PixiEditor.Views.Input;
-
-namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
-
-internal sealed class FloatSetting : Setting<float>
-{
-    public FloatSetting(
-        string name,
-        float initialValue,
-        string label = "",
-        float min = float.NegativeInfinity,
-        float max = float.PositiveInfinity)
-        : base(name)
-    {
-        Label = label;
-        Value = initialValue;
-        Min = min;
-        Max = max;
-    }
-
-    public float Min { get; set; }
-
-    public float Max { get; set; }
-
-    private NumberInput GenerateNumberInput()
-    {
-        var numbrInput = new NumberInput
-        {
-            Width = 40,
-            Min = Min,
-            Max = Max
-        };
-        var binding = new Binding("Value")
-        {
-            Mode = BindingMode.TwoWay
-        };
-        numbrInput.Bind(NumberInput.ValueProperty, binding);
-        return numbrInput;
-    }
-
-    public override Control GenerateControl()
-    {
-        return GenerateNumberInput();
-    }
-}

+ 44 - 0
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/FloatSettingViewModel.cs

@@ -0,0 +1,44 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Data;
+using PixiEditor.Views.Input;
+
+namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
+
+internal sealed class FloatSettingViewModel : Setting<float>
+{
+    private float min = float.NegativeInfinity;
+    private float max = float.PositiveInfinity;
+    
+    public FloatSettingViewModel(
+        string name,
+        float initialValue,
+        string label = "",
+        float min = float.NegativeInfinity,
+        float max = float.PositiveInfinity)
+        : base(name)
+    {
+        Label = label;
+        Value = initialValue;
+        Min = min;
+        Max = max;
+    }
+
+    public float Min
+    {
+        get => min;
+        set
+        {
+            SetProperty(ref min, value);
+        }
+    }
+
+    public float Max
+    {
+        get => max;
+        set
+        {
+            SetProperty(ref max, value);
+        }
+    }
+}

+ 0 - 10
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/Setting.cs

@@ -13,12 +13,6 @@ internal abstract class Setting<T, TControl> : Setting<T>
         : base(name)
         : base(name)
     {
     {
     }
     }
-
-    public new TControl SettingControl
-    {
-        get => (TControl)base.SettingControl;
-        set => base.SettingControl = value;
-    }
 }
 }
 
 
 internal abstract class Setting<T> : Setting
 internal abstract class Setting<T> : Setting
@@ -80,9 +74,5 @@ internal abstract class Setting : ObservableObject
 
 
     public bool HasLabel => !string.IsNullOrEmpty(Label);
     public bool HasLabel => !string.IsNullOrEmpty(Label);
 
 
-    public Control SettingControl { get; set; }
-
-    public abstract Control GenerateControl();
-
     public abstract Type GetSettingType();
     public abstract Type GetSettingType();
 }
 }

+ 0 - 40
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/SizeSetting.cs

@@ -1,40 +0,0 @@
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Data;
-using Avalonia.Layout;
-using PixiEditor.Views.Input;
-
-namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
-
-internal sealed class SizeSetting : Setting<int>
-{
-    public SizeSetting(string name, string label = null)
-        : base(name)
-    {
-        Label = label;
-        Value = 1;
-    }
-
-    private SizeInput GenerateTextBox()
-    {
-        SizeInput tb = new SizeInput
-        {
-            VerticalAlignment = VerticalAlignment.Center,
-            MaxSize = 9999,
-            IsEnabled = true,
-            FocusNext = false
-        };
-
-        Binding binding = new Binding("Value")
-        {
-            Mode = BindingMode.TwoWay,
-        };
-        tb.Bind(SizeInput.SizeProperty, binding);
-        return tb;
-    }
-
-    public override Control GenerateControl()
-    {
-        return GenerateTextBox();
-    }
-}

+ 27 - 0
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/SizeSettingViewModel.cs

@@ -0,0 +1,27 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Data;
+using Avalonia.Layout;
+using PixiEditor.Views.Input;
+
+namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
+
+internal sealed class SizeSettingViewModel : Setting<int>
+{
+    private bool isEnabled = true;
+    public SizeSettingViewModel(string name, string label = null)
+        : base(name)
+    {
+        Label = label;
+        Value = 1;
+    }
+
+    public bool IsEnabled
+    {
+        get => isEnabled;
+        set
+        {
+            SetProperty(ref isEnabled, value);
+        }
+    }
+}

+ 4 - 4
src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/BasicShapeToolbar.cs

@@ -6,12 +6,12 @@ namespace PixiEditor.ViewModels.Tools.ToolSettings.Toolbars;
 #nullable enable
 #nullable enable
 internal class BasicShapeToolbar : BasicToolbar, IBasicShapeToolbar
 internal class BasicShapeToolbar : BasicToolbar, IBasicShapeToolbar
 {
 {
-    public bool Fill => GetSetting<BoolSetting>(nameof(Fill)).Value;
-    public Color FillColor => GetSetting<ColorSetting>(nameof(FillColor)).Value;
+    public bool Fill => GetSetting<BoolSettingViewModel>(nameof(Fill)).Value;
+    public Color FillColor => GetSetting<ColorSettingViewModel>(nameof(FillColor)).Value;
 
 
     public BasicShapeToolbar()
     public BasicShapeToolbar()
     {
     {
-        Settings.Add(new BoolSetting(nameof(Fill), "FILL_SHAPE_LABEL"));
-        Settings.Add(new ColorSetting(nameof(FillColor), "FILL_COLOR_LABEL"));
+        Settings.Add(new BoolSettingViewModel(nameof(Fill), "FILL_SHAPE_LABEL"));
+        Settings.Add(new ColorSettingViewModel(nameof(FillColor), "FILL_COLOR_LABEL"));
     }
     }
 }
 }

+ 3 - 3
src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/BasicToolbar.cs

@@ -10,12 +10,12 @@ internal class BasicToolbar : Toolbar, IBasicToolbar
 {
 {
     public int ToolSize
     public int ToolSize
     {
     {
-        get => GetSetting<SizeSetting>(nameof(ToolSize)).Value;
-        set => GetSetting<SizeSetting>(nameof(ToolSize)).Value = value;
+        get => GetSetting<SizeSettingViewModel>(nameof(ToolSize)).Value;
+        set => GetSetting<SizeSettingViewModel>(nameof(ToolSize)).Value = value;
     }
     }
     public BasicToolbar()
     public BasicToolbar()
     {
     {
-        var setting = new SizeSetting(nameof(ToolSize), "TOOL_SIZE_LABEL");
+        var setting = new SizeSettingViewModel(nameof(ToolSize), "TOOL_SIZE_LABEL");
         setting.ValueChanged += (_, _) => OnPropertyChanged(nameof(ToolSize));
         setting.ValueChanged += (_, _) => OnPropertyChanged(nameof(ToolSize));
         Settings.Add(setting);
         Settings.Add(setting);
     }
     }

+ 0 - 11
src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/Toolbar.cs

@@ -12,17 +12,6 @@ internal abstract class Toolbar : ObservableObject, IToolbar
     private static readonly List<Setting> SharedSettings = new List<Setting>();
     private static readonly List<Setting> SharedSettings = new List<Setting>();
 
 
     public ObservableCollection<Setting> Settings { get; set; } = new ObservableCollection<Setting>();
     public ObservableCollection<Setting> Settings { get; set; } = new ObservableCollection<Setting>();
-    public bool SettingsGenerated { get; private set; }
-
-    public void GenerateSettings()
-    {
-        foreach (Setting setting in Settings)
-        {
-            setting.SettingControl = setting.GenerateControl();
-        }
-
-        SettingsGenerated = true;
-    }
 
 
     /// <summary>
     /// <summary>
     ///     Gets setting in toolbar by name.
     ///     Gets setting in toolbar by name.

+ 5 - 5
src/PixiEditor/ViewModels/Tools/ToolSettings/Toolbars/ToolbarFactory.cs

@@ -55,13 +55,13 @@ internal static class ToolbarFactory
     {
     {
         return attribute switch
         return attribute switch
         {
         {
-            Settings.BoolAttribute => new BoolSetting(name, (bool)(attribute.DefaultValue ?? false), label),
-            Settings.ColorAttribute => new ColorSetting(name,
+            Settings.BoolAttribute => new BoolSettingViewModel(name, (bool)(attribute.DefaultValue ?? false), label),
+            Settings.ColorAttribute => new ColorSettingViewModel(name,
                 ((Color)(attribute.DefaultValue ?? Colors.White)).ToColor(), label),
                 ((Color)(attribute.DefaultValue ?? Colors.White)).ToColor(), label),
             Settings.EnumAttribute => GetEnumSetting(propertyType, name, attribute),
             Settings.EnumAttribute => GetEnumSetting(propertyType, name, attribute),
-            Settings.FloatAttribute floatAttribute => new FloatSetting(name, (float)(attribute.DefaultValue ?? 0f), label,
+            Settings.FloatAttribute floatAttribute => new FloatSettingViewModel(name, (float)(attribute.DefaultValue ?? 0f), label,
                 floatAttribute.Min, floatAttribute.Max),
                 floatAttribute.Min, floatAttribute.Max),
-            Settings.SizeAttribute => new SizeSetting(name, label),
+            Settings.SizeAttribute => new SizeSettingViewModel(name, label),
             _ => throw new NotImplementedException(
             _ => throw new NotImplementedException(
                 $"SettingsAttribute of type '{attribute.GetType().FullName}' has not been implemented")
                 $"SettingsAttribute of type '{attribute.GetType().FullName}' has not been implemented")
         };
         };
@@ -97,7 +97,7 @@ internal static class ToolbarFactory
 
 
     private static Setting GetEnumSetting(Type enumType, string name, Settings.SettingsAttribute attribute)
     private static Setting GetEnumSetting(Type enumType, string name, Settings.SettingsAttribute attribute)
     {
     {
-        return (Setting)typeof(EnumSetting<>)
+        return (Setting)typeof(EnumSettingViewModel<>)
             .MakeGenericType(enumType)
             .MakeGenericType(enumType)
             .GetConstructor(new[] { typeof(string), typeof(string), enumType })!
             .GetConstructor(new[] { typeof(string), typeof(string), enumType })!
             .Invoke(new[] { name, attribute.LabelKey ?? name, attribute.DefaultValue });
             .Invoke(new[] { name, attribute.LabelKey ?? name, attribute.DefaultValue });

+ 5 - 5
src/PixiEditor/ViewModels/Tools/Tools/PenToolViewModel.cs

@@ -55,7 +55,7 @@ namespace PixiEditor.ViewModels.Tools.Tools
             if (e.NewTool == this && PixelPerfectEnabled)
             if (e.NewTool == this && PixelPerfectEnabled)
             {
             {
                 var toolbar = (BasicToolbar)Toolbar;
                 var toolbar = (BasicToolbar)Toolbar;
-                var setting = (SizeSetting)toolbar.Settings.First(x => x.Name == "ToolSize");
+                var setting = (SizeSettingViewModel)toolbar.Settings.First(x => x.Name == "ToolSize");
                 setting.Value = 1;
                 setting.Value = 1;
             }
             }
             
             
@@ -69,7 +69,7 @@ namespace PixiEditor.ViewModels.Tools.Tools
                 return;
                 return;
             }
             }
             
             
-            var oldSetting = (SizeSetting)oldToolbar.Settings[0];
+            var oldSetting = (SizeSettingViewModel)oldToolbar.Settings[0];
             actualToolSize = oldSetting.Value;
             actualToolSize = oldSetting.Value;
         }
         }
 
 
@@ -81,16 +81,16 @@ namespace PixiEditor.ViewModels.Tools.Tools
             }
             }
 
 
             var toolbar = (BasicToolbar)Toolbar;
             var toolbar = (BasicToolbar)Toolbar;
-            var setting = (SizeSetting)toolbar.Settings[0];
+            var setting = (SizeSettingViewModel)toolbar.Settings[0];
             setting.Value = actualToolSize;
             setting.Value = actualToolSize;
         }
         }
 
 
         private void PixelPerfectChanged()
         private void PixelPerfectChanged()
         {
         {
             var toolbar = (BasicToolbar)Toolbar;
             var toolbar = (BasicToolbar)Toolbar;
-            var setting = (SizeSetting)toolbar.Settings[0];
+            var setting = (SizeSettingViewModel)toolbar.Settings[0];
 
 
-            setting.SettingControl.IsEnabled = !PixelPerfectEnabled;
+            setting.IsEnabled = !PixelPerfectEnabled;
 
 
             if (PixelPerfectEnabled)
             if (PixelPerfectEnabled)
             {
             {

+ 1 - 1
src/PixiEditor/Views/Main/Tools/Toolbar.axaml

@@ -61,7 +61,7 @@
                             <Label
                             <Label
                                 IsVisible="{Binding HasLabel}" VerticalAlignment="Center"
                                 IsVisible="{Binding HasLabel}" VerticalAlignment="Center"
                                 Foreground="{DynamicResource ThemeForegroundBrush}" ui:Translator.Key="{Binding Label.Key}" />
                                 Foreground="{DynamicResource ThemeForegroundBrush}" ui:Translator.Key="{Binding Label.Key}" />
-                            <ContentControl VerticalAlignment="Center" Content="{Binding SettingControl}" />
+                            <ContentControl VerticalAlignment="Center" Content="{Binding }" />
                         </StackPanel>
                         </StackPanel>
                     </DataTemplate>
                     </DataTemplate>
                 </ItemsControl.ItemTemplate>
                 </ItemsControl.ItemTemplate>

+ 13 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/BoolSettingView.axaml

@@ -0,0 +1,13 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:settings="clr-namespace:PixiEditor.ViewModels.Tools.ToolSettings.Settings"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.Views.Tools.ToolSettings.Settings.BoolSettingView">
+    <Design.DataContext>
+        <settings:BoolSettingViewModel/>
+    </Design.DataContext>
+    
+    <CheckBox VerticalAlignment="Center" IsChecked="{Binding Value, Mode=TwoWay}"/>
+</UserControl>

+ 14 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/BoolSettingView.axaml.cs

@@ -0,0 +1,14 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.Views.Tools.ToolSettings.Settings;
+
+public partial class BoolSettingView : UserControl
+{
+    public BoolSettingView()
+    {
+        InitializeComponent();
+    }
+}
+

+ 19 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/ColorSettingView.axaml

@@ -0,0 +1,19 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:settings="clr-namespace:PixiEditor.ViewModels.Tools.ToolSettings.Settings"
+             xmlns:input="clr-namespace:PixiEditor.Views.Input"
+             xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.Views.Tools.ToolSettings.Settings.ColorSettingView">
+    <Design.DataContext>
+        <settings:ColorSettingViewModel/>
+    </Design.DataContext>
+    
+    <input:ToolSettingColorPicker SelectedColor="{Binding Value, Mode=TwoWay}">
+        <Interaction.Behaviors>
+            <behaviours:GlobalShortcutFocusBehavior/>
+        </Interaction.Behaviors>
+    </input:ToolSettingColorPicker>
+</UserControl>

+ 14 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/ColorSettingView.axaml.cs

@@ -0,0 +1,14 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.Views.Tools.ToolSettings.Settings;
+
+public partial class ColorSettingView : UserControl
+{
+    public ColorSettingView()
+    {
+        InitializeComponent();
+    }
+}
+

+ 26 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/EnumSettingView.axaml

@@ -0,0 +1,26 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:settings="clr-namespace:PixiEditor.ViewModels.Tools.ToolSettings.Settings"
+             xmlns:enums="clr-namespace:PixiEditor.ChangeableDocument.Enums;assembly=PixiEditor.ChangeableDocument"
+             xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
+             xmlns:helpers="clr-namespace:PixiEditor.Helpers"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.Views.Tools.ToolSettings.Settings.EnumSettingView">
+    <Design.DataContext>
+        <settings:EnumSettingViewModel x:TypeArguments="enums:BlendMode" />
+    </Design.DataContext>
+    
+    <ComboBox VerticalAlignment="Center"
+              MinWidth="85"
+              SelectedIndex="{Binding Value, Mode=TwoWay}" 
+              ItemsSource="{Binding EnumValues}">
+        <ComboBox.ItemContainerTheme>
+            <ControlTheme TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
+                <Setter Property="Tag" Value="{Binding .}"/>
+                <Setter Property="(ui:Translator.Key)" Value="{Binding ., Converter={helpers:EnumDescriptionConverter}}"/>
+            </ControlTheme>
+        </ComboBox.ItemContainerTheme>
+    </ComboBox>
+</UserControl>

+ 14 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/EnumSettingView.axaml.cs

@@ -0,0 +1,14 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.Views.Tools.ToolSettings.Settings;
+
+public partial class EnumSettingView : UserControl
+{
+    public EnumSettingView()
+    {
+        InitializeComponent();
+    }
+}
+

+ 18 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/FloatSettingView.axaml

@@ -0,0 +1,18 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:input="clr-namespace:PixiEditor.Views.Input"
+             xmlns:settings="clr-namespace:PixiEditor.ViewModels.Tools.ToolSettings.Settings"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.Views.Tools.ToolSettings.Settings.FloatSettingView">
+    <Design.DataContext>
+        <settings:FloatSettingViewModel/>
+    </Design.DataContext>
+    <input:NumberInput x:Name="NumberInput"
+                       Value="{Binding Value, Mode=TwoWay}"
+                       Min="{Binding Min}"
+                       Max="{Binding Max}"
+                       Margin="0,0,0,0" 
+                       Width="40" />
+</UserControl>

+ 14 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/FloatSettingView.axaml.cs

@@ -0,0 +1,14 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.Views.Tools.ToolSettings.Settings;
+
+public partial class FloatSettingView : UserControl
+{
+    public FloatSettingView()
+    {
+        InitializeComponent();
+    }
+}
+

+ 15 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/SizeSettingView.axaml

@@ -0,0 +1,15 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:settings="clr-namespace:PixiEditor.ViewModels.Tools.ToolSettings.Settings"
+             xmlns:input="clr-namespace:PixiEditor.Views.Input"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.Views.Tools.ToolSettings.Settings.SizeSettingView">
+    <Design.DataContext>
+        <settings:SizeSettingViewModel/>
+    </Design.DataContext>
+    
+    <input:SizeInput VerticalAlignment="Center" MaxSize="9999" IsEnabled="{Binding IsEnabled}" FocusNext="False"
+                     Size="{Binding Value, Mode=TwoWay}"/>
+</UserControl>

+ 14 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/SizeSettingView.axaml.cs

@@ -0,0 +1,14 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.Views.Tools.ToolSettings.Settings;
+
+public partial class SizeSettingView : UserControl
+{
+    public SizeSettingView()
+    {
+        InitializeComponent();
+    }
+}
+