Forráskód Böngészése

Added guide manager

CPKreuz 2 éve
szülő
commit
ffaf2321eb

+ 1 - 0
src/PixiEditor/Helpers/Extensions/ServiceCollectionHelpers.cs

@@ -41,6 +41,7 @@ internal static class ServiceCollectionHelpers
         .AddSingleton(static x => new DiscordViewModel(x.GetService<ViewModelMain>(), "764168193685979138"))
         .AddSingleton<DebugViewModel>()
         .AddSingleton<SearchViewModel>()
+        .AddSingleton<GuidesViewModel>()
         // Controllers
         .AddSingleton<ShortcutController>()
         .AddSingleton<CommandController>()

BIN
src/PixiEditor/Images/Guides/LineGuide.png


+ 10 - 0
src/PixiEditor/Models/DataHolders/Guides/Guide.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using System.Windows.Controls;
 using System.Windows.Media;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.ViewModels.SubViewModels.Document;
@@ -27,6 +28,7 @@ namespace PixiEditor.Models.DataHolders.Guides
                 if (SetProperty(ref name, value))
                 {
                     InvalidateVisual();
+                    RaisePropertyChanged(nameof(DisplayName));
                 }
             }
         }
@@ -67,6 +69,14 @@ namespace PixiEditor.Models.DataHolders.Guides
             }
         }
 
+        public abstract Control SettingsControl { get; }
+
+        public abstract string TypeNameKey { get; }
+
+        public virtual string IconPath => $"/Images/Guides/{GetType().Name}.png";
+
+        public string DisplayName => !string.IsNullOrWhiteSpace(Name) ? Name : TypeNameKey;
+
         protected IReadOnlyCollection<GuideRenderer> Renderers => renderers;
 
         public DocumentViewModel Document { get; }

+ 6 - 0
src/PixiEditor/Models/DataHolders/Guides/LineGuide.cs

@@ -4,6 +4,7 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
+using System.Windows.Controls;
 using System.Windows.Media;
 using Hardware.Info;
 using PixiEditor.DrawingApi.Core.Numerics;
@@ -55,9 +56,14 @@ namespace PixiEditor.Models.DataHolders.Guides
             }
         }
 
+        public override string TypeNameKey => "LINE_GUIDE";
+
+        public override Control SettingsControl { get; }
+
         public LineGuide(DocumentViewModel document) : base(document)
         {
             Color = Colors.CadetBlue;
+            SettingsControl = new LineGuideSettings(this);
         }
 
         public override void Draw(DrawingContext context, GuideRenderer renderer)

+ 2 - 0
src/PixiEditor/PixiEditor.csproj

@@ -191,6 +191,7 @@
 		<None Remove="Images\Folder-add.png" />
 		<None Remove="Images\Folder.png" />
 		<None Remove="Images\Globe.png" />
+		<None Remove="Images\Guides\LineGuide.png" />
 		<None Remove="Images\hard-drive.png" />
 		<None Remove="Images\Layer-add.png" />
 		<None Remove="Images\Lock-alpha.png" />
@@ -287,6 +288,7 @@
 		<Resource Include="Images\Folder-add.png" />
 		<Resource Include="Images\Folder.png" />
 		<Resource Include="Images\Globe.png" />
+		<Resource Include="Images\Guides\LineGuide.png" />
 		<Resource Include="Images\hard-drive.png" />
 		<Resource Include="Images\LanguageFlags\uk.png" />
 		<Resource Include="Images\Layer-add.png" />

+ 0 - 5
src/PixiEditor/ViewModels/SubViewModels/Document/DocumentViewModel.cs

@@ -182,11 +182,6 @@ internal partial class DocumentViewModel : NotifyableObject
         PreviewSurface = DrawingSurface.Create(new ImageInfo(previewSize.X, previewSize.Y, ColorType.Bgra8888), PreviewBitmap.BackBuffer, PreviewBitmap.BackBufferStride);
 
         ReferenceLayerViewModel = new(this, Internals);
