Browse Source

Implemented center content

flabbet 2 years ago
parent
commit
890917f35c

+ 0 - 3
src/PixiEditor.ChangeableDocument/ChangeInfos/Root/Clip_ChangeInfo.cs

@@ -1,3 +0,0 @@
-namespace PixiEditor.ChangeableDocument.ChangeInfos.Root;
-
-public record Clip_ChangeInfo() : IChangeInfo;

+ 36 - 0
src/PixiEditor.ChangeableDocument/Changeables/Document.cs

@@ -261,4 +261,40 @@ internal class Document : IChangeable, IReadOnlyDocument, IDisposable
         }
         return false;
     }
+    
+    public List<Guid> ExtractLayers(List<Guid> members)
+    {
+        var result = new List<Guid>();
+        foreach (var member in members)
+        {
+            if (TryFindMember(member, out var structureMember))
+            {
+                if (structureMember is Layer layer && !result.Contains(layer.GuidValue))
+                {
+                    result.Add(layer.GuidValue);
+                }
+                else if (structureMember is Folder folder)
+                {
+                    ExtractLayers(folder, result);
+                }
+            }
+        }
+        return result;
+    }
+
+    private List<Guid> ExtractLayers(Folder folder, List<Guid> list)
+    {
+        foreach (var member in folder.Children)
+        {
+            if (member is Layer layer && !list.Contains(layer.GuidValue))
+            {
+                list.Add(layer.GuidValue);
+            }
+            else if (member is Folder childFolder)
+            {
+                ExtractLayers(childFolder, list);
+            }
+        }
+        return list;
+    }
 }

+ 19 - 0
src/PixiEditor.ChangeableDocument/Changes/Drawing/ShiftLayerHelper.cs

@@ -0,0 +1,19 @@
+using PixiEditor.DrawingApi.Core.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changes.Drawing;
+
+internal static class ShiftLayerHelper
+{
+    public static HashSet<VecI> DrawShiftedLayer(Document target, Guid layerGuid, bool keepOriginal, VecI delta)
+    {
+        var targetImage = target.FindMemberOrThrow<Layer>(layerGuid).LayerImage;
+        var prevChunks = targetImage.FindAffectedChunks();
+        targetImage.CancelChanges();
+        if (!keepOriginal)
+            targetImage.EnqueueClear();
+        targetImage.EnqueueDrawChunkyImage(delta, targetImage, false, false);
+        var curChunks = targetImage.FindAffectedChunks();
+        curChunks.UnionWith(prevChunks);
+        return curChunks;
+    }
+}

+ 2 - 15
src/PixiEditor.ChangeableDocument/Changes/Drawing/ShiftLayer_UpdateableChange.cs

@@ -28,22 +28,9 @@ internal class ShiftLayer_UpdateableChange : UpdateableChange
         this.keepOriginal = keepOriginal;
     }
 
-    private HashSet<VecI> DrawShiftedLayer(Document target)
-    {
-        var targetImage = target.FindMemberOrThrow<Layer>(layerGuid).LayerImage;
-        var prevChunks = targetImage.FindAffectedChunks();
-        targetImage.CancelChanges();
-        if (!keepOriginal)
-            targetImage.EnqueueClear();
-        targetImage.EnqueueDrawChunkyImage(delta, targetImage, false, false);
-        var curChunks = targetImage.FindAffectedChunks();
-        curChunks.UnionWith(prevChunks);
-        return curChunks;
-    }
-
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
-        var chunks = DrawShiftedLayer(target);
+        var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta);
         var image = target.FindMemberOrThrow<Layer>(layerGuid).LayerImage;
 
         if (originalLayerChunks is not null)
@@ -57,7 +44,7 @@ internal class ShiftLayer_UpdateableChange : UpdateableChange
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target)
     {
-        var chunks = DrawShiftedLayer(target);
+        var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, keepOriginal, delta);
         return new LayerImageChunks_ChangeInfo(layerGuid, chunks);
     }
 

+ 109 - 0
src/PixiEditor.ChangeableDocument/Changes/Root/CenterContent_Change.cs

@@ -0,0 +1,109 @@
+using PixiEditor.ChangeableDocument.Changes.Drawing;
+using PixiEditor.DrawingApi.Core.Numerics;
+
+namespace PixiEditor.ChangeableDocument.Changes.Root;
+
+internal class CenterContent_Change : Change
+{
+    private VecI _oldOffset;
+    private List<Guid> _affectedLayers;
+    private Dictionary<Guid, CommittedChunkStorage>? originalLayerChunks;
+
+    [GenerateMakeChangeAction]
+    public CenterContent_Change(List<Guid> layers)
+    {
+        _affectedLayers = layers;
+    }
+    
+    public override bool InitializeAndValidate(Document target)
+    {
+        if (_affectedLayers.Count == 0)
+        {
+            return false;
+        }
+
+        _affectedLayers = target.ExtractLayers(_affectedLayers);
+
+        foreach (var layer in _affectedLayers)
+        {
+            if (!target.HasMember(layer)) return false;
+        }
+
+        _oldOffset = CalculateCurrentOffset(target);
+        
+        return true;
+    }
+
+    private VecI CalculateCurrentOffset(Document document)
+    {
+        VecI currentCenter = new VecI(0, 0);
+        RectI? currentBounds = null;
+        foreach (var layerGuid in _affectedLayers)
+        {
+            Layer layer = document.FindMemberOrThrow<Layer>(layerGuid);
+            RectI? tightBounds = layer.LayerImage.FindPreciseBounds();
+            if (tightBounds.HasValue)
+            {
+                currentBounds = currentBounds.HasValue ? currentBounds.Value.Union(tightBounds.Value) : tightBounds;
+                currentCenter = new VecI(
+                    currentBounds.Value.X + currentBounds.Value.Width / 2,
+                    currentBounds.Value.Y + currentBounds.Value.Height / 2);
+            }
+        }
+        
+        return currentCenter;
+    }
+
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
+    {
+        VecI documentCenter = target.Size / 2;
+        VecI currentOffset = _oldOffset;
+        
+        VecI shift = documentCenter - currentOffset;
+
+        List<IChangeInfo> changes = new List<IChangeInfo>();
+        originalLayerChunks = new Dictionary<Guid, CommittedChunkStorage>();
+        
+        foreach (var layerGuid in _affectedLayers)
+        {
+            Layer layer = target.FindMemberOrThrow<Layer>(layerGuid);
+            var chunks = ShiftLayerHelper.DrawShiftedLayer(target, layerGuid, false, shift);
+            changes.Add(new LayerImageChunks_ChangeInfo(layerGuid, chunks));
+            
+            originalLayerChunks[layerGuid] = new CommittedChunkStorage(layer.LayerImage, layer.LayerImage.FindAffectedChunks());
+            layer.LayerImage.CommitChanges();
+        }
+
+        ignoreInUndo = shift.TaxicabLength == 0;
+        return changes;
+    }
+
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
+    {
+        List<IChangeInfo> changes = new List<IChangeInfo>();
+        foreach (var layerGuid in _affectedLayers)
+        {
+            var image = target.FindMemberOrThrow<Layer>(layerGuid).LayerImage;
+            CommittedChunkStorage? originalChunks = originalLayerChunks?[layerGuid];
+            var affected = DrawingChangeHelper.ApplyStoredChunksDisposeAndSetToNull(image, ref originalChunks);
+            changes.Add(new LayerImageChunks_ChangeInfo(layerGuid, affected));
+        }
+        
+        return changes;
+    }
+
+    public override void Dispose()
+    {
+        if (originalLayerChunks == null)
+        {
+            return;
+        }
+
+        foreach (var layerChunk in originalLayerChunks)
+        {
+            layerChunk.Value.Dispose();
+        }
+        
+        originalLayerChunks = null;
+    }
+}

+ 0 - 1
src/PixiEditor.ChangeableDocument/Changes/Root/ClipCanvas_Change.cs

@@ -1,5 +1,4 @@
 using PixiEditor.ChangeableDocument.ChangeInfos.Root;
-using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.DrawingApi.Core.Numerics;
 
 namespace PixiEditor.ChangeableDocument.Changes.Root;

+ 8 - 0
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -251,4 +251,12 @@ internal class DocumentOperationsModule
             return;
         Internals.ActionAccumulator.AddFinishedActions(new ClipCanvas_Action());
     }
+
+    public void CenterContent(IReadOnlyList<Guid> structureMembers)
+    {
+        if (Internals.ChangeController.IsChangeActive)
+            return;
+
+        Internals.ActionAccumulator.AddFinishedActions(new CenterContent_Action(structureMembers.ToList()));
+    }
 }

+ 6 - 2
src/PixiEditor/ViewModels/SubViewModels/Document/DocumentManagerViewModel.cs

@@ -132,7 +132,11 @@ internal class DocumentManagerViewModel : SubViewModel<ViewModelMain>
     [Command.Basic("PixiEditor.Document.CenterContent", "Center Content", "Center Content", CanExecute = "PixiEditor.HasDocument")]
     public void CenterContent()
     {
-        //Owner.BitmapManager.ActiveDocument.CenterContent();
+        if(ActiveDocument is null || ActiveDocument.SelectedStructureMember == null)
+            return;
+        
+        List<Guid> layerGuids = new List<Guid>() { ActiveDocument.SelectedStructureMember.GuidValue };
+        layerGuids.AddRange(ActiveDocument.SoftSelectedStructureMembers.Select(x => x.GuidValue));
+        ActiveDocument.Operations.CenterContent(layerGuids);
     }
-
 }