mirror of
https://github.com/penpot/penpot.git
synced 2025-05-16 22:46:11 +02:00
Move shape related events from data.workspace to data.shapes.
This commit is contained in:
parent
551c95b8fe
commit
bcc82bc5cf
2 changed files with 144 additions and 147 deletions
|
@ -345,3 +345,144 @@
|
||||||
(-apply-update [_ state]
|
(-apply-update [_ state]
|
||||||
(stsh/drop-shape state sid tid loc))))
|
(stsh/drop-shape state sid tid loc))))
|
||||||
|
|
||||||
|
(defn select-shape
|
||||||
|
"Mark a shape selected for drawing in the canvas."
|
||||||
|
[id]
|
||||||
|
(reify
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(let [selected (get-in state [:workspace :selected])]
|
||||||
|
(if (contains? selected id)
|
||||||
|
(update-in state [:workspace :selected] disj id)
|
||||||
|
(update-in state [:workspace :selected] conj id))))))
|
||||||
|
|
||||||
|
(defn select-shapes
|
||||||
|
"Select shapes that matches the select rect."
|
||||||
|
[selrect]
|
||||||
|
(reify
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(let [pageid (get-in state [:workspace :page])
|
||||||
|
xf (comp
|
||||||
|
(filter #(= (:page %) pageid))
|
||||||
|
(remove :hidden)
|
||||||
|
(remove :blocked)
|
||||||
|
(map sh/outer-rect')
|
||||||
|
(filter #(sh/contained-in? % selrect))
|
||||||
|
(map :id))]
|
||||||
|
(->> (into #{} xf (vals (:shapes-by-id state)))
|
||||||
|
(assoc-in state [:workspace :selected]))))))
|
||||||
|
|
||||||
|
;; --- Events (implicit) (for selected)
|
||||||
|
|
||||||
|
(defn deselect-all
|
||||||
|
"Mark a shape selected for drawing in the canvas."
|
||||||
|
[]
|
||||||
|
(reify
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(assoc-in state [:workspace :selected] #{}))))
|
||||||
|
|
||||||
|
(defn group-selected
|
||||||
|
[]
|
||||||
|
(letfn [(update-shapes-on-page [state pid selected group]
|
||||||
|
(as-> (get-in state [:pages-by-id pid :shapes]) $
|
||||||
|
(remove selected $)
|
||||||
|
(into [group] $)
|
||||||
|
(assoc-in state [:pages-by-id pid :shapes] $)))
|
||||||
|
|
||||||
|
(update-shapes-on-index [state shapes group]
|
||||||
|
(reduce (fn [state {:keys [id] :as shape}]
|
||||||
|
(as-> shape $
|
||||||
|
(assoc $ :group group)
|
||||||
|
(assoc-in state [:shapes-by-id id] $)))
|
||||||
|
state
|
||||||
|
shapes))
|
||||||
|
(valid-selection? [shapes]
|
||||||
|
(let [groups (into #{} (map :group shapes))]
|
||||||
|
(= 1 (count groups))))]
|
||||||
|
(reify
|
||||||
|
udp/IPageUpdate
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(let [shapes-by-id (get state :shapes-by-id)
|
||||||
|
sid (random-uuid)
|
||||||
|
pid (get-in state [:workspace :page])
|
||||||
|
selected (get-in state [:workspace :selected])
|
||||||
|
selected' (map #(get shapes-by-id %) selected)
|
||||||
|
group {:type :builtin/group
|
||||||
|
:name (str "Group " (rand-int 1000))
|
||||||
|
:items (into [] selected)
|
||||||
|
:id sid
|
||||||
|
:page pid}]
|
||||||
|
(if (valid-selection? selected')
|
||||||
|
(as-> state $
|
||||||
|
(update-shapes-on-index $ selected' sid)
|
||||||
|
(update-shapes-on-page $ pid selected sid)
|
||||||
|
(update $ :shapes-by-id assoc sid group)
|
||||||
|
(update $ :workspace assoc :selected #{}))
|
||||||
|
state))))))
|
||||||
|
|
||||||
|
;; TODO: maybe split in two separate events
|
||||||
|
(defn duplicate-selected
|
||||||
|
[]
|
||||||
|
(reify
|
||||||
|
udp/IPageUpdate
|
||||||
|
rs/UpdateEvent
|
||||||
|
(-apply-update [_ state]
|
||||||
|
(let [selected (get-in state [:workspace :selected])]
|
||||||
|
(stsh/duplicate-shapes state selected)))))
|
||||||
|
|
||||||
|
(defn delete-selected
|
||||||
|
"Deselect all and remove all selected shapes."
|
||||||
|
[]
|
||||||
|
(reify
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(let [selected (get-in state [:workspace :selected])]
|
||||||
|
(rx/from-coll
|
||||||
|
(into [(deselect-all)] (map #(delete-shape %) selected)))))))
|
||||||
|
|
||||||
|
(defn move-selected
|
||||||
|
"Move a minimal position unit the selected shapes."
|
||||||
|
([dir] (move-selected dir 1))
|
||||||
|
([dir n]
|
||||||
|
{:pre [(contains? #{:up :down :right :left} dir)]}
|
||||||
|
(reify
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(let [selected (get-in state [:workspace :selected])
|
||||||
|
delta (case dir
|
||||||
|
:up (gpt/point 0 (- n))
|
||||||
|
:down (gpt/point 0 n)
|
||||||
|
:right (gpt/point n 0)
|
||||||
|
:left (gpt/point (- n) 0))]
|
||||||
|
(rx/from-coll
|
||||||
|
(map #(move-shape % delta) selected)))))))
|
||||||
|
|
||||||
|
(defn update-selected-shapes-fill
|
||||||
|
"Update the fill related attributed on
|
||||||
|
selected shapes."
|
||||||
|
[opts]
|
||||||
|
(sc/validate! +shape-fill-attrs-schema+ opts)
|
||||||
|
(reify
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(rx/from-coll
|
||||||
|
(->> (get-in state [:workspace :selected])
|
||||||
|
(map #(update-fill-attrs % opts)))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn update-selected-shapes-stroke
|
||||||
|
"Update the fill related attributed on
|
||||||
|
selected shapes."
|
||||||
|
[opts]
|
||||||
|
(sc/validate! +shape-stroke-attrs-schema+ opts)
|
||||||
|
(reify
|
||||||
|
rs/WatchEvent
|
||||||
|
(-apply-watch [_ state s]
|
||||||
|
(rx/from-coll
|
||||||
|
(->> (get-in state [:workspace :selected])
|
||||||
|
(map #(update-stroke-attrs % opts)))))))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,19 +10,15 @@
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[uxbox.shapes :as sh]
|
[uxbox.shapes :as sh]
|
||||||
[uxbox.rstore :as rs]
|
[uxbox.rstore :as rs]
|
||||||
[uxbox.router :as r]
|
|
||||||
[uxbox.state :as st]
|
|
||||||
[uxbox.state.shapes :as stsh]
|
[uxbox.state.shapes :as stsh]
|
||||||
[uxbox.schema :as sc]
|
[uxbox.schema :as sc]
|
||||||
[uxbox.xforms :as xf]
|
|
||||||
[uxbox.shapes :as sh]
|
|
||||||
[uxbox.data.pages :as udp]
|
[uxbox.data.pages :as udp]
|
||||||
[uxbox.data.shapes :as uds]
|
[uxbox.data.shapes :as uds]
|
||||||
|
;; [uxbox.data.worker :as wrk]
|
||||||
[uxbox.util.datetime :as dt]
|
[uxbox.util.datetime :as dt]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]))
|
||||||
[uxbox.util.data :refer (index-of)]))
|
|
||||||
|
|
||||||
;; --- Events (concrete)
|
;; --- Workspace Initialization
|
||||||
|
|
||||||
(defn initialize
|
(defn initialize
|
||||||
"Initialize the workspace state."
|
"Initialize the workspace state."
|
||||||
|
@ -65,146 +61,6 @@
|
||||||
(assoc-in state [:workspace :drawing] shape)
|
(assoc-in state [:workspace :drawing] shape)
|
||||||
(update-in state [:workspace] dissoc :drawing)))))
|
(update-in state [:workspace] dissoc :drawing)))))
|
||||||
|
|
||||||
(defn select-shape
|
|
||||||
"Mark a shape selected for drawing in the canvas."
|
|
||||||
[id]
|
|
||||||
(reify
|
|
||||||
rs/UpdateEvent
|
|
||||||
(-apply-update [_ state]
|
|
||||||
(let [selected (get-in state [:workspace :selected])]
|
|
||||||
(if (contains? selected id)
|
|
||||||
(update-in state [:workspace :selected] disj id)
|
|
||||||
(update-in state [:workspace :selected] conj id))))))
|
|
||||||
|
|
||||||
(defn select-shapes
|
|
||||||
"Select shapes that matches the select rect."
|
|
||||||
[selrect]
|
|
||||||
(reify
|
|
||||||
rs/UpdateEvent
|
|
||||||
(-apply-update [_ state]
|
|
||||||
(let [pageid (get-in state [:workspace :page])
|
|
||||||
xf (comp
|
|
||||||
(filter #(= (:page %) pageid))
|
|
||||||
(remove :hidden)
|
|
||||||
(remove :blocked)
|
|
||||||
(map sh/outer-rect')
|
|
||||||
(filter #(sh/contained-in? % selrect))
|
|
||||||
(map :id))]
|
|
||||||
(->> (into #{} xf (vals (:shapes-by-id state)))
|
|
||||||
(assoc-in state [:workspace :selected]))))))
|
|
||||||
|
|
||||||
;; --- Events (implicit) (for selected)
|
|
||||||
|
|
||||||
(defn deselect-all
|
|
||||||
"Mark a shape selected for drawing in the canvas."
|
|
||||||
[]
|
|
||||||
(reify
|
|
||||||
rs/UpdateEvent
|
|
||||||
(-apply-update [_ state]
|
|
||||||
(assoc-in state [:workspace :selected] #{}))))
|
|
||||||
|
|
||||||
(defn group-selected
|
|
||||||
[]
|
|
||||||
(letfn [(update-shapes-on-page [state pid selected group]
|
|
||||||
(as-> (get-in state [:pages-by-id pid :shapes]) $
|
|
||||||
(remove selected $)
|
|
||||||
(into [group] $)
|
|
||||||
(assoc-in state [:pages-by-id pid :shapes] $)))
|
|
||||||
|
|
||||||
(update-shapes-on-index [state shapes group]
|
|
||||||
(reduce (fn [state {:keys [id] :as shape}]
|
|
||||||
(as-> shape $
|
|
||||||
(assoc $ :group group)
|
|
||||||
(assoc-in state [:shapes-by-id id] $)))
|
|
||||||
state
|
|
||||||
shapes))
|
|
||||||
(valid-selection? [shapes]
|
|
||||||
(let [groups (into #{} (map :group shapes))]
|
|
||||||
(= 1 (count groups))))]
|
|
||||||
(reify
|
|
||||||
udp/IPageUpdate
|
|
||||||
rs/UpdateEvent
|
|
||||||
(-apply-update [_ state]
|
|
||||||
(let [shapes-by-id (get state :shapes-by-id)
|
|
||||||
sid (random-uuid)
|
|
||||||
pid (get-in state [:workspace :page])
|
|
||||||
selected (get-in state [:workspace :selected])
|
|
||||||
selected' (map #(get shapes-by-id %) selected)
|
|
||||||
group {:type :builtin/group
|
|
||||||
:name (str "Group " (rand-int 1000))
|
|
||||||
:items (into [] selected)
|
|
||||||
:id sid
|
|
||||||
:page pid}]
|
|
||||||
(if (valid-selection? selected')
|
|
||||||
(as-> state $
|
|
||||||
(update-shapes-on-index $ selected' sid)
|
|
||||||
(update-shapes-on-page $ pid selected sid)
|
|
||||||
(update $ :shapes-by-id assoc sid group)
|
|
||||||
(update $ :workspace assoc :selected #{}))
|
|
||||||
state))))))
|
|
||||||
|
|
||||||
;; TODO: maybe split in two separate events
|
|
||||||
(defn duplicate-selected
|
|
||||||
[]
|
|
||||||
(reify
|
|
||||||
udp/IPageUpdate
|
|
||||||
rs/UpdateEvent
|
|
||||||
(-apply-update [_ state]
|
|
||||||
(let [selected (get-in state [:workspace :selected])]
|
|
||||||
(stsh/duplicate-shapes state selected)))))
|
|
||||||
|
|
||||||
(defn delete-selected
|
|
||||||
"Deselect all and remove all selected shapes."
|
|
||||||
[]
|
|
||||||
(reify
|
|
||||||
rs/WatchEvent
|
|
||||||
(-apply-watch [_ state s]
|
|
||||||
(let [selected (get-in state [:workspace :selected])]
|
|
||||||
(rx/from-coll
|
|
||||||
(into [(deselect-all)] (map #(uds/delete-shape %) selected)))))))
|
|
||||||
|
|
||||||
(defn move-selected
|
|
||||||
"Move a minimal position unit the selected shapes."
|
|
||||||
([dir] (move-selected dir 1))
|
|
||||||
([dir n]
|
|
||||||
{:pre [(contains? #{:up :down :right :left} dir)]}
|
|
||||||
(reify
|
|
||||||
rs/WatchEvent
|
|
||||||
(-apply-watch [_ state s]
|
|
||||||
(let [selected (get-in state [:workspace :selected])
|
|
||||||
delta (case dir
|
|
||||||
:up (gpt/point 0 (- n))
|
|
||||||
:down (gpt/point 0 n)
|
|
||||||
:right (gpt/point n 0)
|
|
||||||
:left (gpt/point (- n) 0))]
|
|
||||||
(rx/from-coll
|
|
||||||
(map #(uds/move-shape % delta) selected)))))))
|
|
||||||
|
|
||||||
(defn update-selected-shapes-fill
|
|
||||||
"Update the fill related attributed on
|
|
||||||
selected shapes."
|
|
||||||
[opts]
|
|
||||||
(sc/validate! uds/+shape-fill-attrs-schema+ opts)
|
|
||||||
(reify
|
|
||||||
rs/WatchEvent
|
|
||||||
(-apply-watch [_ state s]
|
|
||||||
(rx/from-coll
|
|
||||||
(->> (get-in state [:workspace :selected])
|
|
||||||
(map #(uds/update-fill-attrs % opts)))))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn update-selected-shapes-stroke
|
|
||||||
"Update the fill related attributed on
|
|
||||||
selected shapes."
|
|
||||||
[opts]
|
|
||||||
(sc/validate! uds/+shape-stroke-attrs-schema+ opts)
|
|
||||||
(reify
|
|
||||||
rs/WatchEvent
|
|
||||||
(-apply-watch [_ state s]
|
|
||||||
(rx/from-coll
|
|
||||||
(->> (get-in state [:workspace :selected])
|
|
||||||
(map #(uds/update-stroke-attrs % opts)))))))
|
|
||||||
|
|
||||||
;; --- Copy to Clipboard
|
;; --- Copy to Clipboard
|
||||||
|
|
||||||
(defrecord CopyToClipboard []
|
(defrecord CopyToClipboard []
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue