From bc27dc87ea700561b8cf2c91a81e910b173f1d25 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 19 Jan 2026 15:17:25 +0100 Subject: [PATCH] WIP --- .../app/main/data/workspace/path/changes.cljs | 7 +- .../app/main/data/workspace/path/edition.cljs | 129 ++++++++++++------ .../main/data/workspace/path/selection.cljs | 5 +- .../app/main/data/workspace/path/state.cljs | 9 ++ .../app/main/data/workspace/path/streams.cljs | 1 + .../app/main/data/workspace/path/undo.cljs | 2 + 6 files changed, 106 insertions(+), 47 deletions(-) diff --git a/frontend/src/app/main/data/workspace/path/changes.cljs b/frontend/src/app/main/data/workspace/path/changes.cljs index d766487e7e..b3578b552c 100644 --- a/frontend/src/app/main/data/workspace/path/changes.cljs +++ b/frontend/src/app/main/data/workspace/path/changes.cljs @@ -17,14 +17,12 @@ (defn generate-path-changes "Generates changes to update the new content of the shape" - [it objects page-id shape old-content new-content] + [it objects page-id shape-id old-content new-content] (assert (path/content? old-content)) (assert (path/content? new-content)) - (let [shape-id (:id shape) - - ;; We set the old values so the update-shapes works + (let [;; We set the old values so the update-shapes works objects (update objects shape-id (fn [shape] @@ -62,6 +60,7 @@ ([] (save-path-content {})) ([{:keys [preserve-move-to] :or {preserve-move-to false}}] + (ptk/reify ::save-path-content ptk/UpdateEvent (update [_ state] diff --git a/frontend/src/app/main/data/workspace/path/edition.cljs b/frontend/src/app/main/data/workspace/path/edition.cljs index 1210111f71..53985eac52 100644 --- a/frontend/src/app/main/data/workspace/path/edition.cljs +++ b/frontend/src/app/main/data/workspace/path/edition.cljs @@ -52,26 +52,61 @@ content-modifiers (dm/get-in state [:workspace-local :edit-path id :content-modifiers])] + (if (or (nil? shape) (nil? content-modifiers)) (rx/of (dwe/clear-edition-mode)) - (let [page-id (get state :current-page-id state) - objects (dsh/lookup-page-objects state) + (let [page-id (get state :current-page-id) + objects (dsh/lookup-page-objects state page-id) - content (get shape :content) - new-content (path/apply-content-modifiers content content-modifiers) + old-content (get shape :content) + new-content (path/apply-content-modifiers old-content content-modifiers) - old-points (path.segment/get-points content) + old-points (path.segment/get-points old-content) new-points (path.segment/get-points new-content) - point-change (->> (map hash-map old-points new-points) (reduce merge))] + point-change (->> (map hash-map old-points new-points) + (reduce merge))] (when (and (some? new-content) (some? shape)) - (let [changes (changes/generate-path-changes it objects page-id shape (:content shape) new-content)] + (let [changes (changes/generate-path-changes it objects page-id shape old-content new-content)] (if (empty? new-content) (rx/of (dch/commit-changes changes) (dwe/clear-edition-mode)) (rx/of (dch/commit-changes changes) - (selection/update-selection point-change) - (fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers :moving-nodes :moving-handler)))))))))))) + (selection/update-selection id point-change) + (fn [state] + (update-in state [:workspace-local :edit-path id] + dissoc :content-modifiers :moving-nodes :moving-handler)))))))))))) + + +(defn apply-content-modifiers2 + [shape-id old-content] + (ptk/reify ::apply-content-modifiers2 + ptk/WatchEvent + (watch [it state _] + (let [ ;; FIXME: hide under getter function under state + content-modifiers + (dm/get-in state [:workspace-local :edit-path shape-id :content-modifiers])] + + (if (nil? content-modifiers) + (rx/of (dwe/clear-edition-mode)) + (let [page-id (get state :current-page-id) + objects (dsh/lookup-page-objects state page-id) + new-content (path/apply-content-modifiers old-content content-modifiers) + point-change (->> (map hash-map + (path.segment/get-points old-content) + (path.segment/get-points new-content)) + (reduce merge)) + changes (changes/generate-path-changes it objects page-id shape-id old-content new-content)] + + (if (empty? new-content) + (rx/of (dch/commit-changes changes) + (dwe/clear-edition-mode)) + (rx/of (dch/commit-changes changes) + (selection/update-selection shape-id point-change) + (fn [state] + (update-in state [:workspace-local :edit-path shape-id] + dissoc :content-modifiers :moving-nodes :moving-handler)))))))))) + (defn modify-content-point [content {dx :x dy :y} modifiers point] @@ -109,12 +144,12 @@ (-> state (assoc-in [:workspace-local :edit-path id :content-modifiers] content-modifiers)))))) -(defn move-selected-path-point [from-point to-point] +(defn- move-selected-path-point [id from-point to-point] (ptk/reify ::move-point ptk/UpdateEvent (update [_ state] - (let [id (st/get-path-id state) - content (st/get-path state :content) + (let [shape (st/get-path* state id) + content (get shape :content) to-point (cond-> to-point (:shift? to-point) (path.helpers/position-fixed-angle from-point)) @@ -139,39 +174,43 @@ (ptk/reify ::start-move-path-point ptk/WatchEvent (watch [_ state _] - (let [id (dm/get-in state [:workspace-local :edition]) - selected-points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{}) - selected? (contains? selected-points position)] + (let [local (get state :workspace-local) + id (get local :edition) + points (get-in local [:edit-path id :selected-points] #{}) + selected? (contains? points position)] + + (prn "start-move-path-point" id) (streams/drag-stream (rx/of (dwsh/update-shapes [id] path/convert-to-path) (when-not selected? (selection/select-node position shift?)) - (drag-selected-points @ms/mouse-position)) + (drag-selected-points id @ms/mouse-position)) (rx/of (selection/select-node position shift?))))))) -(defn drag-selected-points - [start-position] +(defn- drag-selected-points + [id start-position] (ptk/reify ::drag-selected-points ptk/WatchEvent (watch [_ state stream] (let [stopper (mse/drag-stopper stream) - id (dm/get-in state [:workspace-local :edition]) + shape (st/get-path* state id) + content (get shape :content) + points (path.segment/get-points content) - selected-points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{}) + selected-points + (dm/get-in state [:workspace-local :edit-path id :selected-points] #{}) - start-position (apply min-key #(gpt/distance start-position %) selected-points) - - content (st/get-path state :content) - points (path.segment/get-points content)] + start-position + (apply min-key #(gpt/distance start-position %) selected-points)] (rx/concat ;; This stream checks the consecutive mouse positions to do the dragging (->> points (streams/move-points-stream start-position selected-points) - (rx/map #(move-selected-path-point start-position %)) + (rx/map #(move-selected-path-point id start-position %)) (rx/take-until stopper)) - (rx/of (apply-content-modifiers))))))) + (rx/of (apply-content-modifiers2 id content))))))) (defn- get-displacement "Retrieve the correct displacement delta point for the @@ -335,28 +374,38 @@ (watch [_ _ _] (rx/of (ptk/data-event :layout/update {:ids [id]}))))) -(defn split-segments - [{:keys [from-p to-p t]}] - (ptk/reify ::split-segments + +(defn- snapshot-path-content + [id] + (ptk/reify ::snapshot-path-content ptk/UpdateEvent (update [_ state] - (let [id (st/get-path-id state) - content (st/get-path state :content)] - (-> state - (assoc-in [:workspace-local :edit-path id :old-content] content) - (st/set-content (-> content - (path.segment/split-segments #{from-p to-p} t) - (path/content)))))) + (let [shape (st/get-path* state id) + content (get shape :content)] + (update-in state [:workspace-local :edit-path id] assoc :old-content content))))) +(defn- split-segments + [shape-id {:keys [from-p to-p t]}] + (ptk/reify ::split-segments ptk/WatchEvent - (watch [_ _ _] - (rx/of (changes/save-path-content {:preserve-move-to true}))))) + (watch [it state _] + (let [page-id (get state :current-page-id) + objects (dsh/lookup-page-objects state page-id) + + shape (st/get-path* state shape-id) + old-content (get shape :content) + new-content (-> old-content + (path.segment/split-segments #{from-p to-p} t) + (path/content)) + changes (changes/generate-path-changes it objects page-id shape-id old-content new-content)] + + (rx/of (dch/commit-changes changes)))))) (defn create-node-at-position - [event] + [params] (ptk/reify ::create-node-at-position ptk/WatchEvent (watch [_ state _] (let [id (st/get-path-id state)] (rx/of (dwsh/update-shapes [id] path/convert-to-path) - (split-segments event)))))) + (split-segments id params)))))) diff --git a/frontend/src/app/main/data/workspace/path/selection.cljs b/frontend/src/app/main/data/workspace/path/selection.cljs index 81210ab9fb..0c002f749f 100644 --- a/frontend/src/app/main/data/workspace/path/selection.cljs +++ b/frontend/src/app/main/data/workspace/path/selection.cljs @@ -149,12 +149,11 @@ (rx/of (clear-area-selection)))))))) (defn update-selection - [point-change] + [id point-change] (ptk/reify ::update-selection ptk/UpdateEvent (update [_ state] - (let [id (st/get-path-id state) - selected-points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{}) + (let [selected-points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{}) selected-points (into #{} (map point-change) selected-points)] (-> state (assoc-in [:workspace-local :edit-path id :selected-points] selected-points)))))) diff --git a/frontend/src/app/main/data/workspace/path/state.cljs b/frontend/src/app/main/data/workspace/path/state.cljs index 6a89ed127a..b2bd6ac32e 100644 --- a/frontend/src/app/main/data/workspace/path/state.cljs +++ b/frontend/src/app/main/data/workspace/path/state.cljs @@ -34,6 +34,15 @@ shape (get-in shape ks)))) + +(defn get-path* + "Retrieves the location of the path object and additionally can pass + the arguments. This location can be used in get-in, assoc-in... functions" + [state id] + (let [page-id (:current-page-id state) + file-id (:current-file-id state)] + (get-in state [:files file-id :data :pages-index page-id :objects id]))) + (defn set-content [state content] (let [path-loc (get-path-location state :content)] diff --git a/frontend/src/app/main/data/workspace/path/streams.cljs b/frontend/src/app/main/data/workspace/path/streams.cljs index b6028eec11..f39efc152e 100644 --- a/frontend/src/app/main/data/workspace/path/streams.cljs +++ b/frontend/src/app/main/data/workspace/path/streams.cljs @@ -82,6 +82,7 @@ (defn move-points-stream [start-point selected-points points] + ;; FIXME: provide zoom on params and avoid derefing state (let [zoom (get-in @st/state [:workspace-local :zoom] 1) ranges (snap/create-ranges points selected-points) d-pos (/ snap/snap-path-accuracy zoom) diff --git a/frontend/src/app/main/data/workspace/path/undo.cljs b/frontend/src/app/main/data/workspace/path/undo.cljs index bd0a6efa9f..8dd9a88686 100644 --- a/frontend/src/app/main/data/workspace/path/undo.cljs +++ b/frontend/src/app/main/data/workspace/path/undo.cljs @@ -72,6 +72,8 @@ (watch [_ state _] (let [id (st/get-path-id state) undo-stack (get-in state [:workspace-local :edit-path id :undo-stack])] + + (app.common.pprint/pprint undo-stack) (if (> (:index undo-stack) 0) (rx/of (changes/save-path-content {:preserve-move-to true})) (rx/of (changes/save-path-content {:preserve-move-to true})