-        Guides.Add(new LineGuide(this)
-        {
-            Position = new VecD(16, 16),
-            Rotation = Math.PI / 4
-        });
     }
 
     /// <summary>

+ 45 - 0
src/PixiEditor/ViewModels/SubViewModels/Main/GuidesViewModel.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using PixiEditor.Models.Commands.Attributes.Commands;
+using PixiEditor.Models.DataHolders.Guides;
+using PixiEditor.Views.Dialogs.Guides;
+
+namespace PixiEditor.ViewModels.SubViewModels.Main;
+
+internal class GuidesViewModel : SubViewModel<ViewModelMain>
+{
+    private GuidesManager guideManager;
+
+    public GuidesViewModel(ViewModelMain owner) : base(owner)
+    { }
+
+    [Command.Basic("PixiEditor.Guides.OpenManager", "OPEN_GUIDES_MANAGER", "OPEN_GUIDES_MANAGER_DESCRIPTIVE")]
+    public void OpenGuideManager(Index openAt)
+    {
+        if (guideManager == null)
+        {
+            guideManager = new GuidesManager();
+        }
+
+        guideManager.Show();
+        guideManager.Activate();
+    }
+
+    [Command.Basic("PixiEditor.Guides.AddLineGuide", "ADD_LINE_GUIDE", "ADD_LINE_GUIDE_DESCRIPTIVE", CanExecute = "PixiEditor.HasDocument")]
+    public void AddLineGuide()
+    {
+        var document = Owner.DocumentManagerSubViewModel.ActiveDocument;
+
+        var guide = new LineGuide(document)
+        {
+            Position = document.SizeBindable / 2,
+            Rotation = Math.PI / 4
+        };
+
+        document.Guides.Add(guide);
+        OpenGuideManager(^0);
+    }
+}

+ 3 - 0
src/PixiEditor/ViewModels/ViewModelMain.cs

@@ -50,6 +50,8 @@ internal class ViewModelMain : ViewModelBase
 
     public ViewOptionsViewModel ViewportSubViewModel { get; set; }
 
+    public GuidesViewModel GuidesSubViewModel { get; set; }
+
     public ColorsViewModel ColorsSubViewModel { get; set; }
 
     public MiscViewModel MiscSubViewModel { get; set; }
@@ -128,6 +130,7 @@ internal class ViewModelMain : ViewModelBase
         ClipboardSubViewModel = services.GetService<ClipboardViewModel>();
         UndoSubViewModel = services.GetService<UndoViewModel>();
         ViewportSubViewModel = services.GetService<ViewOptionsViewModel>();
+        GuidesSubViewModel = services.GetService<GuidesViewModel>();
         ColorsSubViewModel = services.GetService<ColorsViewModel>();
         ColorsSubViewModel?.SetupPaletteParsers(services);
 

+ 116 - 0
src/PixiEditor/Views/Dialogs/Guides/GuidesManager.xaml

