Browse Source

Resize canvas anchors

Equbuxu 3 years ago
parent
commit
d5115d79ef

+ 10 - 1
src/PixiEditor.ChangeableDocument/Changes/Root/ResizeCanvas_Change.cs

@@ -1,4 +1,5 @@
 using PixiEditor.ChangeableDocument.ChangeInfos.Root;
+using PixiEditor.ChangeableDocument.Enums;
 
 namespace PixiEditor.ChangeableDocument.Changes.Root;
 
@@ -10,12 +11,15 @@ internal class ResizeCanvas_Change : Change
     private Dictionary<Guid, CommittedChunkStorage> deletedChunks = new();
     private Dictionary<Guid, CommittedChunkStorage> deletedMaskChunks = new();
     private VecI newSize;
+    private readonly ResizeAnchor anchor;
 
     [GenerateMakeChangeAction]
-    public ResizeCanvas_Change(VecI size)
+    public ResizeCanvas_Change(VecI size, ResizeAnchor anchor)
     {
         newSize = size;
+        this.anchor = anchor;
     }
+
     public override OneOf<Success, Error> InitializeAndValidate(Document target)
     {
         if (target.Size == newSize)
@@ -48,6 +52,9 @@ internal class ResizeCanvas_Change : Change
         ForEachLayer(target.StructureRoot, (layer) =>
         {
             layer.LayerImage.EnqueueResize(newSize);
+            layer.LayerImage.EnqueueClear();
+            layer.LayerImage.EnqueueDrawChunkyImage(anchor.FindOffsetFor(originalSize, newSize), layer.LayerImage);
+
             deletedChunks.Add(layer.GuidValue, new CommittedChunkStorage(layer.LayerImage, layer.LayerImage.FindAffectedChunks()));
             layer.LayerImage.CommitChanges();
 
@@ -55,6 +62,8 @@ internal class ResizeCanvas_Change : Change
                 return;
 
             layer.Mask.EnqueueResize(newSize);
+            layer.Mask.EnqueueClear();
+            layer.Mask.EnqueueDrawChunkyImage(anchor.FindOffsetFor(originalSize, newSize), layer.Mask);
             deletedMaskChunks.Add(layer.GuidValue, new CommittedChunkStorage(layer.Mask, layer.Mask.FindAffectedChunks()));
             layer.Mask.CommitChanges();
         });

+ 14 - 0
src/PixiEditor.ChangeableDocument/Enums/ResizeAnchor.cs

@@ -0,0 +1,14 @@
+namespace PixiEditor.ChangeableDocument.Enums;
+
+public enum ResizeAnchor
+{
+    TopLeft,
+    Top,
+    TopRight,
+    Left,
+    Center,
+    Right,
+    BottomLeft,
+    Bottom,
+    BottomRight
+}

+ 23 - 0
src/PixiEditor.ChangeableDocument/Enums/ResizeAnchorEx.cs

@@ -0,0 +1,23 @@
+namespace PixiEditor.ChangeableDocument.Enums;
+
+internal static class ResizeAnchorEx
+{
+    public static VecI FindOffsetFor(this ResizeAnchor anchor, VecI imageSize, VecI newImageSize)
+    {
+        VecI centerOffset = -(VecI)(imageSize / 2f - newImageSize / 2f).Round();
+        VecI botRightOffset = newImageSize - imageSize;
+        return anchor switch
+        {
+            ResizeAnchor.TopLeft => VecI.Zero,
+            ResizeAnchor.Top => new(centerOffset.X, 0),
+            ResizeAnchor.TopRight => new(botRightOffset.X, 0),
+            ResizeAnchor.Left => new(0, centerOffset.Y),
+            ResizeAnchor.Center => centerOffset,
+            ResizeAnchor.Right => new(botRightOffset.X, centerOffset.Y),
+            ResizeAnchor.BottomLeft => new(0, botRightOffset.Y),
+            ResizeAnchor.Bottom => new(centerOffset.X, botRightOffset.Y),
+            ResizeAnchor.BottomRight => botRightOffset,
+            _ => throw new ArgumentOutOfRangeException(nameof(anchor), anchor, null)
+        };
+    }
+}

+ 2 - 2
src/PixiEditorPrototype/ViewModels/DocumentViewModel.cs

@@ -220,7 +220,7 @@ internal class DocumentViewModel : INotifyPropertyChanged
     {
         DocumentViewModel document = new DocumentViewModel(owner, name);
         var acc = document.Helpers.ActionAccumulator;
-        acc.AddActions(new ResizeCanvas_Action(new(serDocument.Width, serDocument.Height)));
+        acc.AddActions(new ResizeCanvas_Action(new(serDocument.Width, serDocument.Height), ResizeAnchor.TopLeft));
         int index = 0;
         foreach (var layer in serDocument.Layers.Reverse())
         {
@@ -669,7 +669,7 @@ internal class DocumentViewModel : INotifyPropertyChanged
     {
         if (updateableChangeActive)
             return;
-        Helpers.ActionAccumulator.AddFinishedActions(new ResizeCanvas_Action(new(ResizeWidth, ResizeHeight)));
+        Helpers.ActionAccumulator.AddFinishedActions(new ResizeCanvas_Action(new(ResizeWidth, ResizeHeight), owner.ResizeAnchor));
     }
 
     private void CreateMask(object? param)

+ 11 - 0
src/PixiEditorPrototype/ViewModels/ViewModelMain.cs

@@ -7,6 +7,7 @@ using System.Windows.Input;
 using System.Windows.Media;
 using ChunkyImageLib.DataHolders;
 using Microsoft.Win32;
+using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.Parser;
 using PixiEditor.Zoombox;
 using PixiEditorPrototype.Models;
@@ -24,6 +25,7 @@ internal class ViewModelMain : INotifyPropertyChanged
     public RelayCommand MouseUpCommand { get; }
     public RelayCommand ChangeActiveToolCommand { get; }
     public RelayCommand SetSelectionModeCommand { get; }
+    public RelayCommand SetResizeAnchorCommand { get; }
     public RelayCommand LoadDocumentCommand { get; }
 
     public Color SelectedColor { get; set; } = Colors.Black;
@@ -91,6 +93,7 @@ internal class ViewModelMain : INotifyPropertyChanged
 
     private Tool activeTool = Tool.Rectangle;
     private SelectionMode selectionMode = SelectionMode.New;
+    public ResizeAnchor ResizeAnchor { get; private set; } = ResizeAnchor.TopLeft;
 
     private Tool toolOnMouseDown = Tool.Rectangle;
 
@@ -101,11 +104,19 @@ internal class ViewModelMain : INotifyPropertyChanged
         MouseUpCommand = new RelayCommand(MouseUp);
         ChangeActiveToolCommand = new RelayCommand(ChangeActiveTool);
         SetSelectionModeCommand = new RelayCommand(SetSelectionMode);
+        SetResizeAnchorCommand = new RelayCommand(SetResizeAnchor);
         LoadDocumentCommand = new RelayCommand(LoadDocument);
 
         Documents.Add(new DocumentViewModel(this, "New Artwork"));
     }
 
+    private void SetResizeAnchor(object? obj)
+    {
+        if (obj is not ResizeAnchor anchor)
+            return;
+        ResizeAnchor = anchor;
+    }
+
     private void SetSelectionMode(object? obj)
     {
         if (obj is not SelectionMode mode)

+ 51 - 0
src/PixiEditorPrototype/Views/MainWindow.xaml

@@ -470,6 +470,57 @@
                             </i:EventTrigger>
                         </i:Interaction.Triggers>
                     </ComboBox>
+                    <ComboBox
+                        Width="70"
+                        Height="20"
+                        Margin="5"
+                        SelectedIndex="0"
+                        x:Name="resizeAnchorComboBox">
+                        <ComboBoxItem
+                            Tag="{x:Static chen:ResizeAnchor.TopLeft}">
+                            Top Left
+                        </ComboBoxItem>
+                        <ComboBoxItem
+                            Tag="{x:Static chen:ResizeAnchor.Top}">
+                            Top
+                        </ComboBoxItem>
+                        <ComboBoxItem
+                            Tag="{x:Static chen:ResizeAnchor.TopRight}">
+                            Top Right
+                        </ComboBoxItem>
+                        <ComboBoxItem
+                            Tag="{x:Static chen:ResizeAnchor.Left}">
+                            Left
+                        </ComboBoxItem>
+                        <ComboBoxItem
+                            Tag="{x:Static chen:ResizeAnchor.Center}">
+                            Center
+                        </ComboBoxItem>
+                        <ComboBoxItem
+                            Tag="{x:Static chen:ResizeAnchor.Right}">
+                            Right
+                        </ComboBoxItem>
+                        <ComboBoxItem
+                            Tag="{x:Static chen:ResizeAnchor.BottomLeft}">
+                            Bottom Left
+                        </ComboBoxItem>
+                        <ComboBoxItem
+                            Tag="{x:Static chen:ResizeAnchor.Bottom}">
+                            Bottom
+                        </ComboBoxItem>
+                        <ComboBoxItem
+                            Tag="{x:Static chen:ResizeAnchor.BottomRight}">
+                            Bottom Right
+                        </ComboBoxItem>
+                        <i:Interaction.Triggers>
+                            <i:EventTrigger
+                                EventName="SelectionChanged">
+                                <i:InvokeCommandAction
+                                    Command="{Binding SetResizeAnchorCommand}"
+                                    CommandParameter="{Binding SelectedItem.Tag, ElementName=resizeAnchorComboBox}" />
+                            </i:EventTrigger>
+                        </i:Interaction.Triggers>
+                    </ComboBox>
                     <Button
                         Width="120"
                         Margin="5"

+ 1 - 1
src/README.md

@@ -88,7 +88,7 @@ Decouples the state of a document from the UI.
         - [x] Layer/Folder Blend Modes
         - [ ] Layer/Folder locking
         - [ ] Reference layer manipulation?
-        - [ ] Resize canvas (basic done, anchors left)
+        - [x] Resize canvas
         - [ ] Resize image
         - [x] Paste image with transformation
         - [x] Rectangle