瀏覽代碼

Added small color picker and color sliders

Krzysztof Krysiński 1 年之前
父節點
當前提交
585fe96abc

+ 0 - 5
src/PixiEditor.AvaloniaUI/Data/Localization/Languages/en.json

@@ -587,11 +587,6 @@
   "ADD_PRIMARY_COLOR_TO_PALETTE_DESCRIPTIVE": "Add primary color to current palette",
 
   "EXPORT_SAVE_TITLE": "Choose a location to save the image",
-  "COLOR_PICKER_DOCKABLE_TITLE": "Color Picker",
-  "LAYERS_DOCKABLE_TITLE": "Layers",
-  "NAVIGATOR_DOCKABLE_TITLE": "Navigator",
-  "SWATCHES_DOCKABLE_TITLE": "Swatches",
-    "PALETTE_DOCKABLE_TITLE": "Palette",
 
   "BROWSE_DIRECTORY": "Browse Directory",
   "CRASH_NOT_ALL_DOCUMENTS_RECOVERED_TITLE": "Not all documents were recovered",

+ 16 - 0
src/PixiEditor.AvaloniaUI/Helpers/Converters/FloorConverter.cs

@@ -0,0 +1,16 @@
+using System.Globalization;
+
+namespace PixiEditor.AvaloniaUI.Helpers.Converters;
+
+internal class FloorConverter : SingleInstanceConverter<FloorConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        return Math.Floor((double)value);
+    }
+
+    public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        return value;
+    }
+}

+ 18 - 0
src/PixiEditor.AvaloniaUI/Helpers/Converters/IntToPickerTypeConverter.cs

@@ -0,0 +1,18 @@
+using System.Globalization;
+using ColorPicker.Models;
+
+namespace PixiEditor.AvaloniaUI.Helpers.Converters;
+
+internal class IntToPickerTypeConverter
+    : SingleInstanceConverter<IntToPickerTypeConverter>
+{
+    public override object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        return (PickerType)value;
+    }
+
+    public override object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+    {
+        return (int)value;
+    }
+}

+ 1 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Dock/ColorPickerDockViewModel.cs