@@ -0,0 +1,116 @@
+<Window x:Class="PixiEditor.Views.Dialogs.Guides.GuidesManager"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        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:dialogs="clr-namespace:PixiEditor.Views.Dialogs"
+        xmlns:views="clr-namespace:PixiEditor.Views"
+        xmlns:gModels="clr-namespace:PixiEditor.Models.DataHolders.Guides"
+        xmlns:local="clr-namespace:PixiEditor.Views.Dialogs.Guides"
+        xmlns:vm="clr-namespace:PixiEditor.ViewModels"
+        xmlns:cmds="clr-namespace:PixiEditor.Models.Commands.XAML"
+        mc:Ignorable="d"
+        views:Translator.Key="GUIDES_MANAGER_TITLE"
+        Width="800" Height="450"
+        MinWidth="250" MinHeight="450"
+        Background="{StaticResource AccentColor}"
+        Foreground="White">
+
+    <WindowChrome.WindowChrome>
+        <WindowChrome CaptionHeight="32"  GlassFrameThickness="0.1"
+                      ResizeBorderThickness="{x:Static SystemParameters.WindowResizeBorderThickness}" />
+    </WindowChrome.WindowChrome>
+
+    <Window.CommandBindings>
+        <CommandBinding Command="{x:Static SystemCommands.CloseWindowCommand}" CanExecute="CommandBinding_CanExecute"
+                        Executed="CommandBinding_Executed_Close" />
+    </Window.CommandBindings>
+
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="35"/>
+            <RowDefinition/>
+        </Grid.RowDefinitions>
+        
+        <dialogs:DialogTitleBar TitleKey="GUIDES_MANAGER_TITLE" CloseCommand="{x:Static SystemCommands.CloseWindowCommand}"/>
+        <Grid Grid.Row="1">
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="250"/>
+                <ColumnDefinition/>
+            </Grid.ColumnDefinitions>
+
+            <Border Margin="20" Background="{StaticResource DarkerAccentColor}" CornerRadius="5" BorderThickness="1" BorderBrush="{StaticResource MainColor}">
+                <Grid>
+                    <Grid.RowDefinitions>
+                        <RowDefinition/>
+                        <RowDefinition Height="25"/>
+                    </Grid.RowDefinitions>
+
+                    <ListView ItemsSource="{Binding ActiveDocument.Guides, Source={vm:MainVM DocumentManagerSVM}}" Margin="0,5"
+                              Background="Transparent" BorderThickness="0" x:Name="guideList">
+                        <ListView.ItemContainerStyle>
+                            <Style TargetType="ListViewItem">
+                                <Setter Property="BorderBrush" Value="Transparent" />
+                                <Setter Property="Background" Value="Transparent"/>
+                                <Setter Property="Foreground" Value="White"/>
+                                <Setter Property="Template">
+                                    <Setter.Value>
+                                        <ControlTemplate TargetType="ListViewItem">
+                                            <Border x:Name="border"
+                                                Background="{TemplateBinding Background}"
+                                                BorderBrush="Transparent"
+                                                BorderThickness="0,1.5">
+                                                <ContentPresenter />
+                                            </Border>
+                                            <ControlTemplate.Triggers>
+                                                <Trigger Property="IsMouseOver" Value="True">
+                                                    <Setter TargetName="border" Property="Background" Value="{StaticResource MainColor}" />
+                                                    <Setter TargetName="border" Property="BorderBrush" Value="{StaticResource MainColor}" />
+                                                </Trigger>
+                                                <Trigger Property="IsSelected" Value="True">
+                                                    <Setter TargetName="border" Property="Background" Value="{StaticResource MainColor}" />
+                                                    <Setter TargetName="border" Property="BorderBrush" Value="{StaticResource BrighterAccentColor}" />
+                                                </Trigger>
+                                                <MultiTrigger>
+                                                    <MultiTrigger.Conditions>
+                                                        <Condition Property="IsMouseOver" Value="True"/>
+                                                        <Condition Property="IsSelected" Value="True"/>
+                                                    </MultiTrigger.Conditions>
+                                                    <Setter TargetName="border" Property="Background" Value="{StaticResource BrighterAccentColor}"/>
+                                                </MultiTrigger>
+                                            </ControlTemplate.Triggers>
+                                        </ControlTemplate>
+                                    </Setter.Value>
+                                </Setter>
+                            </Style>
+                        </ListView.ItemContainerStyle>
+                        <ListView.ItemTemplate>
+                            <DataTemplate DataType="{x:Type gModels:Guide}">
+                                <Grid Height="15" Margin="5">
+                                    <Grid.ColumnDefinitions>
+                                        <ColumnDefinition Width="Auto"/>
+                                        <ColumnDefinition/>
+                                        <ColumnDefinition Width="Auto"/>
+                                    </Grid.ColumnDefinitions>
+
+                                    <Image Source="{Binding IconPath}"/>
+                                    <TextBlock Grid.Column="1" Text="{Binding DisplayName}" Margin="5,0,0,0"/>
+                                    <StackPanel Grid.Column="2"></StackPanel>
+                                </Grid>
+                            </DataTemplate>
+                        </ListView.ItemTemplate>
+                    </ListView>
+
+                    <Border Grid.Row="1" BorderThickness="0,1,0,0" BorderBrush="{StaticResource MainColor}">
+                        <DockPanel>
+                            <Button DockPanel.Dock="Left" Width="25"
+                                    Background="Transparent" Foreground="White"
+                                    Command="{cmds:Command PixiEditor.Guides.AddLineGuide}">LG</Button>
+                        </DockPanel>
+                    </Border>
+                </Grid>
+            </Border>
+            <ContentPresenter Margin="20" Grid.Column="1" Content="{Binding SelectedItem.SettingsControl, ElementName=guideList}"/>
+        </Grid>
+    </Grid>
+</Window>

