mirror of
https://github.com/penpot/penpot.git
synced 2025-01-26 08:29:42 -05:00
✨ Improve canvas handling on sitemap and workspace.
This commit is contained in:
parent
3d8b3f3040
commit
31ffa73bda
8 changed files with 247 additions and 141 deletions
|
@ -11,7 +11,7 @@
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[uxbox.main.repo :as rp]
|
[uxbox.main.repo :as rp]
|
||||||
[uxbox.util.data :refer [index-by-id]]
|
[uxbox.util.data :refer [index-by-id concatv]]
|
||||||
[uxbox.util.spec :as us]
|
[uxbox.util.spec :as us]
|
||||||
[uxbox.util.timers :as ts]
|
[uxbox.util.timers :as ts]
|
||||||
[uxbox.util.uuid :as uuid]))
|
[uxbox.util.uuid :as uuid]))
|
||||||
|
@ -97,7 +97,8 @@
|
||||||
(letfn [(pack-shapes [ids]
|
(letfn [(pack-shapes [ids]
|
||||||
(mapv #(get-in state [:shapes %]) ids))]
|
(mapv #(get-in state [:shapes %]) ids))]
|
||||||
(let [page (get-in state [:pages id])
|
(let [page (get-in state [:pages id])
|
||||||
data {:shapes (pack-shapes (:shapes page))}]
|
data {:shapes (pack-shapes (concatv (:canvas page)
|
||||||
|
(:shapes page)))}]
|
||||||
(-> page
|
(-> page
|
||||||
(assoc :data data)
|
(assoc :data data)
|
||||||
(dissoc :shapes)))))
|
(dissoc :shapes)))))
|
||||||
|
@ -106,13 +107,20 @@
|
||||||
"Unpacks packed page object and assocs it to the
|
"Unpacks packed page object and assocs it to the
|
||||||
provided state."
|
provided state."
|
||||||
[state {:keys [id data] :as page}]
|
[state {:keys [id data] :as page}]
|
||||||
(let [shapes-data (:shapes data [])
|
(let [shapes-list (:shapes data [])
|
||||||
shapes (mapv :id shapes-data)
|
|
||||||
shapes-map (index-by-id shapes-data)
|
shapes (->> shapes-list
|
||||||
|
(filter #(not= :canvas (:type %)))
|
||||||
|
(mapv :id))
|
||||||
|
canvas (->> shapes-list
|
||||||
|
(filter #(= :canvas (:type %)))
|
||||||
|
(mapv :id))
|
||||||
|
|
||||||
|
shapes-map (index-by-id shapes-list)
|
||||||
|
|
||||||
page (-> page
|
page (-> page
|
||||||
(dissoc :data)
|
(dissoc :data)
|
||||||
(assoc :shapes shapes))]
|
(assoc :shapes shapes :canvas canvas))]
|
||||||
(-> state
|
(-> state
|
||||||
(update :shapes merge shapes-map)
|
(update :shapes merge shapes-map)
|
||||||
(update :pages assoc id page))))
|
(update :pages assoc id page))))
|
||||||
|
|
|
@ -113,9 +113,11 @@
|
||||||
:page page
|
:page page
|
||||||
:id shape-id
|
:id shape-id
|
||||||
:name shape-name)]
|
:name shape-name)]
|
||||||
(-> state
|
(as-> state $
|
||||||
(update-in [:pages page :shapes] #(into [] (cons shape-id %)))
|
(if (= :canvas (:type shape))
|
||||||
(assoc-in [:shapes shape-id] shape))))
|
(update-in $ [:pages page :canvas] conj shape-id)
|
||||||
|
(update-in $ [:pages page :shapes] conj shape-id))
|
||||||
|
(assoc-in $ [:shapes shape-id] shape))))
|
||||||
|
|
||||||
(defn duplicate-shapes'
|
(defn duplicate-shapes'
|
||||||
([state shapes page]
|
([state shapes page]
|
||||||
|
|
|
@ -553,7 +553,7 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:shapes id :name] name))))
|
(assoc-in state [:shapes id :name] name))))
|
||||||
|
|
||||||
;; --- Change Shape Order (Ordering)
|
;; --- Change Shape Order (D&D Ordering)
|
||||||
|
|
||||||
(defn change-shape-order
|
(defn change-shape-order
|
||||||
[{:keys [id index] :as params}]
|
[{:keys [id index] :as params}]
|
||||||
|
@ -568,6 +568,22 @@
|
||||||
shapes (vec (concat before [id] after))]
|
shapes (vec (concat before [id] after))]
|
||||||
(assoc-in state [:pages page-id :shapes] shapes)))))
|
(assoc-in state [:pages page-id :shapes] shapes)))))
|
||||||
|
|
||||||
|
;; --- Change Canvas Order (D&D Ordering)
|
||||||
|
|
||||||
|
(defn change-canvas-order
|
||||||
|
[{:keys [id index] :as params}]
|
||||||
|
(s/assert ::us/uuid id)
|
||||||
|
(s/assert ::us/number index)
|
||||||
|
(reify
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [page-id (get-in state [:shapes id :page])
|
||||||
|
canvas (get-in state [:pages page-id :canvas])
|
||||||
|
canvas (into [] (remove #(= % id)) canvas)
|
||||||
|
[before after] (split-at index canvas)
|
||||||
|
canvas (vec (concat before [id] after))]
|
||||||
|
(assoc-in state [:pages page-id :canvas] canvas)))))
|
||||||
|
|
||||||
;; --- Shape Transformations
|
;; --- Shape Transformations
|
||||||
|
|
||||||
(defn initial-shape-align
|
(defn initial-shape-align
|
||||||
|
@ -619,6 +635,32 @@
|
||||||
#(update-in % [:shapes id] dissoc :modifier-mtx)
|
#(update-in % [:shapes id] dissoc :modifier-mtx)
|
||||||
::udp/page-update))))))
|
::udp/page-update))))))
|
||||||
|
|
||||||
|
(defn rehash-shape-relationship
|
||||||
|
"Checks shape overlaping with existing canvas, if one or more
|
||||||
|
overlaps, assigns the shape to the first one."
|
||||||
|
[id]
|
||||||
|
(s/assert ::us/uuid id)
|
||||||
|
(letfn [(overlaps? [canvas shape]
|
||||||
|
(let [shape1 (geom/shape->rect-shape canvas)
|
||||||
|
shape2 (geom/shape->rect-shape shape)]
|
||||||
|
(geom/overlaps? shape1 shape2)))]
|
||||||
|
(reify
|
||||||
|
ptk/EventType
|
||||||
|
(type [_] ::rehash-shape-relationship)
|
||||||
|
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [shape (get-in state [:shapes id])
|
||||||
|
xform (comp (map #(get-in state [:shapes %]))
|
||||||
|
(filter #(overlaps? % shape))
|
||||||
|
(take 1))
|
||||||
|
canvas (->> (get-in state [:pages (:page shape) :canvas])
|
||||||
|
(sequence xform)
|
||||||
|
(first))]
|
||||||
|
(if canvas
|
||||||
|
(update-in state [:shapes id] assoc :canvas (:id canvas))
|
||||||
|
(update-in state [:shapes id] assoc :canvas nil)))))))
|
||||||
|
|
||||||
;; --- Start shape "edition mode"
|
;; --- Start shape "edition mode"
|
||||||
|
|
||||||
(defn start-edition-mode
|
(defn start-edition-mode
|
||||||
|
@ -777,79 +819,49 @@
|
||||||
|
|
||||||
;; --- Shape Visibility
|
;; --- Shape Visibility
|
||||||
|
|
||||||
(deftype HideShape [id]
|
(defn set-hidden-attr
|
||||||
udp/IPageUpdate
|
[id value]
|
||||||
ptk/UpdateEvent
|
(s/assert ::us/uuid id)
|
||||||
(update [_ state]
|
(s/assert ::us/boolean value)
|
||||||
(letfn [(mark-hidden [state id]
|
(letfn [(impl-set-hidden [state id]
|
||||||
(let [shape (get-in state [:shapes id])]
|
(let [{:keys [type] :as shape} (get-in state [:shapes id])]
|
||||||
(if (= :group (:type shape))
|
(as-> state $
|
||||||
(as-> state $
|
(assoc-in $ [:shapes id :hidden] value)
|
||||||
(assoc-in $ [:shapes id :hidden] true)
|
(if (= :canvas type)
|
||||||
(reduce mark-hidden $ (:items shape)))
|
(let [shapes (get-in state [:pages (:page shape) :shapes])
|
||||||
(assoc-in state [:shapes id :hidden] true))))]
|
xform (comp (map #(get-in state [:shapes %]))
|
||||||
(mark-hidden state id))))
|
(filter #(= id (:canvas %)))
|
||||||
|
(map :id))]
|
||||||
(defn hide-shape
|
(reduce impl-set-hidden $ (sequence xform shapes)))
|
||||||
[id]
|
$))))]
|
||||||
{:pre [(uuid? id)]}
|
(reify
|
||||||
(HideShape. id))
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
(deftype ShowShape [id]
|
(update [_ state]
|
||||||
udp/IPageUpdate
|
(impl-set-hidden state id)))))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(letfn [(mark-visible [state id]
|
|
||||||
(let [shape (get-in state [:shapes id])]
|
|
||||||
(if (= :group (:type shape))
|
|
||||||
(as-> state $
|
|
||||||
(assoc-in $ [:shapes id :hidden] false)
|
|
||||||
(reduce mark-visible $ (:items shape)))
|
|
||||||
(assoc-in state [:shapes id :hidden] false))))]
|
|
||||||
(mark-visible state id))))
|
|
||||||
|
|
||||||
(defn show-shape
|
|
||||||
[id]
|
|
||||||
{:pre [(uuid? id)]}
|
|
||||||
(ShowShape. id))
|
|
||||||
|
|
||||||
;; --- Shape Blocking
|
;; --- Shape Blocking
|
||||||
|
|
||||||
(deftype BlockShape [id]
|
(defn set-blocked-attr
|
||||||
udp/IPageUpdate
|
[id value]
|
||||||
ptk/UpdateEvent
|
(s/assert ::us/uuid id)
|
||||||
(update [_ state]
|
(s/assert ::us/boolean value)
|
||||||
(letfn [(mark-blocked [state id]
|
(letfn [(impl-set-blocked [state id]
|
||||||
(let [shape (get-in state [:shapes id])]
|
(let [{:keys [type] :as shape} (get-in state [:shapes id])]
|
||||||
(if (= :group (:type shape))
|
(as-> state $
|
||||||
(as-> state $
|
(assoc-in $ [:shapes id :blocked] value)
|
||||||
(assoc-in $ [:shapes id :blocked] true)
|
(if (= :canvas type)
|
||||||
(reduce mark-blocked $ (:items shape)))
|
(let [shapes (get-in state [:pages (:page shape) :shapes])
|
||||||
(assoc-in state [:shapes id :blocked] true))))]
|
xform (comp (map #(get-in state [:shapes %]))
|
||||||
(mark-blocked state id))))
|
(filter #(= id (:canvas %)))
|
||||||
|
(map :id))]
|
||||||
(defn block-shape
|
(reduce impl-set-blocked $ (sequence xform shapes)))
|
||||||
[id]
|
$))))]
|
||||||
{:pre [(uuid? id)]}
|
(reify
|
||||||
(BlockShape. id))
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
(deftype UnblockShape [id]
|
(update [_ state]
|
||||||
udp/IPageUpdate
|
(impl-set-blocked state id)))))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(letfn [(mark-unblocked [state id]
|
|
||||||
(let [shape (get-in state [:shapes id])]
|
|
||||||
(if (= :group (:type shape))
|
|
||||||
(as-> state $
|
|
||||||
(assoc-in $ [:shapes id :blocked] false)
|
|
||||||
(reduce mark-unblocked $ (:items shape)))
|
|
||||||
(assoc-in state [:shapes id :blocked] false))))]
|
|
||||||
(mark-unblocked state id))))
|
|
||||||
|
|
||||||
(defn unblock-shape
|
|
||||||
[id]
|
|
||||||
{:pre [(uuid? id)]}
|
|
||||||
(UnblockShape. id))
|
|
||||||
|
|
||||||
;; --- Shape Locking
|
;; --- Shape Locking
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,8 @@
|
||||||
[{:keys [status] :as error}]
|
[{:keys [status] :as error}]
|
||||||
(js/console.error "Unhandled Error:"
|
(js/console.error "Unhandled Error:"
|
||||||
"\n - message:" (ex-message error)
|
"\n - message:" (ex-message error)
|
||||||
"\n - data:" (pr-str (ex-data error))
|
"\n - data:" (pr-str (ex-data error)))
|
||||||
"\n - stack:" (.-stack error))
|
(js/console.error error)
|
||||||
(reset! st/loader false)
|
(reset! st/loader false)
|
||||||
(cond
|
(cond
|
||||||
;; Unauthorized or Auth timeout
|
;; Unauthorized or Auth timeout
|
||||||
|
|
|
@ -33,7 +33,8 @@
|
||||||
(->> uws/mouse-position-deltas
|
(->> uws/mouse-position-deltas
|
||||||
(rx/map #(dw/apply-temporal-displacement id %))
|
(rx/map #(dw/apply-temporal-displacement id %))
|
||||||
(rx/take-until stoper))
|
(rx/take-until stoper))
|
||||||
(rx/of (dw/materialize-current-modifier id)))))))
|
(rx/of (dw/materialize-current-modifier id)
|
||||||
|
(dw/rehash-shape-relationship id)))))))
|
||||||
|
|
||||||
(def start-move-selected
|
(def start-move-selected
|
||||||
(reify
|
(reify
|
||||||
|
|
|
@ -17,10 +17,14 @@
|
||||||
[uxbox.main.ui.keyboard :as kbd]
|
[uxbox.main.ui.keyboard :as kbd]
|
||||||
[uxbox.main.ui.shapes.icon :as icon]
|
[uxbox.main.ui.shapes.icon :as icon]
|
||||||
[uxbox.main.ui.workspace.sortable :refer [use-sortable]]
|
[uxbox.main.ui.workspace.sortable :refer [use-sortable]]
|
||||||
[uxbox.util.data :refer [classnames]]
|
[uxbox.util.data :refer [classnames enumerate]]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.util.i18n :refer (tr)]))
|
[uxbox.util.i18n :refer (tr)]))
|
||||||
|
|
||||||
|
(def ^:private shapes-iref
|
||||||
|
(-> (l/key :shapes)
|
||||||
|
(l/derive st/state)))
|
||||||
|
|
||||||
;; --- Helpers
|
;; --- Helpers
|
||||||
|
|
||||||
(defn- element-icon
|
(defn- element-icon
|
||||||
|
@ -76,21 +80,13 @@
|
||||||
[{:keys [shape selected index] :as props}]
|
[{:keys [shape selected index] :as props}]
|
||||||
(letfn [(toggle-blocking [event]
|
(letfn [(toggle-blocking [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [id (:id shape)
|
(let [{:keys [id blocked]} shape]
|
||||||
blocked? (:blocked shape)]
|
(st/emit! (dw/set-blocked-attr id (not blocked)))))
|
||||||
(if blocked?
|
|
||||||
(st/emit! (dw/unblock-shape id))
|
|
||||||
(st/emit! (dw/block-shape id)))))
|
|
||||||
|
|
||||||
(toggle-visibility [event]
|
(toggle-visibility [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [id (:id shape)
|
(let [{:keys [id hidden]} shape]
|
||||||
hidden? (:hidden shape)]
|
(st/emit! (dw/set-hidden-attr id (not hidden)))))
|
||||||
(if hidden?
|
|
||||||
(st/emit! (dw/show-shape id))
|
|
||||||
(st/emit! (dw/hide-shape id)))
|
|
||||||
(when (contains? selected id)
|
|
||||||
(st/emit! (dw/select-shape id)))))
|
|
||||||
|
|
||||||
(select-shape [event]
|
(select-shape [event]
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
|
@ -115,7 +111,7 @@
|
||||||
|
|
||||||
(on-hover [item monitor]
|
(on-hover [item monitor]
|
||||||
(st/emit! (dw/change-shape-order {:id (:shape-id item)
|
(st/emit! (dw/change-shape-order {:id (:shape-id item)
|
||||||
:index index})))]
|
:index index})))]
|
||||||
(let [selected? (contains? selected (:id shape))
|
(let [selected? (contains? selected (:id shape))
|
||||||
[dprops dnd-ref] (use-sortable
|
[dprops dnd-ref] (use-sortable
|
||||||
{:type "layer-item"
|
{:type "layer-item"
|
||||||
|
@ -141,65 +137,129 @@
|
||||||
[:div.element-icon (element-icon shape)]
|
[:div.element-icon (element-icon shape)]
|
||||||
[:& layer-name {:shape shape}]]])))
|
[:& layer-name {:shape shape}]]])))
|
||||||
|
|
||||||
|
(mf/defc canvas-item
|
||||||
|
[{:keys [canvas shapes selected index] :as props}]
|
||||||
|
(letfn [(toggle-blocking [event]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(let [{:keys [id blocked]} canvas]
|
||||||
|
(st/emit! (dw/set-blocked-attr id (not blocked)))))
|
||||||
|
|
||||||
;; --- Layer Canvas
|
(toggle-visibility [event]
|
||||||
|
(dom/stop-propagation event)
|
||||||
|
(let [{:keys [id hidden]} canvas]
|
||||||
|
(st/emit! (dw/set-hidden-attr id (not hidden)))))
|
||||||
|
|
||||||
;; (mf/defc layer-canvas
|
(select-shape [event]
|
||||||
;; [{:keys [canvas selected index] :as props}]
|
(dom/prevent-default event)
|
||||||
;; (letfn [(select-shape [event]
|
(let [id (:id canvas)]
|
||||||
;; (dom/prevent-default event)
|
(cond
|
||||||
;; (st/emit! (dw/select-canvas (:id canvas))))
|
(or (:blocked canvas)
|
||||||
;; (let [selected? (contains? selected (:id shape))]
|
(:hidden canvas))
|
||||||
;; [:li {:class (classnames
|
nil
|
||||||
;; :selected selected?)}
|
|
||||||
;; [:div.element-list-body {:class (classnames :selected selected?)
|
(.-ctrlKey event)
|
||||||
;; :on-click select-shape
|
(st/emit! (dw/select-shape id))
|
||||||
;; :on-double-click #(dom/stop-propagation %)
|
|
||||||
;; :draggable true}
|
(> (count selected) 1)
|
||||||
;; [:div.element-actions
|
(st/emit! (dw/deselect-all)
|
||||||
;; [:div.toggle-element {:class (when-not (:hidden shape) "selected")
|
(dw/select-shape id))
|
||||||
;; :on-click toggle-visibility}
|
:else
|
||||||
;; i/eye]
|
(st/emit! (dw/deselect-all)
|
||||||
;; [:div.block-element {:class (when (:blocked shape) "selected")
|
(dw/select-shape id)))))
|
||||||
;; :on-click toggle-blocking}
|
|
||||||
;; i/lock]]
|
(on-drop [item monitor]
|
||||||
;; [:div.element-icon (element-icon shape)]
|
(st/emit! (udp/persist-page (:page canvas))))
|
||||||
;; [:& layer-name {:shape shape}]]])))
|
|
||||||
|
(on-hover [item monitor]
|
||||||
|
(prn "canvas-item$hover" (:id canvas))
|
||||||
|
(st/emit! (dw/change-canvas-order {:id (:canvas-id item)
|
||||||
|
:index index})))]
|
||||||
|
(let [selected? (contains? selected (:id canvas))
|
||||||
|
collapsed? (:collapsed canvas false)
|
||||||
|
|
||||||
|
shapes (filter #(= (:canvas (second %)) (:id canvas)) shapes)
|
||||||
|
[dprops dnd-ref] (use-sortable
|
||||||
|
{:type "canvas-item"
|
||||||
|
:data {:canvas-id (:id canvas)
|
||||||
|
:page-id (:page canvas)
|
||||||
|
:index index}
|
||||||
|
:on-hover on-hover
|
||||||
|
:on-drop on-drop})]
|
||||||
|
[:li.group {:ref dnd-ref
|
||||||
|
:class (classnames
|
||||||
|
:selected selected?
|
||||||
|
:dragging-TODO (:dragging? dprops))}
|
||||||
|
[:div.element-list-body {:class (classnames :selected selected?)
|
||||||
|
:on-click select-shape
|
||||||
|
:on-double-click #(dom/stop-propagation %)}
|
||||||
|
[:div.element-actions
|
||||||
|
[:div.toggle-element {:class (when-not (:hidden canvas) "selected")
|
||||||
|
:on-click toggle-visibility}
|
||||||
|
i/eye]
|
||||||
|
[:div.block-element {:class (when (:blocked canvas) "selected")
|
||||||
|
:on-click toggle-blocking}
|
||||||
|
i/lock]]
|
||||||
|
[:div.element-icon i/folder]
|
||||||
|
[:& layer-name {:shape canvas}]
|
||||||
|
[:span.toggle-content
|
||||||
|
{ ;; :on-click toggle-collapse
|
||||||
|
:class (when-not collapsed? "inverse")}
|
||||||
|
i/arrow-slide]]
|
||||||
|
[:ul
|
||||||
|
(for [[index shape] shapes]
|
||||||
|
[:& layer-item {:shape shape
|
||||||
|
:selected selected
|
||||||
|
:index index
|
||||||
|
:key (:id shape)}])]])))
|
||||||
|
|
||||||
;; --- Layers List
|
;; --- Layers List
|
||||||
|
|
||||||
(def ^:private shapes-iref
|
|
||||||
(-> (l/key :shapes)
|
|
||||||
(l/derive st/state)))
|
|
||||||
|
|
||||||
(def ^:private canvas-iref
|
|
||||||
(-> (l/key :canvas)
|
|
||||||
(l/derive st/state)))
|
|
||||||
|
|
||||||
(mf/defc layers-list
|
(mf/defc layers-list
|
||||||
[{:keys [shapes selected] :as props}]
|
[{:keys [shapes selected] :as props}]
|
||||||
(let [shapes-map (mf/deref shapes-iref)
|
[:ul.element-list
|
||||||
canvas-map (mf/deref canvas-iref)
|
(for [[index shape] shapes]
|
||||||
selected-shapes (mf/deref refs/selected-shapes)
|
[:& layer-item {:shape shape
|
||||||
selected-canvas (mf/deref refs/selected-canvas)]
|
:selected selected
|
||||||
[:div.tool-window-content
|
:index index
|
||||||
[:ul.element-list
|
:key (:id shape)}])])
|
||||||
(for [[index id] (map-indexed vector shapes)]
|
|
||||||
[:& layer-item {:shape (get shapes-map id)
|
(mf/defc canvas-list
|
||||||
:selected selected-shapes
|
[{:keys [shapes canvas selected] :as props}]
|
||||||
:index index
|
[:ul.element-list
|
||||||
:key id}])]]))
|
(for [[index item] canvas]
|
||||||
|
[:& canvas-item {:canvas item
|
||||||
|
:shapes shapes
|
||||||
|
:selected selected
|
||||||
|
:index index
|
||||||
|
:key (:id item)}])])
|
||||||
|
|
||||||
;; --- Layers Toolbox
|
;; --- Layers Toolbox
|
||||||
|
|
||||||
(mf/defc layers-toolbox
|
(mf/defc layers-toolbox
|
||||||
[{:keys [page selected] :as props}]
|
[{:keys [page selected] :as props}]
|
||||||
(let [on-click #(st/emit! (dw/toggle-flag :layers))
|
(let [on-click #(st/emit! (dw/toggle-flag :layers))
|
||||||
selected (mf/deref refs/selected-shapes)]
|
selected (mf/deref refs/selected-shapes)
|
||||||
|
shapes-by-id (mf/deref shapes-iref)
|
||||||
|
canvas (->> (:canvas page)
|
||||||
|
(map #(get shapes-by-id %))
|
||||||
|
(enumerate))
|
||||||
|
all-shapes (->> (:shapes page)
|
||||||
|
(map #(get shapes-by-id %)))
|
||||||
|
|
||||||
|
shapes (->> all-shapes
|
||||||
|
(filter #(not (:canvas %)))
|
||||||
|
(enumerate))
|
||||||
|
|
||||||
|
all-shapes (enumerate all-shapes)]
|
||||||
|
|
||||||
[:div#layers.tool-window
|
[:div#layers.tool-window
|
||||||
[:div.tool-window-bar
|
[:div.tool-window-bar
|
||||||
[:div.tool-window-icon i/layers]
|
[:div.tool-window-icon i/layers]
|
||||||
[:span (tr "ds.settings.layers")]
|
[:span (tr "ds.settings.layers")]
|
||||||
[:div.tool-window-close {:on-click on-click} i/close]]
|
[:div.tool-window-close {:on-click on-click} i/close]]
|
||||||
[:& layers-list {:shapes (:shapes page)
|
[:div.tool-window-content
|
||||||
:selected selected}]]))
|
[:& canvas-list {:canvas canvas
|
||||||
|
:shapes all-shapes
|
||||||
|
:selected selected}]
|
||||||
|
[:& layers-list {:shapes shapes
|
||||||
|
:selected selected}]]]))
|
||||||
|
|
|
@ -246,6 +246,9 @@
|
||||||
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
[:g.zoom {:transform (str "scale(" zoom ", " zoom ")")}
|
||||||
(when page
|
(when page
|
||||||
[:*
|
[:*
|
||||||
|
(for [id (reverse (:canvas page))]
|
||||||
|
[:& uus/shape-component {:id id :key id}])
|
||||||
|
|
||||||
(for [id (reverse (:shapes page))]
|
(for [id (reverse (:shapes page))]
|
||||||
[:& uus/shape-component {:id id :key id}])
|
[:& uus/shape-component {:id id :key id}])
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,26 @@
|
||||||
(disj s v)
|
(disj s v)
|
||||||
(conj s v)))
|
(conj s v)))
|
||||||
|
|
||||||
|
(defn enumerate
|
||||||
|
([items] (enumerate items 0))
|
||||||
|
([items start]
|
||||||
|
(loop [idx start
|
||||||
|
items items
|
||||||
|
res []]
|
||||||
|
(if (empty? items)
|
||||||
|
res
|
||||||
|
(recur (inc idx)
|
||||||
|
(rest items)
|
||||||
|
(conj res [idx (first items)]))))))
|
||||||
|
|
||||||
|
(defn concatv
|
||||||
|
[& colls]
|
||||||
|
(loop [colls colls
|
||||||
|
result []]
|
||||||
|
(if (seq colls)
|
||||||
|
(recur (rest colls) (reduce conj result (first colls)))
|
||||||
|
result)))
|
||||||
|
|
||||||
(defn seek
|
(defn seek
|
||||||
([pred coll]
|
([pred coll]
|
||||||
(seek pred coll nil))
|
(seek pred coll nil))
|
||||||
|
|
Loading…
Add table
Reference in a new issue