From f0b80f3171631dabdc29ecb17c94ada8aa09d1d4 Mon Sep 17 00:00:00 2001 From: dscyrescotti Date: Mon, 17 Jun 2024 01:33:10 +0700 Subject: [PATCH] feat: implement undo and redo logic --- Memola/Canvas/Contexts/GraphicContext.swift | 17 ++++++++++++++++- Memola/Canvas/Core/Canvas.swift | 2 +- Memola/Canvas/History/History.swift | 14 ++++++++++++++ Memola/Canvas/History/HistoryEvent.swift | 1 + .../ViewController/CanvasViewController.swift | 3 ++- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/Memola/Canvas/Contexts/GraphicContext.swift b/Memola/Canvas/Contexts/GraphicContext.swift index 61e811b..fefd095 100644 --- a/Memola/Canvas/Contexts/GraphicContext.swift +++ b/Memola/Canvas/Contexts/GraphicContext.swift @@ -70,6 +70,13 @@ final class GraphicContext: @unchecked Sendable { } } previousElement = nil + case .photo(let photo): + tree.remove(photo.element, in: photo.photoBox) + withPersistence(\.backgroundContext) { [weak photo] context in + photo?.object?.element?.graphicContext = nil + try context.saveIfNeeded() + context.refreshAllObjects() + } } } @@ -105,6 +112,13 @@ final class GraphicContext: @unchecked Sendable { } } previousElement = nil + case .photo(let photo): + tree.insert(photo.element, in: photo.photoBox) + withPersistence(\.backgroundContext) { [weak self, weak photo] context in + photo?.object?.element?.graphicContext = self?.object + try context.saveIfNeeded() + context.refreshAllObjects() + } } } } @@ -304,7 +318,7 @@ extension GraphicContext { // MARK: - Photo extension GraphicContext { - func insertPhoto(at point: CGPoint, photoItem: PhotoItem) { + func insertPhoto(at point: CGPoint, photoItem: PhotoItem) -> Photo { let size = photoItem.dimension let origin = point let bounds = [origin.x - size.width / 2, origin.y - size.height / 2, origin.x + size.width / 2, origin.y + size.height / 2] @@ -331,6 +345,7 @@ extension GraphicContext { try context.saveIfNeeded() } self.previousElement = .photo(photo) + return photo } } diff --git a/Memola/Canvas/Core/Canvas.swift b/Memola/Canvas/Core/Canvas.swift index 595fa79..4189a32 100644 --- a/Memola/Canvas/Core/Canvas.swift +++ b/Memola/Canvas/Core/Canvas.swift @@ -128,7 +128,7 @@ extension Canvas { // MARK: - Photo extension Canvas { - func insertPhoto(at point: CGPoint, photoItem: PhotoItem) { + func insertPhoto(at point: CGPoint, photoItem: PhotoItem) -> Photo { graphicContext.insertPhoto(at: point, photoItem: photoItem) } } diff --git a/Memola/Canvas/History/History.swift b/Memola/Canvas/History/History.swift index 6125381..a6d152b 100644 --- a/Memola/Canvas/History/History.swift +++ b/Memola/Canvas/History/History.swift @@ -70,6 +70,20 @@ class History: ObservableObject { try context.saveIfNeeded() } } + case .photo(let _photo): + if let url = _photo.bookmark?.getBookmarkURL() { + do { + try FileManager.default.removeItem(at: url) + } catch { + NSLog("[Memola] - \(error.localizedDescription)") + } + } + withPersistence(\.backgroundContext) { context in + if let photo = _photo.object { + context.delete(photo) + } + try context.saveIfNeeded() + } } } redoStack.removeAll() diff --git a/Memola/Canvas/History/HistoryEvent.swift b/Memola/Canvas/History/HistoryEvent.swift index 4fb811f..a24d301 100644 --- a/Memola/Canvas/History/HistoryEvent.swift +++ b/Memola/Canvas/History/HistoryEvent.swift @@ -9,4 +9,5 @@ import Foundation enum HistoryEvent { case stroke(any Stroke) + case photo(Photo) } diff --git a/Memola/Canvas/View/Bridge/ViewController/CanvasViewController.swift b/Memola/Canvas/View/Bridge/ViewController/CanvasViewController.swift index c995c08..a21f7fb 100644 --- a/Memola/Canvas/View/Bridge/ViewController/CanvasViewController.swift +++ b/Memola/Canvas/View/Bridge/ViewController/CanvasViewController.swift @@ -238,7 +238,8 @@ extension CanvasViewController { tool.selectedPhotoItem = nil } let point = gesture.location(in: drawingView) - canvas.insertPhoto(at: point.muliply(by: drawingView.ratio), photoItem: photoItem) + let photo = canvas.insertPhoto(at: point.muliply(by: drawingView.ratio), photoItem: photoItem) + history.addUndo(.photo(photo)) drawingView.draw() } }