+ 35 - 0
src/PixiEditor/Views/Dialogs/Guides/GuidesManager.xaml.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace PixiEditor.Views.Dialogs.Guides;
+/// <summary>
+/// Interaction logic for GuideManager.xaml
+/// </summary>
+public partial class GuidesManager : Window
+{
+    public GuidesManager()
+    {
+        InitializeComponent();
+    }
+
+    private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
+    {
+        e.CanExecute = true;
+    }
+
+    private void CommandBinding_Executed_Close(object sender, ExecutedRoutedEventArgs e)
+    {
+        Hide();
+    }
+}

+ 2 - 2
src/PixiEditor/Views/UserControls/Guides/GuideRenderer.cs

@@ -50,12 +50,12 @@ namespace PixiEditor.Views.UserControls.Guides
 
             if (e.OldValue is Guide oldGuide)
             {
-                oldGuide.AttachRenderer(renderer);
+                oldGuide.DetachRenderer(renderer);
             }
 
             if (e.NewValue is Guide newGuide)
             {
-                newGuide.DetachRenderer(renderer);
+                newGuide.AttachRenderer(renderer);
             }
         }
     }

+ 27 - 0
src/PixiEditor/Views/UserControls/Guides/LineGuideSettings.xaml

@@ -0,0 +1,27 @@
+<UserControl x:Class="PixiEditor.Views.UserControls.Guides.LineGuideSettings"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:gModels="clr-namespace:PixiEditor.Models.DataHolders.Guides"
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls.Guides"
+             xmlns:colorpicker="clr-namespace:ColorPicker;assembly=ColorPicker"
+             xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:uc="clr-namespace:PixiEditor.Views.UserControls"
+             mc:Ignorable="d" 
+             d:DesignHeight="450" d:DesignWidth="800">
+    <StackPanel>
+        <TextBox Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+                 Style="{StaticResource DarkTextBoxStyle}">
+            <i:Interaction.Behaviors>
+                <behaviors:GlobalShortcutFocusBehavior/>
+                <behaviors:TextBoxFocusBehavior 
+                        SelectOnMouseClick="{Binding BehaveLikeSmallEmbeddedField, ElementName=uc}" 
+                        ConfirmOnEnter="{Binding BehaveLikeSmallEmbeddedField, ElementName=uc}"
+                        DeselectOnFocusLoss="True"/>
+            </i:Interaction.Behaviors>
+        </TextBox>
+        <colorpicker:PortableColorPicker SelectedColor="{Binding Color, Mode=TwoWay}" Width="40" Height="25"/>
+        <uc:NumberInput Value="{Binding Rotation, Mode=TwoWay}"/>
+    </StackPanel>
+</UserControl>

+ 28 - 0
src/PixiEditor/Views/UserControls/Guides/LineGuideSettings.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using PixiEditor.Models.DataHolders.Guides;
+
+namespace PixiEditor.Views.UserControls.Guides;
+/// <summary>
+/// Interaction logic for LineGuideSettings.xaml
+/// </summary>
+public partial class LineGuideSettings : UserControl
+{
+    internal LineGuideSettings(LineGuide guide)
+    {
+        DataContext = guide;
+        InitializeComponent();
+    }
+}