🎉 Update master component

This commit is contained in:
Andrés Moya 2020-09-09 11:19:29 +02:00
parent 917643489f
commit f837bad894
10 changed files with 337 additions and 166 deletions

View file

@ -182,6 +182,20 @@
(assoc m key (apply f found args)) (assoc m key (apply f found args))
m))) m)))
(defn assoc-in-when
[m key-seq v]
(let [found (get-in m key-seq sentinel)]
(if-not (identical? sentinel found)
(assoc-in m key-seq v)
m)))
(defn assoc-when
[m key v]
(let [found (get m key sentinel)]
(if-not (identical? sentinel found)
(assoc m key v)
m)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Data Parsing / Conversion ;; Data Parsing / Conversion
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -362,8 +362,8 @@
(defmethod change-spec :del-component [_] (defmethod change-spec :del-component [_]
(s/keys :req-un [::id])) (s/keys :req-un [::id]))
(defmethod change-spec :sync-library [_] (defmethod change-spec :update-component [_]
(s/keys :req-un [::id])) (s/keys :req-un [::id ::shapes]))
(s/def ::change (s/multi-spec change-spec :type)) (s/def ::change (s/multi-spec change-spec :type))
(s/def ::changes (s/coll-of ::change)) (s/def ::changes (s/coll-of ::change))
@ -777,80 +777,50 @@
[data {:keys [id]}] [data {:keys [id]}]
(d/dissoc-in data [:components id])) (d/dissoc-in data [:components id]))
(declare sync-page) (declare sync-component-shape)
(declare sync-shape-and-children)
(declare sync-shape)
(defmethod process-change :sync-library (defmethod process-change :update-component
[data id] [data {:keys [id shapes]}]
(cph/walk-pages (sync-page (:components data)) data)) (let [sync-component
(fn [component]
(update component :objects
#(d/mapm (partial sync-component-shape shapes) %)))]
(defn- sync-page (update-in data [:components id] sync-component)))
[components]
(fn [page-id page]
(let [linked-shapes
(cph/select-objects #(some? (:component-id %)) page)
updated-shapes (defn- sync-component-shape
(reduce [new-shapes _ component-shape]
(fn [updated-shapes linked-shape] (let [shape (d/seek #(= (:shape-ref %) (:id component-shape)) new-shapes)]
(let [component-id (:component-id linked-shape) (if (nil? shape)
component (get components component-id)] component-shape
(into updated-shapes (-> component-shape
(sync-shape-and-children linked-shape (d/assoc-when :content (:content shape))
component (d/assoc-when :fill-color (:fill-color shape))
(:objects page))))) (d/assoc-when :fill-color-ref-file (:fill-color-ref-file shape))
[] (d/assoc-when :fill-color-ref-id (:fill-color-ref-id shape))
linked-shapes)] (d/assoc-when :fill-opacity (:fill-opacity shape))
(d/assoc-when :font-family (:font-family shape))
(cph/update-object-list page updated-shapes)))) (d/assoc-when :font-size (:font-size shape))
(d/assoc-when :font-style (:font-style shape))
(defn- sync-shape-and-children (d/assoc-when :font-weight (:font-weight shape))
[linked-shape component objects] (d/assoc-when :letter-spacing (:letter-spacing shape))
(let [children (cph/get-children-objects (:id linked-shape) objects) (d/assoc-when :line-height (:line-height shape))
all-shapes (conj children linked-shape)] (d/assoc-when :proportion (:proportion shape))
(if (nil? component) (d/assoc-when :rx (:rx shape))
(map #(dissoc % :component-id :shape-ref) all-shapes) (d/assoc-when :ry (:ry shape))
(map #(sync-shape % (:objects component)) all-shapes)))) (d/assoc-when :stroke-color (:stroke-color shape))
(d/assoc-when :stroke-color-ref-file (:stroke-color-ref-file shape))
(defn- sync-shape (d/assoc-when :stroke-color-ref-id (:stroke-color-ref-id shape))
[shape component-objs] (d/assoc-when :stroke-opacity (:stroke-opacity shape))
(let [component-shape (get component-objs (:shape-ref shape))] (d/assoc-when :stroke-style (:stroke-style shape))
(if (nil? component-shape) (d/assoc-when :stroke-width (:stroke-width shape))
(assoc shape :shape-ref nil) (d/assoc-when :stroke-alignment (:stroke-alignment shape))
(-> shape (d/assoc-when :text-align (:text-align shape))
(d/update-when :content :content component-shape) (d/assoc-when :width (:width shape))
(d/update-when :fill-color :fill-color component-shape) (d/assoc-when :height (:height shape))
(d/update-when :fill-color-ref-file :fill-color-ref-file component-shape) (d/assoc-when :interactions (:interactions shape))
(d/update-when :fill-color-ref-id :fill-color-ref-id component-shape) (d/assoc-when :selrect (:selrect shape))
(d/update-when :fill-opacity :fill-opacity component-shape) (d/assoc-when :points (:points shape))))))
(d/update-when :font-family :font-family component-shape)
(d/update-when :font-size :font-size component-shape)
(d/update-when :font-style :font-style component-shape)
(d/update-when :font-weight :font-weight component-shape)
(d/update-when :letter-spacing :letter-spacing component-shape)
(d/update-when :line-height :line-height component-shape)
(d/update-when :proportion :proportion component-shape)
(d/update-when :rx :rx component-shape)
(d/update-when :ry :ry component-shape)
(d/update-when :cx :cx component-shape)
(d/update-when :cy :cy component-shape)
(d/update-when :x :x component-shape)
(d/update-when :y :y component-shape)
(d/update-when :exports :exports component-shape)
(d/update-when :stroke-color :stroke-color component-shape)
(d/update-when :stroke-color-ref-file :stroke-color-ref-file component-shape)
(d/update-when :stroke-color-ref-id :stroke-color-ref-id component-shape)
(d/update-when :stroke-opacity :stroke-opacity component-shape)
(d/update-when :stroke-style :stroke-style component-shape)
(d/update-when :stroke-width :stroke-width component-shape)
(d/update-when :stroke-alignment :stroke-alignment component-shape)
(d/update-when :text-align :text-align component-shape)
(d/update-when :width :width component-shape)
(d/update-when :height :height component-shape)
(d/update-when :interactions :interactions component-shape)
(d/update-when :selrect :selrect component-shape)
(d/update-when :points :points component-shape)))))
(defmethod process-operation :set (defmethod process-operation :set
[shape op] [shape op]

View file

@ -30,6 +30,16 @@
(update page :objects (update page :objects
#(into % (d/index-by :id objects-list)))) #(into % (d/index-by :id objects-list))))
(defn get-root-component
"Get the root shape linked to the component for this shape, if any"
[id objects]
(let [obj (get objects id)]
(if-let [component-id (:component-id obj)]
id
(if-let [parent-id (:parent-id obj)]
(get-root-component parent-id obj)
nil))))
(defn get-children (defn get-children
"Retrieve all children ids recursively for a given object" "Retrieve all children ids recursively for a given object"
[id objects] [id objects]
@ -43,6 +53,26 @@
[id objects] [id objects]
(map #(get objects %) (get-children id objects))) (map #(get objects %) (get-children id objects)))
(defn get-object-with-children
"Retrieve a list with an object and all of its children"
[id objects]
(map #(get objects %) (concat [id] (get-children id objects))))
(defn walk-children
"Go through an object and all the children tree, and apply a
function to each one. Return the list of changed objects."
[id f objects]
(let [obj (get objects id)]
(if (nil? (:shapes obj))
[(apply f obj)]
(loop [children (map #(get objects %) (:shapes obj))
updated-children []]
(if (empty? children)
updated-children
(let [child (first children)]
(recur (rest children)
(concat [(apply f child)] updated-children))))))))
(defn is-shape-grouped (defn is-shape-grouped
"Checks if a shape is inside a group" "Checks if a shape is inside a group"
[shape-id objects] [shape-id objects]
@ -136,3 +166,54 @@
(lazy-seq (loopfn (rest ids))))))] (lazy-seq (loopfn (rest ids))))))]
(loopfn (:shapes root)))) (loopfn (:shapes root))))
(defn clone-object
"Gets a copy of the object and all its children, with new ids
and with the parent-children links correctly set. Admits functions
to make more transformations to the cloned objects and the
original ones.
Returns the cloned object, the list of all new objects (including
the cloned one), and possibly a list of original objects modified."
([object parent-id objects xf-new-object]
(clone-object object parent-id objects xf-new-object identity))
([object parent-id objects xf-new-object xf-original-object]
(let [new-id (uuid/next)]
(loop [child-ids (seq (:shapes object))
new-direct-children []
new-children []
updated-children []]
(if (empty? child-ids)
(let [new-object (cond-> object
true
(assoc :id new-id
:parent-id parent-id)
(some? (:shapes object))
(assoc :shapes (map :id new-direct-children)))
new-object (xf-new-object new-object object)
new-objects (concat [new-object] new-children)
updated-object (xf-original-object object new-object)
updated-objects (if (= object updated-object)
updated-children
(concat [updated-object] updated-children))]
[new-object new-objects updated-objects])
(let [child-id (first child-ids)
child (get objects child-id)
[new-child new-child-objects updated-child-objects]
(clone-object child new-id objects xf-new-object xf-original-object)]
(recur
(next child-ids)
(concat new-direct-children [new-child])
(concat new-children new-child-objects)
(concat updated-children updated-child-objects))))))))

View file

@ -48,10 +48,6 @@
(s/def ::set-of-string (s/def ::set-of-string
(s/every string? :kind set?)) (s/every string? :kind set?))
;; --- Expose inner functions
(defn interrupt? [e] (= e :interrupt))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Workspace Initialization ;; Workspace Initialization
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -956,7 +952,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(->> stream (->> stream
(rx/filter interrupt?) (rx/filter dwc/interrupt?)
(rx/take 1) (rx/take 1)
(rx/map (constantly clear-edition-mode)))))) (rx/map (constantly clear-edition-mode))))))
@ -985,7 +981,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(let [cancel-event? (fn [event] (let [cancel-event? (fn [event]
(interrupt? event)) (dwc/interrupt? event))
stoper (rx/filter (ptk/type? ::clear-drawing) stream)] stoper (rx/filter (ptk/type? ::clear-drawing) stream)]
(->> (rx/filter cancel-event? stream) (->> (rx/filter cancel-event? stream)
(rx/take 1) (rx/take 1)

View file

@ -44,6 +44,11 @@
([state page-id] ([state page-id]
(get-in state [:workspace-data :pages-index page-id :options]))) (get-in state [:workspace-data :pages-index page-id :options])))
(defn interrupt? [e] (= e :interrupt))
(defn lookup-component-objects
([state component-id]
(get-in state [:workspace-data :components component-id :objects])))
;; --- Changes Handling ;; --- Changes Handling
@ -454,3 +459,4 @@
objects (lookup-page-objects state page-id) objects (lookup-page-objects state page-id)
[rchanges uchanges] (impl-gen-changes objects page-id (seq ids))] [rchanges uchanges] (impl-gen-changes objects page-id (seq ids))]
(rx/of (commit-changes rchanges uchanges {:commit-local? true}))))))) (rx/of (commit-changes rchanges uchanges {:commit-local? true})))))))

