mirror of
https://github.com/penpot/penpot.git
synced 2025-02-10 09:08:31 -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)
|
||||
:frame-id (:frame-id shape)
|
||||
:id id
|
||||
:index (cph/get-position-on-parent objects (:id shape))
|
||||
:index (cph/get-position-on-parent objects id)
|
||||
:obj (cond-> shape
|
||||
(contains? shape :shapes)
|
||||
(assoc :shapes []))})))
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.logging :as log]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.spec.interactions :as csi]
|
||||
|
@ -280,40 +281,23 @@
|
|||
{:keys [frame-id parent-id]} shape]
|
||||
[frame-id parent-id (inc index)])))))
|
||||
|
||||
(defn add-shape-changes
|
||||
([page-id objects selected attrs]
|
||||
(add-shape-changes page-id objects selected attrs true))
|
||||
([page-id objects selected attrs reg-object?]
|
||||
(let [id (:id attrs)
|
||||
shape (gpr/setup-proportions attrs)
|
||||
(defn make-new-shape
|
||||
[attrs objects selected]
|
||||
(let [default-attrs (if (= :frame (:type attrs))
|
||||
cp/default-frame-attrs
|
||||
cp/default-shape-attrs)
|
||||
|
||||
default-attrs (if (= :frame (:type shape))
|
||||
cp/default-frame-attrs
|
||||
cp/default-shape-attrs)
|
||||
selected-non-frames
|
||||
(into #{} (filter #(not= (:type (get objects %)) :frame) selected))
|
||||
|
||||
shape (merge default-attrs shape)
|
||||
[frame-id parent-id index]
|
||||
(get-shape-layer-position objects selected-non-frames attrs)]
|
||||
|
||||
not-frame? #(not (= :frame (get-in objects [% :type])))
|
||||
selected (into #{} (filter not-frame?) selected)
|
||||
|
||||
[frame-id parent-id index] (get-shape-layer-position objects selected attrs)
|
||||
|
||||
redo-changes (cond-> [{:type :add-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:frame-id frame-id
|
||||
:parent-id parent-id
|
||||
: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])))
|
||||
(-> (merge default-attrs attrs)
|
||||
(gpr/setup-proportions)
|
||||
(assoc :frame-id frame-id
|
||||
:parent-id parent-id
|
||||
:index index))))
|
||||
|
||||
(defn add-shape
|
||||
([attrs]
|
||||
|
@ -326,26 +310,23 @@
|
|||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
|
||||
id (or (:id attrs) (uuid/next))
|
||||
name (-> objects
|
||||
(retrieve-used-names)
|
||||
(generate-unique-name (:name attrs)))
|
||||
|
||||
selected (wsh/lookup-selected state)
|
||||
|
||||
[rchanges uchanges] (add-shape-changes
|
||||
page-id
|
||||
objects
|
||||
selected
|
||||
(-> attrs
|
||||
(assoc :id id )
|
||||
(assoc :name name)))]
|
||||
id (or (:id attrs) (uuid/next))
|
||||
name (-> objects
|
||||
(retrieve-used-names)
|
||||
(generate-unique-name (:name attrs)))
|
||||
|
||||
shape (make-new-shape
|
||||
(assoc attrs :id id :name name)
|
||||
objects
|
||||
selected)
|
||||
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/add-obj shape))]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (dch/commit-changes {:redo-changes rchanges
|
||||
:undo-changes uchanges
|
||||
:origin it})
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(when-not no-select?
|
||||
(select-shapes (d/ordered-set id))))
|
||||
(when (= :text (:type attrs))
|
||||
|
@ -361,28 +342,15 @@
|
|||
|
||||
to-move-shapes (->> (cph/get-immediate-children objects)
|
||||
(remove cph/frame-shape?)
|
||||
(mapv :id)
|
||||
(d/enumerate)
|
||||
(filterv (comp shapes second)))
|
||||
(filterv (comp shapes :id second))
|
||||
(mapv second))
|
||||
|
||||
rchanges [{:type :mov-objects
|
||||
:parent-id frame-id
|
||||
:frame-id frame-id
|
||||
:page-id page-id
|
||||
:index 0
|
||||
:shapes (mapv second to-move-shapes)}]
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/change-parent frame-id to-move-shapes 0))]
|
||||
|
||||
uchanges (->> to-move-shapes
|
||||
(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}))))))
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
(s/def ::set-of-uuid
|
||||
(s/every ::us/uuid :kind set?))
|
||||
|
@ -395,10 +363,10 @@
|
|||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
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)
|
||||
flows (:flows options)
|
||||
|
||||
groups-to-unmask
|
||||
(reduce (fn [group-ids id]
|
||||
|
@ -416,6 +384,8 @@
|
|||
|
||||
interacting-shapes
|
||||
(filter (fn [shape]
|
||||
;; If any of the deleted shapes is the destination of
|
||||
;; some interaction, this must be deleted, too.
|
||||
(let [interactions (:interactions shape)]
|
||||
(some #(and (csi/has-destination %)
|
||||
(contains? ids (:destination %)))
|
||||
|
@ -423,7 +393,26 @@
|
|||
(vals objects))
|
||||
|
||||
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
|
||||
(comp
|
||||
|
@ -435,142 +424,36 @@
|
|||
(take-while some?)
|
||||
(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
|
||||
;; Any parent whose children are all deleted, must be deleted too.
|
||||
(into (d/ordered-set) empty-parents-xform all-parents)
|
||||
|
||||
mk-del-obj-xf
|
||||
(comp (filter (partial contains? objects))
|
||||
(map (fn [id]
|
||||
{:type :del-obj
|
||||
:page-id page-id
|
||||
:id id})))
|
||||
changes (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-page page)
|
||||
(pcb/with-objects objects)
|
||||
(pcb/remove-objects all-children)
|
||||
(pcb/remove-objects ids)
|
||||
(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
|
||||
(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}))))))
|
||||
(rx/of (dch/commit-changes changes))))))
|
||||
|
||||
;; --- Add shape to Workspace
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :refer [max-safe-int min-safe-int]]
|
||||
[app.common.uuid :as uuid]
|
||||
|
@ -397,32 +398,23 @@
|
|||
(mapv #(usvg/inherit-attributes attrs %)))]
|
||||
[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)]
|
||||
(if (some? 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
|
||||
;; 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))
|
||||
unames (conj unames (:name new-shape))
|
||||
|
||||
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)))
|
||||
|
||||
;; Cannot create the data from current tags
|
||||
[unames [rchs uchs]])))
|
||||
[unames changes])))
|
||||
|
||||
(declare create-svg-shapes)
|
||||
|
||||
|
@ -493,27 +485,29 @@
|
|||
root-id (:id 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)
|
||||
(usvg/format-styles))
|
||||
|
||||
;; Reduces the children to create the changes to add the children shapes
|
||||
[_ [rchanges uchanges]]
|
||||
;; Reduce the children to create the changes to add the children shapes
|
||||
[_ changes]
|
||||
(reduce (partial add-svg-child-changes page-id objects selected frame-id root-id svg-data)
|
||||
[unames changes]
|
||||
(d/enumerate (->> (:content svg-data)
|
||||
(mapv #(usvg/inherit-attributes root-attrs %)))))
|
||||
|
||||
reg-objects-action {:type :reg-objects
|
||||
:page-id page-id
|
||||
:shapes (->> rchanges (filter #(= :add-obj (:type %))) (map :id) reverse vec)}
|
||||
changes (pcb/resize-parents changes
|
||||
(->> changes
|
||||
:redo-changes
|
||||
(filter #(= :add-obj (:type %)))
|
||||
(map :id)
|
||||
reverse
|
||||
vec))]
|
||||
|
||||
rchanges (conj rchanges reg-objects-action)]
|
||||
|
||||
(rx/of (dch/commit-changes {:redo-changes rchanges
|
||||
:undo-changes uchanges
|
||||
:origin it})
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(dwc/select-shapes (d/ordered-set root-id))))
|
||||
|
||||
(catch :default e
|
||||
|
|
Loading…
Add table
Reference in a new issue