@@ -10,7 +10,7 @@ internal class ColorPickerDockViewModel : DockableViewModel
 {
     public const string TabId = "ColorPicker";
     public override string Id => TabId;
-    public override string Title => new LocalizedString("COLOR_PICKER_DOCKABLE_TITLE");
+    public override string Title => new LocalizedString("COLOR_PICKER_TITLE");
     public override bool CanFloat => true;
     public override bool CanClose => true;
 

+ 31 - 0
src/PixiEditor.AvaloniaUI/ViewModels/Dock/ColorSlidersDockViewModel.cs

@@ -0,0 +1,31 @@
+using Avalonia;
+using Avalonia.Media;
+using PixiEditor.AvaloniaUI.Helpers.Converters;
+using PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
+using PixiEditor.Extensions.Common.Localization;
+
+namespace PixiEditor.AvaloniaUI.ViewModels.Dock;
+
+internal class ColorSlidersDockViewModel : DockableViewModel
+{
+    public const string TabId = "ColorSliders";
+    public override string Id => TabId;
+    public override string Title => new LocalizedString("COLOR_SLIDERS_TITLE");
+    public override bool CanFloat => true;
+    public override bool CanClose => true;
+
+    private ColorsViewModel colorsSubViewModel;
+
+    public ColorsViewModel ColorsSubViewModel
+    {
+        get => colorsSubViewModel;
+        set => SetProperty(ref colorsSubViewModel, value);
+    }
+
+    public ColorSlidersDockViewModel(ColorsViewModel colorsSubVm)
+    {
+        ColorsSubViewModel = colorsSubVm;
+        TabCustomizationSettings.Icon =
+            ImagePathToBitmapConverter.TryLoadBitmapFromRelativePath("/Images/Dockables/ColorPicker.png");
+    }
+}

+ 1 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Dock/LayersDockViewModel.cs

@@ -10,7 +10,7 @@ internal class LayersDockViewModel : DockableViewModel
 {
     public const string TabId = "Layers";
     public override string Id => TabId;
-    public override string Title => new LocalizedString("LAYERS_DOCKABLE_TITLE");
+    public override string Title => new LocalizedString("LAYERS_TITLE");
     public override bool CanFloat => true;
     public override bool CanClose => true;
 

+ 3 - 0
src/PixiEditor.AvaloniaUI/ViewModels/Dock/LayoutManager.cs

@@ -32,12 +32,14 @@ internal class LayoutManager
     {
         LayersDockViewModel layersDockViewModel = new(mainViewModel.DocumentManagerSubViewModel);
         ColorPickerDockViewModel colorPickerDockViewModel = new(mainViewModel.ColorsSubViewModel);
+        ColorSlidersDockViewModel colorSldersDockViewModel = new(mainViewModel.ColorsSubViewModel);
         NavigationDockViewModel navigationDockViewModel = new(mainViewModel.ColorsSubViewModel, mainViewModel.DocumentManagerSubViewModel);
         SwatchesDockViewModel swatchesDockViewModel = new(mainViewModel.DocumentManagerSubViewModel);
         PaletteViewerDockViewModel paletteViewerDockViewModel = new(mainViewModel.ColorsSubViewModel, mainViewModel.DocumentManagerSubViewModel);
 
         RegisterDockable(layersDockViewModel);
         RegisterDockable(colorPickerDockViewModel);
+        RegisterDockable(colorSldersDockViewModel);
         RegisterDockable(navigationDockViewModel);
         RegisterDockable(swatchesDockViewModel);
         RegisterDockable(paletteViewerDockViewModel);
@@ -64,6 +66,7 @@ internal class LayoutManager
                             Dockables =
                             [
                                 DockContext.CreateDockable(colorPickerDockViewModel),
+                                DockContext.CreateDockable(colorSldersDockViewModel),
                                 DockContext.CreateDockable(swatchesDockViewModel),
                                 DockContext.CreateDockable(paletteViewerDockViewModel)
                             ]

+ 1 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Dock/NavigationDockViewModel.cs

@@ -11,7 +11,7 @@ internal class NavigationDockViewModel : DockableViewModel
     public const string TabId = "Navigator";
 
     public override string Id => TabId;
-    public override string Title => new LocalizedString("NAVIGATOR_DOCKABLE_TITLE");
+    public override string Title => new LocalizedString("NAVIGATION_TITLE");
     public override bool CanFloat => true;
     public override bool CanClose => true;
 

+ 2 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Dock/PaletteViewerDockViewModel.cs

@@ -1,13 +1,14 @@
 using PixiEditor.AvaloniaUI.Helpers.Converters;
 using PixiEditor.AvaloniaUI.ViewModels.Document;
 using PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
+using PixiEditor.Extensions.Common.Localization;
 
 namespace PixiEditor.AvaloniaUI.ViewModels.Dock;
 
 internal class PaletteViewerDockViewModel : DockableViewModel
 {
     public override string Id => "PaletteViewer";
-    public override string Title => "Palettes";
+    public override string Title => new LocalizedString("PALETTE_TITLE");
     public override bool CanFloat => true;
     public override bool CanClose => true;
 

+ 1 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Dock/SwatchesDockViewModel.cs

@@ -8,7 +8,7 @@ namespace PixiEditor.AvaloniaUI.ViewModels.Dock;
 internal class SwatchesDockViewModel : DockableViewModel
 {
     public override string Id => "Swatches";
-    public override string Title => new LocalizedString("SWATCHES_DOCKABLE_TITLE");
+    public override string Title => new LocalizedString("SWATCHES_TITLE");
     public override bool CanFloat => true;
     public override bool CanClose => true;
 

+ 16 - 2
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ColorsViewModel.cs

@@ -7,6 +7,7 @@ using Avalonia.Controls;
 using Avalonia.Controls.Primitives;
 using Avalonia.Input;
 using Avalonia.Media;
+using ColorPicker.Models;
 using CommunityToolkit.Mvvm.Input;
 using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.AvaloniaUI.Helpers.Extensions;
@@ -46,8 +47,20 @@ internal class ColorsViewModel : SubViewModel<ViewModelMain>, IColorsHandler
         (LocalPalettesFetcher)PaletteProvider.DataSources.FirstOrDefault(x => x is LocalPalettesFetcher)!;
 
     private Color primaryColor = Colors.Black;
+    private Color secondaryColor = Colors.White;
+    private ColorState primaryColorState;
     private LocalPalettesFetcher _localPaletteFetcher;
 
+    public ColorState PrimaryColorState
+    {
+        get => primaryColorState;
+        set
+        {
+            primaryColorState = value;
+            OnPropertyChanged(nameof(PrimaryColorState));
+        }
+    }
+
     public Color PrimaryColor // Primary color, hooked with left mouse button
     {
         get => primaryColor;
@@ -61,8 +74,6 @@ internal class ColorsViewModel : SubViewModel<ViewModelMain>, IColorsHandler
         }
     }
 
-    private Color secondaryColor = Colors.White;
-
     public Color SecondaryColor
     {
         get => secondaryColor;
@@ -79,6 +90,9 @@ internal class ColorsViewModel : SubViewModel<ViewModelMain>, IColorsHandler
     public ColorsViewModel(ViewModelMain owner)
         : base(owner)
     {
+        primaryColorState = new ColorState();
+        primaryColorState.SetARGB(PrimaryColor.A, PrimaryColor.R, PrimaryColor.G, PrimaryColor.B);
+
         ImportPaletteCommand = new AsyncRelayCommand<List<PaletteColor>>(ImportPalette, CanImportPalette);
         Owner.OnStartupEvent += OwnerOnStartupEvent;
     }

+ 4 - 1
src/PixiEditor.AvaloniaUI/Views/Dock/ColorPickerDockView.axaml

@@ -6,14 +6,17 @@
              xmlns:converters="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Converters"
              xmlns:subViewModels="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.SubViewModels"
              xmlns:dock="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.Dock"
+             xmlns:input="clr-namespace:PixiEditor.AvaloniaUI.Views.Input"
              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
              x:DataType="dock:ColorPickerDockViewModel"
              x:Class="PixiEditor.AvaloniaUI.Views.Dock.ColorPickerDockView">
     <Design.DataContext>
         <dock:ColorPickerDockViewModel/>
     </Design.DataContext>
-    <colorPicker:StandardColorPicker
+
+    <input:SmallColorPicker
         SelectedColor="{Binding ColorsSubViewModel.PrimaryColor, Mode=TwoWay, Converter={converters:GenericColorToMediaColorConverter}}"
         SecondaryColor="{Binding ColorsSubViewModel.SecondaryColor, Mode=TwoWay, Converter={converters:GenericColorToMediaColorConverter}}"
+        ColorState="{Binding ColorsSubViewModel.PrimaryColorState, Mode=TwoWay}"
         UseHintColor="False"/>
 </UserControl>

+ 15 - 0
src/PixiEditor.AvaloniaUI/Views/Dock/ColorSlidersDockView.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:dock="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.Dock"
+             xmlns:colorPicker="clr-namespace:ColorPicker;assembly=ColorPicker.AvaloniaUI"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.AvaloniaUI.Views.Dock.ColorSlidersDockView" x:DataType="dock:ColorSlidersDockViewModel">
+    <Design.DataContext>
+        <dock:ColorSlidersDockViewModel/>
+    </Design.DataContext>
+
+    <colorPicker:ColorSliders ColorState="{Binding Path=ColorsSubViewModel.PrimaryColorState, Mode=TwoWay}"/>
+
+</UserControl>

+ 14 - 0
src/PixiEditor.AvaloniaUI/Views/Dock/ColorSlidersDockView.axaml.cs

@@ -0,0 +1,14 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.AvaloniaUI.Views.Dock;
+
+public partial class ColorSlidersDockView : UserControl
+{
+    public ColorSlidersDockView()
+    {
+        InitializeComponent();
+    }
+}
+

+ 70 - 0
src/PixiEditor.AvaloniaUI/Views/Input/SmallColorPicker.axaml

@@ -0,0 +1,70 @@
+<colorPicker:DualPickerControlBase 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:converters="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Converters"
+                                   xmlns:input="clr-namespace:PixiEditor.AvaloniaUI.Views.Input"
+                                   xmlns:colorPicker="clr-namespace:ColorPicker;assembly=ColorPicker.AvaloniaUI"
+                                   x:Class="PixiEditor.AvaloniaUI.Views.Input.SmallColorPicker"
+                                   x:ClassModifier="internal"
+                                   mc:Ignorable="d"
+                                   d:DesignHeight="380"
+                                   d:DesignWidth="270"
+                                   MaxWidth="400">
+    <colorPicker:DualPickerControlBase.Template>
+        <ControlTemplate TargetType="input:SmallColorPicker">
+            <Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
+                <colorPicker:StandardColorPicker ColorState="{Binding Path=ColorState, Mode=TwoWay}"
+                                                 SecondColorState="{Binding  Path=SecondColorState, Mode=TwoWay}"
+                                                 IsVisible="{Binding  Path=Bounds.Height, Converter={converters:ThresholdVisibilityConverter CheckIfLess=False, Threshold=380}}"
+                                                 x:Name="mainColorPicker" />
+                <Grid
+                    IsVisible="{Binding  Path=Bounds.Height, Converter={converters:ThresholdVisibilityConverter CheckIfLess=True, Threshold=380}}">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition MaxWidth="80" Width="1*" />
+                        <ColumnDefinition Width="3*" />
+                    </Grid.ColumnDefinitions>
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="8*" />
+                        <RowDefinition Height="2*" />
+                        <RowDefinition Height="1.2*" />
+                        <RowDefinition Height="25" />
+                    </Grid.RowDefinitions>
+                    <colorPicker:SquarePicker Grid.ColumnSpan="2" Grid.RowSpan="2" Margin="3"
+                                              x:Name="mainPicker"
+                                              ColorState="{Binding ColorState, Mode=TwoWay}"
+                                              PickerType="{Binding ElementName=colorSpaceComboBox, Path=SelectedIndex, Converter={converters:IntToPickerTypeConverter}}" />
+                    <colorPicker:ColorDisplay Grid.Row="1" Grid.RowSpan="2" HorizontalAlignment="Stretch"
+                                              VerticalAlignment="Stretch" Margin="3,0,0,0"
+                                              ColorState="{Binding ColorState, Mode=TwoWay, ElementName=mainPicker}"
+                                              SecondColorState="{Binding SecondColorState, Mode=TwoWay}" />
+                    <ComboBox Grid.Row="1" Grid.RowSpan="2" SelectedIndex="0" Grid.Column="2"
+                              HorizontalAlignment="Right"
+                              VerticalAlignment="Bottom" x:Name="colorSpaceComboBox" Margin="0,0,90,0">
+                        <ComboBoxItem>HSV</ComboBoxItem>
+                        <ComboBoxItem>HSL</ComboBoxItem>
+                    </ComboBox>
+                    <colorPicker:HexColorTextBox Grid.Row="1" Grid.RowSpan="2" Grid.Column="2" Margin="0,0,3,0"
+                                                 HorizontalAlignment="Right" VerticalAlignment="Bottom"
+                                                 ColorState="{Binding ColorState, Mode=TwoWay}" />
+                    <Grid Grid.Row="3" Grid.ColumnSpan="2">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="25" />
+                            <ColumnDefinition />
+                            <ColumnDefinition Width="50" />
+                        </Grid.ColumnDefinitions>
+                        <Label VerticalAlignment="Center" Margin="3,0,0,0">A:</Label>
+                        <colorPicker:AlphaSlider Margin="5,0" Grid.Column="1" VerticalAlignment="Center"
+                                                 ColorState="{Binding ColorState, Mode=TwoWay}" />
+                        <input:NumberInput
+                            Grid.Column="2" HorizontalAlignment="Right" Margin="5,0"
+                            Min="0" Max="255"
+                            Width="40"
+                            VerticalAlignment="Center"
+                            Value="{Binding Path=Color.A, Mode=TwoWay, Converter={converters:FloorConverter}}" />
+                    </Grid>
+                </Grid>
+            </Grid>
+        </ControlTemplate>
+    </colorPicker:DualPickerControlBase.Template>
+</colorPicker:DualPickerControlBase>

+ 15 - 0
src/PixiEditor.AvaloniaUI/Views/Input/SmallColorPicker.axaml.cs

@@ -0,0 +1,15 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+using ColorPicker;
+
+namespace PixiEditor.AvaloniaUI.Views.Input;
+
+internal partial class SmallColorPicker : DualPickerControlBase
+{
+    public SmallColorPicker()
+    {
+        InitializeComponent();
+    }
+}
+