mirror of
https://github.com/penpot/penpot.git
synced 2025-02-13 18:48:37 -05:00
🔧 Use changes-builder in workspace common operations
This commit is contained in:
parent
8ed857b4b9
commit
a7b455fb9a
3 changed files with 107 additions and 230 deletions
|
@ -270,7 +270,7 @@
|
||||||
:parent-id (:frame-id shape)
|
:parent-id (:frame-id shape)
|
||||||
:frame-id (:frame-id shape)
|
:frame-id (:frame-id shape)
|
||||||
:id id
|
:id id
|
||||||
:index (cph/get-position-on-parent objects (:id shape))
|
:index (cph/get-position-on-parent objects id)
|
||||||
:obj (cond-> shape
|
:obj (cond-> shape
|
||||||
(contains? shape :shapes)
|
(contains? shape :shapes)
|
||||||
(assoc :shapes []))})))
|
(assoc :shapes []))})))
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
|
[app.common.pages.changes-builder :as pcb]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.spec.interactions :as csi]
|
[app.common.spec.interactions :as csi]
|
||||||
|
@ -280,40 +281,23 @@
|
||||||
{:keys [frame-id parent-id]} shape]
|
{:keys [frame-id parent-id]} shape]
|
||||||
[frame-id parent-id (inc index)])))))
|
[frame-id parent-id (inc index)])))))
|
||||||
|
|
||||||
(defn add-shape-changes
|
(defn make-new-shape
|
||||||
([page-id objects selected attrs]
|
[attrs objects selected]
|
||||||
(add-shape-changes page-id objects selected attrs true))
|
(let [default-attrs (if (= :frame (:type attrs))
|
||||||
([page-id objects selected attrs reg-object?]
|
|
||||||
(let [id (:id attrs)
|
|
||||||
shape (gpr/setup-proportions attrs)
|
|
||||||
|
|
||||||
default-attrs (if (= :frame (:type shape))
|
|
||||||
cp/default-frame-attrs
|
cp/default-frame-attrs
|
||||||
cp/default-shape-attrs)
|
cp/default-shape-attrs)
|
||||||
|
|
||||||
shape (merge default-attrs shape)
|
selected-non-frames
|
||||||
|
(into #{} (filter #(not= (:type (get objects %)) :frame) selected))
|
||||||
|
|
||||||
not-frame? #(not (= :frame (get-in objects [% :type])))
|
[frame-id parent-id index]
|
||||||
selected (into #{} (filter not-frame?) selected)
|
(get-shape-layer-position objects selected-non-frames attrs)]
|
||||||
|
|
||||||
[frame-id parent-id index] (get-shape-layer-position objects selected attrs)
|
(-> (merge default-attrs attrs)
|
||||||
|
(gpr/setup-proportions)
|
||||||
redo-changes (cond-> [{:type :add-obj
|
(assoc :frame-id frame-id
|
||||||
:id id
|
|
||||||
:page-id page-id
|
|
||||||
:frame-id frame-id
|
|
||||||
:parent-id parent-id
|
:parent-id parent-id
|
||||||
:index index
|
:index index))))
|
||||||
:obj shape}]
|
|
||||||
reg-object?
|
|
||||||
(conj {:type :reg-objects
|
|
||||||
:page-id page-id
|
|
||||||
:shapes [id]}))
|
|
||||||
undo-changes [{:type :del-obj
|
|
||||||
:page-id page-id
|
|
||||||
:id id}]]
|
|
||||||
|
|
||||||
[redo-changes undo-changes])))
|
|
||||||
|
|
||||||
(defn add-shape
|
(defn add-shape
|
||||||
([attrs]
|
([attrs]
|
||||||
|
@ -326,26 +310,23 @@
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
|
selected (wsh/lookup-selected state)
|
||||||
|
|
||||||
id (or (:id attrs) (uuid/next))
|
id (or (:id attrs) (uuid/next))
|
||||||
name (-> objects
|
name (-> objects
|
||||||
(retrieve-used-names)
|
(retrieve-used-names)
|
||||||
(generate-unique-name (:name attrs)))
|
(generate-unique-name (:name attrs)))
|
||||||
|
|
||||||
selected (wsh/lookup-selected state)
|
shape (make-new-shape
|
||||||
|
(assoc attrs :id id :name name)
|
||||||
[rchanges uchanges] (add-shape-changes
|
|
||||||
page-id
|
|
||||||
objects
|
objects
|
||||||
selected
|
selected)
|
||||||
(-> attrs
|
|
||||||
(assoc :id id )
|
changes (-> (pcb/empty-changes it page-id)
|
||||||
(assoc :name name)))]
|
(pcb/add-obj shape))]
|
||||||
|
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of (dch/commit-changes {:redo-changes rchanges
|
(rx/of (dch/commit-changes changes)
|
||||||
:undo-changes uchanges
|
|
||||||
:origin it})
|
|
||||||
(when-not no-select?
|
(when-not no-select?
|
||||||
(select-shapes (d/ordered-set id))))
|
(select-shapes (d/ordered-set id))))
|
||||||
(when (= :text (:type attrs))
|
(when (= :text (:type attrs))
|
||||||
|
@ -361,28 +342,15 @@
|
||||||
|
|
||||||
to-move-shapes (->> (cph/get-immediate-children objects)
|
to-move-shapes (->> (cph/get-immediate-children objects)
|
||||||
(remove cph/frame-shape?)
|
(remove cph/frame-shape?)
|
||||||
(mapv :id)
|
|
||||||
(d/enumerate)
|
(d/enumerate)
|
||||||
(filterv (comp shapes second)))
|
(filterv (comp shapes :id second))
|
||||||
|
(mapv second))
|
||||||
|
|
||||||
rchanges [{:type :mov-objects
|
changes (-> (pcb/empty-changes it page-id)
|
||||||
:parent-id frame-id
|
(pcb/with-objects objects)
|
||||||
:frame-id frame-id
|
(pcb/change-parent frame-id to-move-shapes 0))]
|
||||||
:page-id page-id
|
|
||||||
:index 0
|
|
||||||
:shapes (mapv second to-move-shapes)}]
|
|
||||||
|
|
||||||
uchanges (->> to-move-shapes
|
(rx/of (dch/commit-changes changes))))))
|
||||||
(mapv (fn [[index shape-id]]
|
|
||||||
{:type :mov-objects
|
|
||||||
:parent-id uuid/zero
|
|
||||||
:frame-id uuid/zero
|
|
||||||
:page-id page-id
|
|
||||||
:index index
|
|
||||||
:shapes [shape-id]})))]
|
|
||||||
(rx/of (dch/commit-changes {:redo-changes rchanges
|
|
||||||
:undo-changes uchanges
|
|
||||||
:origin it}))))))
|
|
||||||
|
|
||||||
(s/def ::set-of-uuid
|
(s/def ::set-of-uuid
|
||||||
(s/every ::us/uuid :kind set?))
|
(s/every ::us/uuid :kind set?))
|
||||||
|
@ -395,10 +363,10 @@
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
options (wsh/lookup-page-options state page-id)
|
page (wsh/lookup-page state page-id)
|
||||||
|
flows (-> page :options :flows)
|
||||||
|
|
||||||
ids (cph/clean-loops objects ids)
|
ids (cph/clean-loops objects ids)
|
||||||
flows (:flows options)
|
|
||||||
|
|
||||||
groups-to-unmask
|
groups-to-unmask
|
||||||
(reduce (fn [group-ids id]
|
(reduce (fn [group-ids id]
|
||||||
|
@ -416,6 +384,8 @@
|
||||||
|
|
||||||
interacting-shapes
|
interacting-shapes
|
||||||
(filter (fn [shape]
|
(filter (fn [shape]
|
||||||
|
;; If any of the deleted shapes is the destination of
|
||||||
|
;; some interaction, this must be deleted, too.
|
||||||
(let [interactions (:interactions shape)]
|
(let [interactions (:interactions shape)]
|
||||||
(some #(and (csi/has-destination %)
|
(some #(and (csi/has-destination %)
|
||||||
(contains? ids (:destination %)))
|
(contains? ids (:destination %)))
|
||||||
|
@ -423,7 +393,26 @@
|
||||||
(vals objects))
|
(vals objects))
|
||||||
|
|
||||||
starting-flows
|
starting-flows
|
||||||
(filter #(contains? ids (:starting-frame %)) flows)
|
(filter (fn [flow]
|
||||||
|
;; If any of the deleted is a frame that starts a flow,
|
||||||
|
;; this must be deleted, too.
|
||||||
|
(contains? ids (:starting-frame flow)))
|
||||||
|
flows)
|
||||||
|
|
||||||
|
all-parents
|
||||||
|
(reduce (fn [res id]
|
||||||
|
;; All parents of any deleted shape must be resized.
|
||||||
|
(into res (cph/get-parent-ids objects id)))
|
||||||
|
(d/ordered-set)
|
||||||
|
ids)
|
||||||
|
|
||||||
|
all-children
|
||||||
|
(->> ids ;; Children of deleted shapes must be also deleted.
|
||||||
|
(reduce (fn [res id]
|
||||||
|
(into res (cph/get-children-ids objects id)))
|
||||||
|
[])
|
||||||
|
(reverse)
|
||||||
|
(into (d/ordered-set)))
|
||||||
|
|
||||||
empty-parents-xform
|
empty-parents-xform
|
||||||
(comp
|
(comp
|
||||||
|
@ -435,142 +424,36 @@
|
||||||
(take-while some?)
|
(take-while some?)
|
||||||
(map :id))
|
(map :id))
|
||||||
|
|
||||||
all-parents
|
|
||||||
(reduce (fn [res id]
|
|
||||||
(into res (cph/get-parent-ids objects id)))
|
|
||||||
(d/ordered-set)
|
|
||||||
ids)
|
|
||||||
|
|
||||||
all-children
|
|
||||||
(->> ids
|
|
||||||
(reduce (fn [res id]
|
|
||||||
(into res (cph/get-children-ids objects id)))
|
|
||||||
[])
|
|
||||||
(reverse)
|
|
||||||
(into (d/ordered-set)))
|
|
||||||
|
|
||||||
empty-parents
|
empty-parents
|
||||||
|
;; Any parent whose children are all deleted, must be deleted too.
|
||||||
(into (d/ordered-set) empty-parents-xform all-parents)
|
(into (d/ordered-set) empty-parents-xform all-parents)
|
||||||
|
|
||||||
mk-del-obj-xf
|
changes (-> (pcb/empty-changes it page-id)
|
||||||
(comp (filter (partial contains? objects))
|
(pcb/with-page page)
|
||||||
(map (fn [id]
|
(pcb/with-objects objects)
|
||||||
{:type :del-obj
|
(pcb/remove-objects all-children)
|
||||||
:page-id page-id
|
(pcb/remove-objects ids)
|
||||||
:id id})))
|
(pcb/remove-objects empty-parents)
|
||||||
|
(pcb/resize-parents all-parents)
|
||||||
|
(pcb/update-shapes groups-to-unmask
|
||||||
|
(fn [shape]
|
||||||
|
(assoc shape :masked-group? false)))
|
||||||
|
(pcb/update-shapes (map :id interacting-shapes)
|
||||||
|
(fn [shape]
|
||||||
|
(update shape :interactions
|
||||||
|
(fn [interactions]
|
||||||
|
(when interactions
|
||||||
|
(d/removev #(and (csi/has-destination %)
|
||||||
|
(contains? ids (:destination %)))
|
||||||
|
interactions))))))
|
||||||
|
(cond->
|
||||||
|
(seq starting-flows)
|
||||||
|
(pcb/set-page-option :flows
|
||||||
|
(reduce #(csp/remove-flow %1 (:id %2))
|
||||||
|
flows
|
||||||
|
starting-flows))))]
|
||||||
|
|
||||||
mk-add-obj-xf
|
(rx/of (dch/commit-changes changes))))))
|
||||||
(comp (filter (partial contains? objects))
|
|
||||||
(map (fn [id]
|
|
||||||
(let [item (get objects id)]
|
|
||||||
{:type :add-obj
|
|
||||||
:id (:id item)
|
|
||||||
:page-id page-id
|
|
||||||
:index (cph/get-position-on-parent objects id)
|
|
||||||
:frame-id (:frame-id item)
|
|
||||||
:parent-id (:parent-id item)
|
|
||||||
:obj item}))))
|
|
||||||
|
|
||||||
mk-mod-touched-xf
|
|
||||||
(comp (filter (partial contains? objects))
|
|
||||||
(map (fn [id]
|
|
||||||
(let [parent (get objects id)]
|
|
||||||
{:type :mod-obj
|
|
||||||
:page-id page-id
|
|
||||||
:id (:id parent)
|
|
||||||
:operations [{:type :set-touched
|
|
||||||
:touched (:touched parent)}]}))))
|
|
||||||
|
|
||||||
mk-mod-int-del-xf
|
|
||||||
(comp (filter some?)
|
|
||||||
(map (fn [obj]
|
|
||||||
{:type :mod-obj
|
|
||||||
:page-id page-id
|
|
||||||
:id (:id obj)
|
|
||||||
:operations [{:type :set
|
|
||||||
:attr :interactions
|
|
||||||
:val (vec (remove (fn [interaction]
|
|
||||||
(and (csi/has-destination interaction)
|
|
||||||
(contains? ids (:destination interaction))))
|
|
||||||
(:interactions obj)))}]})))
|
|
||||||
mk-mod-int-add-xf
|
|
||||||
(comp (filter some?)
|
|
||||||
(map (fn [obj]
|
|
||||||
{:type :mod-obj
|
|
||||||
:page-id page-id
|
|
||||||
:id (:id obj)
|
|
||||||
:operations [{:type :set
|
|
||||||
:attr :interactions
|
|
||||||
:val (:interactions obj)}]})))
|
|
||||||
|
|
||||||
mk-mod-del-flow-xf
|
|
||||||
(comp (filter some?)
|
|
||||||
(map (fn [flow]
|
|
||||||
{:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option :flows
|
|
||||||
:value (csp/remove-flow flows (:id flow))})))
|
|
||||||
|
|
||||||
mk-mod-add-flow-xf
|
|
||||||
(comp (filter some?)
|
|
||||||
(map (fn [_]
|
|
||||||
{:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option :flows
|
|
||||||
:value flows})))
|
|
||||||
|
|
||||||
mk-mod-unmask-xf
|
|
||||||
(comp (filter (partial contains? objects))
|
|
||||||
(map (fn [id]
|
|
||||||
{:type :mod-obj
|
|
||||||
:page-id page-id
|
|
||||||
:id id
|
|
||||||
:operations [{:type :set
|
|
||||||
:attr :masked-group?
|
|
||||||
:val false}]})))
|
|
||||||
|
|
||||||
mk-mod-mask-xf
|
|
||||||
(comp (filter (partial contains? objects))
|
|
||||||
(map (fn [id]
|
|
||||||
{:type :mod-obj
|
|
||||||
:page-id page-id
|
|
||||||
:id id
|
|
||||||
:operations [{:type :set
|
|
||||||
:attr :masked-group?
|
|
||||||
:val true}]})))
|
|
||||||
|
|
||||||
rchanges
|
|
||||||
(-> []
|
|
||||||
(into mk-del-obj-xf all-children)
|
|
||||||
(into mk-del-obj-xf ids)
|
|
||||||
(into mk-del-obj-xf empty-parents)
|
|
||||||
(conj {:type :reg-objects
|
|
||||||
:page-id page-id
|
|
||||||
:shapes (vec all-parents)})
|
|
||||||
(into mk-mod-unmask-xf groups-to-unmask)
|
|
||||||
(into mk-mod-int-del-xf interacting-shapes)
|
|
||||||
(into mk-mod-del-flow-xf starting-flows))
|
|
||||||
|
|
||||||
uchanges
|
|
||||||
(-> []
|
|
||||||
(into mk-add-obj-xf (reverse empty-parents))
|
|
||||||
(into mk-add-obj-xf (reverse ids))
|
|
||||||
(into mk-add-obj-xf (reverse all-children))
|
|
||||||
(conj {:type :reg-objects
|
|
||||||
:page-id page-id
|
|
||||||
:shapes (vec all-parents)})
|
|
||||||
(into mk-mod-touched-xf (reverse all-parents))
|
|
||||||
(into mk-mod-mask-xf groups-to-unmask)
|
|
||||||
(into mk-mod-int-add-xf interacting-shapes)
|
|
||||||
(into mk-mod-add-flow-xf starting-flows))]
|
|
||||||
|
|
||||||
;; (println "================ rchanges")
|
|
||||||
;; (cljs.pprint/pprint rchanges)
|
|
||||||
;; (println "================ uchanges")
|
|
||||||
;; (cljs.pprint/pprint uchanges)
|
|
||||||
(rx/of (dch/commit-changes {:redo-changes rchanges
|
|
||||||
:undo-changes uchanges
|
|
||||||
:origin it}))))))
|
|
||||||
|
|
||||||
;; --- Add shape to Workspace
|
;; --- Add shape to Workspace
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
|
[app.common.pages.changes-builder :as pcb]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.spec :refer [max-safe-int min-safe-int]]
|
[app.common.spec :refer [max-safe-int min-safe-int]]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
|
@ -397,32 +398,23 @@
|
||||||
(mapv #(usvg/inherit-attributes attrs %)))]
|
(mapv #(usvg/inherit-attributes attrs %)))]
|
||||||
[shape children]))))
|
[shape children]))))
|
||||||
|
|
||||||
(defn add-svg-child-changes [page-id objects selected frame-id parent-id svg-data [unames [rchs uchs]] [index data]]
|
(defn add-svg-child-changes [page-id objects selected frame-id parent-id svg-data [unames changes] [index data]]
|
||||||
(let [[shape children] (parse-svg-element frame-id svg-data data unames)]
|
(let [[shape children] (parse-svg-element frame-id svg-data data unames)]
|
||||||
(if (some? shape)
|
(if (some? shape)
|
||||||
(let [shape-id (:id shape)
|
(let [shape-id (:id shape)
|
||||||
|
|
||||||
[rch1 uch1] (dwc/add-shape-changes page-id objects selected shape false)
|
new-shape (dwc/make-new-shape shape objects selected)
|
||||||
|
changes (-> changes
|
||||||
|
(pcb/with-objects objects)
|
||||||
|
(pcb/add-obj new-shape)
|
||||||
|
(pcb/change-parent parent-id [new-shape]))
|
||||||
|
|
||||||
;; Mov-objects won't have undo because we "delete" the object in the undo of the
|
unames (conj unames (:name new-shape))
|
||||||
;; previous operation
|
|
||||||
rch2 [{:type :mov-objects
|
|
||||||
:parent-id parent-id
|
|
||||||
:frame-id frame-id
|
|
||||||
:page-id page-id
|
|
||||||
:index index
|
|
||||||
:shapes [shape-id]}]
|
|
||||||
|
|
||||||
;; Careful! the undo changes are concatenated reversed (we undo in reverse order
|
|
||||||
changes [(d/concat-vec rchs rch1 rch2)
|
|
||||||
(d/concat-vec uch1 uchs)]
|
|
||||||
unames (conj unames (:name shape))
|
|
||||||
|
|
||||||
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id shape-id svg-data)]
|
reducer-fn (partial add-svg-child-changes page-id objects selected frame-id shape-id svg-data)]
|
||||||
(reduce reducer-fn [unames changes] (d/enumerate children)))
|
(reduce reducer-fn [unames changes] (d/enumerate children)))
|
||||||
|
|
||||||
;; Cannot create the data from current tags
|
[unames changes])))
|
||||||
[unames [rchs uchs]])))
|
|
||||||
|
|
||||||
(declare create-svg-shapes)
|
(declare create-svg-shapes)
|
||||||
|
|
||||||
|
@ -493,27 +485,29 @@
|
||||||
root-id (:id root-shape)
|
root-id (:id root-shape)
|
||||||
|
|
||||||
;; Creates the root shape
|
;; Creates the root shape
|
||||||
changes (dwc/add-shape-changes page-id objects selected root-shape false)
|
new-shape (dwc/make-new-shape root-shape objects selected)
|
||||||
|
changes (-> (pcb/empty-changes it page-id)
|
||||||
|
(pcb/add-obj new-shape))
|
||||||
|
|
||||||
root-attrs (-> (:attrs svg-data)
|
root-attrs (-> (:attrs svg-data)
|
||||||
(usvg/format-styles))
|
(usvg/format-styles))
|
||||||
|
|
||||||
;; Reduces the children to create the changes to add the children shapes
|
;; Reduce the children to create the changes to add the children shapes
|
||||||
[_ [rchanges uchanges]]
|
[_ changes]
|
||||||
(reduce (partial add-svg-child-changes page-id objects selected frame-id root-id svg-data)
|
(reduce (partial add-svg-child-changes page-id objects selected frame-id root-id svg-data)
|
||||||
[unames changes]
|
[unames changes]
|
||||||
(d/enumerate (->> (:content svg-data)
|
(d/enumerate (->> (:content svg-data)
|
||||||
(mapv #(usvg/inherit-attributes root-attrs %)))))
|
(mapv #(usvg/inherit-attributes root-attrs %)))))
|
||||||
|
|
||||||
reg-objects-action {:type :reg-objects
|
changes (pcb/resize-parents changes
|
||||||
:page-id page-id
|
(->> changes
|
||||||
:shapes (->> rchanges (filter #(= :add-obj (:type %))) (map :id) reverse vec)}
|
:redo-changes
|
||||||
|
(filter #(= :add-obj (:type %)))
|
||||||
|
(map :id)
|
||||||
|
reverse
|
||||||
|
vec))]
|
||||||
|
|
||||||
rchanges (conj rchanges reg-objects-action)]
|
(rx/of (dch/commit-changes changes)
|
||||||
|
|
||||||
(rx/of (dch/commit-changes {:redo-changes rchanges
|
|
||||||
:undo-changes uchanges
|
|
||||||
:origin it})
|
|
||||||
(dwc/select-shapes (d/ordered-set root-id))))
|
(dwc/select-shapes (d/ordered-set root-id))))
|
||||||
|
|
||||||
(catch :default e
|
(catch :default e
|
||||||
|
|
Loading…
Add table
Reference in a new issue