View file

@ -12,11 +12,15 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.common.pages-helpers :as cph]
[app.common.geom.point :as gpt]
[app.common.geom.shapes :as geom]
[app.main.data.workspace.common :as dwc] [app.main.data.workspace.common :as dwc]
[app.main.data.workspace.selection :as dws] [app.main.data.workspace.selection :as dws]
[app.common.pages :as cp] [app.common.pages :as cp]
[app.main.repo :as rp] [app.main.repo :as rp]
[app.main.store :as st] [app.main.store :as st]
[app.main.streams :as ms]
[app.util.color :as color] [app.util.color :as color]
[app.util.i18n :refer [tr]] [app.util.i18n :refer [tr]]
[beicon.core :as rx] [beicon.core :as rx]
@ -107,7 +111,7 @@
:object prev}] :object prev}]
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true})))))) (rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true}))))))
(declare clone-shape) (declare make-component-shape)
(def add-component (def add-component
(ptk/reify ::add-component (ptk/reify ::add-component
@ -127,7 +131,7 @@
(dws/prepare-create-group page-id shapes "Component-" true)) (dws/prepare-create-group page-id shapes "Component-" true))
[new-shape new-shapes updated-shapes] [new-shape new-shapes updated-shapes]
(clone-shape group nil objects) (make-component-shape group nil objects)
rchanges (conj rchanges rchanges (conj rchanges
{:type :add-component {:type :add-component
@ -168,59 +172,23 @@
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
(dws/select-shapes (d/ordered-set (:id group)))))))))) (dws/select-shapes (d/ordered-set (:id group))))))))))
(defn- clone-shape (defn- make-component-shape
"Clone the shape and all children. Generate new ids and detach "Clone the shape and all children. Generate new ids and detach
from parent and frame. Update the original shapes to have links from parent and frame. Update the original shapes to have links
to the new ones." to the new ones."
[shape parent-id objects] [shape parent-id objects]
(let [new-id (uuid/next)] (let [xf-new-shape (fn [new-shape original-shape]
(if (nil? (:shapes shape)) (assoc new-shape :frame-id nil))
; TODO: unify this case with the empty child-ids case. xf-original-shape (fn [original-shape new-shape]
(let [new-shape (assoc shape (cond-> original-shape
:id new-id true
:parent-id parent-id (assoc :shape-ref (:id new-shape))
:frame-id nil)
new-shapes [new-shape] (nil? (:parent-id new-shape))
(assoc :component-id (:id new-shape))))]
updated-shapes [(cond-> shape (cph/clone-object shape parent-id objects xf-new-shape xf-original-shape)))
true (assoc :shape-ref (:id new-shape))
(nil? parent-id) (assoc :component-id (:id new-shape)))]]
[new-shape new-shapes updated-shapes])
(loop [child-ids (seq (:shapes shape))
new-children []
updated-children []]
(if (empty? child-ids)
(let [new-shape (assoc shape
:id new-id
:parent-id parent-id
:frame-id nil
:shapes (map :id new-children))
new-shapes (conj new-children new-shape)
updated-shapes
(conj updated-children
(cond-> shape
true (assoc :shape-ref (:id new-shape))
(nil? parent-id) (assoc :component-id (:id new-shape))))]
[new-shape new-shapes updated-shapes])
(let [child-id (first child-ids)
child (get objects child-id)
[new-child new-child-shapes updated-child-shapes]
(clone-shape child new-id objects)]
(recur
(next child-ids)
(into new-children new-child-shapes)
(into updated-children updated-child-shapes))))))))
(defn delete-component (defn delete-component
[{:keys [id] :as params}] [{:keys [id] :as params}]
@ -241,3 +209,145 @@
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
(defn instantiate-component
[id]
(us/assert ::us/uuid id)
(ptk/reify ::instantiate-component
ptk/WatchEvent
(watch [_ state stream]
(let [component (get-in state [:workspace-data :components id])
component-shape (get-in component [:objects (:id component)])
orig-pos (gpt/point (:x component-shape) (:y component-shape))
mouse-pos @ms/mouse-position
delta (gpt/subtract mouse-pos orig-pos)
_ (js/console.log "orig-pos" (clj->js orig-pos))
_ (js/console.log "mouse-pos" (clj->js mouse-pos))
_ (js/console.log "delta" (clj->js delta))
page-id (:current-page-id state)
objects (dwc/lookup-page-objects state page-id)
unames (dwc/retrieve-used-names objects)
all-frames (cph/select-frames objects)
xf-new-shape
(fn [new-shape original-shape]
(let [new-name ;; TODO: ojoooooooooo
(dwc/generate-unique-name unames (:name new-shape))]
(cond-> new-shape
true
(as-> $
(assoc $ :name new-name)
(geom/move $ delta)
(assoc $ :frame-id
(dwc/calculate-frame-overlap all-frames $))
(assoc $ :parent-id
(or (:parent-id $) (:frame-id $)))
(assoc $ :shape-ref (:id original-shape)))
(nil? (:parent-id original-shape))
(assoc :component-id (:id original-shape)))))
[new-shape new-shapes _]
(cph/clone-object component-shape
nil
(get component :objects)
xf-new-shape)
rchanges (map (fn [obj]
{:type :add-obj
:id (:id obj)
:page-id page-id
:frame-id (:frame-id obj)
:parent-id (:parent-id obj)
:obj obj})
new-shapes)
uchanges (map (fn [obj]
{:type :del-obj
:id (:id obj)
:page-id page-id})
new-shapes)]
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
(dws/select-shapes (d/ordered-set (:id new-shape))))))))
(defn detach-component
[id]
(us/assert ::us/uuid id)
(ptk/reify ::detach-component
ptk/WatchEvent
(watch [_ state stream]
(let [page-id (:current-page-id state)
objects (dwc/lookup-page-objects state page-id)
root-id (cph/get-root-component id objects)
shapes (cph/get-object-with-children root-id objects)
rchanges (map (fn [obj]
{:type :mod-obj
:page-id page-id
:id (:id obj)
:operations [{:type :set
:attr :component-id
:val nil}
{:type :set
:attr :shape-ref
:val nil}]})
shapes)
uchanges (map (fn [obj]
{:type :mod-obj
:page-id page-id
:id (:id obj)
:operations [{:type :set
:attr :component-id
:val (:component-id obj)}
{:type :set
:attr :shape-ref
:val (:shape-ref obj)}]})
shapes)]
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
(defn reset-component
[id]
[id]
(us/assert ::us/uuid id)
(ptk/reify ::reset-component
ptk/WatchEvent
(watch [_ state stream]
)))
(defn update-component
[id]
[id]
(us/assert ::us/uuid id)
(ptk/reify ::update-component
ptk/WatchEvent
(watch [_ state stream]
(let [page-id (:current-page-id state)
objects (dwc/lookup-page-objects state page-id)
root-id (cph/get-root-component id objects)
root-shape (get objects id)
component-id (get root-shape :component-id)
component-objs (dwc/lookup-component-objects state component-id)
shapes (cph/get-object-with-children root-id objects)
rchanges [{:type :update-component
:id component-id
:shapes shapes}
{:type :sync-library
:id (get-in state [:workspace-file :id])}]
uchanges [{:type :update-component
:id component-id
:shapes (vals component-objs)}]]
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))

View file

@ -33,33 +33,6 @@
(s/def ::set-of-string (s/def ::set-of-string
(s/every string? :kind set?)) (s/every string? :kind set?))
;; Duplicate from workspace.
;; FIXME: Move these functions to a common place
(defn interrupt? [e] (= e :interrupt))
(defn- retrieve-used-names
[objects]
(into #{} (map :name) (vals objects)))
(defn- extract-numeric-suffix
[basename]
(if-let [[match p1 p2] (re-find #"(.*)-([0-9]+)$" basename)]
[p1 (+ 1 (d/parse-integer p2))]
[basename 1]))
(defn- generate-unique-name
"A unique name generator"
[used basename]
(s/assert ::set-of-string used)
(s/assert ::us/string basename)
(let [[prefix initial] (extract-numeric-suffix basename)]
(loop [counter initial]
(let [candidate (str prefix "-" counter)]
(if (contains? used candidate)
(recur (inc counter))
candidate)))))
;; --- Selection Rect ;; --- Selection Rect
(declare select-shapes-by-current-selrect) (declare select-shapes-by-current-selrect)
@ -88,7 +61,7 @@
(ptk/reify ::handle-selection (ptk/reify ::handle-selection
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
(let [stoper (rx/filter #(or (interrupt? %) (let [stoper (rx/filter #(or (dwc/interrupt? %)
(ms/mouse-up? %)) (ms/mouse-up? %))
stream)] stream)]
(rx/concat (rx/concat
@ -198,7 +171,9 @@
(let [selrect (geom/selection-rect shapes) (let [selrect (geom/selection-rect shapes)
frame-id (-> shapes first :frame-id) frame-id (-> shapes first :frame-id)
parent-id (-> shapes first :parent-id) parent-id (-> shapes first :parent-id)
group-name (if (and keep-name (= (count shapes) 1)) group-name (if (and keep-name
(= (count shapes) 1)
(= (:type (first shapes)) :group))
(:name (first shapes)) (:name (first shapes))
(name (gensym prefix)))] (name (gensym prefix)))]
(-> (cp/make-minimal-group frame-id selrect group-name) (-> (cp/make-minimal-group frame-id selrect group-name)
@ -298,7 +273,7 @@
(defn- prepare-duplicate-shape-change (defn- prepare-duplicate-shape-change
[objects page-id names obj delta frame-id parent-id] [objects page-id names obj delta frame-id parent-id]
(let [id (uuid/next) (let [id (uuid/next)
name (generate-unique-name names (:name obj)) name (dwc/generate-unique-name names (:name obj))
renamed-obj (assoc obj :id id :name name) renamed-obj (assoc obj :id id :name name)
moved-obj (geom/move renamed-obj delta) moved-obj (geom/move renamed-obj delta)
frames (cph/select-frames objects) frames (cph/select-frames objects)
@ -338,7 +313,7 @@
(defn- prepare-duplicate-frame-change (defn- prepare-duplicate-frame-change
[objects page-id names obj delta] [objects page-id names obj delta]
(let [frame-id (uuid/next) (let [frame-id (uuid/next)
frame-name (generate-unique-name names (:name obj)) frame-name (dwc/generate-unique-name names (:name obj))
sch (->> (map #(get objects %) (:shapes obj)) sch (->> (map #(get objects %) (:shapes obj))
(mapcat #(prepare-duplicate-shape-change objects page-id names % delta frame-id frame-id))) (mapcat #(prepare-duplicate-shape-change objects page-id names % delta frame-id frame-id)))
@ -367,7 +342,7 @@
selected (get-in state [:workspace-local :selected]) selected (get-in state [:workspace-local :selected])
delta (gpt/point 0 0) delta (gpt/point 0 0)
unames (retrieve-used-names objects) unames (dwc/retrieve-used-names objects)
rchanges (prepare-duplicate-changes objects page-id unames selected delta) rchanges (prepare-duplicate-changes objects page-id unames selected delta)
uchanges (mapv #(array-map :type :del-obj :page-id page-id :id (:id %)) uchanges (mapv #(array-map :type :del-obj :page-id page-id :id (:id %))

View file

@ -61,7 +61,10 @@
do-unlock-shape #(st/emit! (dw/update-shape-flags id {:blocked false})) do-unlock-shape #(st/emit! (dw/update-shape-flags id {:blocked false}))
do-create-group #(st/emit! dw/group-selected) do-create-group #(st/emit! dw/group-selected)
do-remove-group #(st/emit! dw/ungroup-selected) do-remove-group #(st/emit! dw/ungroup-selected)
do-add-component #(st/emit! dwl/add-component)] do-add-component #(st/emit! dwl/add-component)
do-detach-component #(st/emit! (dwl/detach-component id))
do-reset-component #(st/emit! (dwl/reset-component id))
do-update-component #(st/emit! (dwl/update-component id))]
[:* [:*
[:& menu-entry {:title "Copy" [:& menu-entry {:title "Copy"
:shortcut "Ctrl + c" :shortcut "Ctrl + c"
@ -110,9 +113,18 @@
:on-click do-lock-shape}]) :on-click do-lock-shape}])
[:& menu-separator] [:& menu-separator]
[:& menu-entry {:title "Create component"
:shortcut "Ctrl + K" (if (nil? (:shape-ref shape))
:on-click do-add-component}] [:& menu-entry {:title "Create component"
:shortcut "Ctrl + K"
:on-click do-add-component}]
[:*
[:& menu-entry {:title "Detach instance"
:on-click do-detach-component}]
[:& menu-entry {:title "Reset overrides"
:on-click do-reset-component}]
[:& menu-entry {:title "Update master component"
:on-click do-update-component}]])
[:& menu-separator] [:& menu-separator]
[:& menu-entry {:title "Delete" [:& menu-entry {:title "Delete"

View file

@ -69,8 +69,8 @@
on-drag-start on-drag-start
(mf/use-callback (mf/use-callback
(fn [path event] (fn [component-id event]
(dnd/set-data! event "text/uri-list" (cfg/resolve-media-path path)) (dnd/set-data! event "app/component" component-id)
(dnd/set-allowed-effect! event "move")))] (dnd/set-allowed-effect! event "move")))]
[:div.asset-group [:div.asset-group
@ -82,7 +82,7 @@
[:div.grid-cell {:key (:id component) [:div.grid-cell {:key (:id component)
:draggable true :draggable true
:on-context-menu (on-context-menu (:id component)) :on-context-menu (on-context-menu (:id component))
:on-drag-start (partial on-drag-start (:path component))} :on-drag-start (partial on-drag-start (:id component))}
[:& exports/component-svg {:group (get-in component [:objects (:id component)]) [:& exports/component-svg {:group (get-in component [:objects (:id component)])
:objects (:objects component)}] :objects (:objects component)}]
[:div.cell-name (:name component)]]) [:div.cell-name (:name component)]])

View file

@ -22,6 +22,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.main.constants :as c] [app.main.constants :as c]
[app.main.data.workspace :as dw] [app.main.data.workspace :as dw]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.drawing :as dd] [app.main.data.workspace.drawing :as dd]
[app.main.data.colors :as dwc] [app.main.data.colors :as dwc]
[app.main.data.fetch :as mdf] [app.main.data.fetch :as mdf]
@ -454,6 +455,7 @@
on-drag-enter on-drag-enter
(fn [e] (fn [e]
(when (or (dnd/has-type? e "app/shape") (when (or (dnd/has-type? e "app/shape")
(dnd/has-type? e "app/component")
(dnd/has-type? e "Files") (dnd/has-type? e "Files")
(dnd/has-type? e "text/uri-list")) (dnd/has-type? e "text/uri-list"))
(dom/prevent-default e))) (dom/prevent-default e)))
@ -461,6 +463,7 @@
on-drag-over on-drag-over
(fn [e] (fn [e]
(when (or (dnd/has-type? e "app/shape") (when (or (dnd/has-type? e "app/shape")
(dnd/has-type? e "app/component")
(dnd/has-type? e "Files") (dnd/has-type? e "Files")
(dnd/has-type? e "text/uri-list")) (dnd/has-type? e "text/uri-list"))
(dom/prevent-default e))) (dom/prevent-default e)))
@ -491,6 +494,10 @@
(assoc :x final-x) (assoc :x final-x)
(assoc :y final-y))))) (assoc :y final-y)))))
(dnd/has-type? event "app/component")
(let [component-id (dnd/get-data event "app/component")]
(st/emit! (dwl/instantiate-component component-id)))
(dnd/has-type? event "text/uri-list") (dnd/has-type? event "text/uri-list")
(let [data (dnd/get-data event "text/uri-list") (let [data (dnd/get-data event "text/uri-list")
lines (str/lines data) lines (str/lines data)