mirror of
https://github.com/penpot/penpot.git
synced 2025-06-01 20:21:39 +02:00
Minor refactor on shapes data events.
Adding more asserts and more specs.
This commit is contained in:
parent
fdf3f1b6f0
commit
b3a2ae3eb2
8 changed files with 281 additions and 205 deletions
|
@ -49,6 +49,8 @@
|
||||||
(s/def ::hidden boolean?)
|
(s/def ::hidden boolean?)
|
||||||
(s/def ::blocked boolean?)
|
(s/def ::blocked boolean?)
|
||||||
(s/def ::locked boolean?)
|
(s/def ::locked boolean?)
|
||||||
|
(s/def ::width number?)
|
||||||
|
(s/def ::height number?)
|
||||||
(s/def ::x1 number?)
|
(s/def ::x1 number?)
|
||||||
(s/def ::y1 number?)
|
(s/def ::y1 number?)
|
||||||
(s/def ::x2 number?)
|
(s/def ::x2 number?)
|
||||||
|
@ -103,11 +105,12 @@
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [shape (geom/setup-proportions data)
|
(let [shape (geom/setup-proportions data)
|
||||||
page (l/focus ul/selected-page state)]
|
page (get-in state [:workspace :page])]
|
||||||
(impl/assoc-shape-to-page state shape page))))
|
(impl/assoc-shape-to-page state shape page))))
|
||||||
|
|
||||||
(defn add-shape
|
(defn add-shape
|
||||||
[data]
|
[data]
|
||||||
|
{:pre [(us/valid? ::shape data)]}
|
||||||
(AddShape. data))
|
(AddShape. data))
|
||||||
|
|
||||||
;; --- Delete Shape
|
;; --- Delete Shape
|
||||||
|
@ -125,14 +128,18 @@
|
||||||
{:pre [(uuid? id)]}
|
{:pre [(uuid? id)]}
|
||||||
(DeleteShape. id))
|
(DeleteShape. id))
|
||||||
|
|
||||||
(defn update-shape
|
;; --- Rename Shape
|
||||||
"Just updates in place the shape."
|
|
||||||
[{:keys [id] :as shape}]
|
(deftype RenameShape [id name]
|
||||||
(reify
|
udp/IPageUpdate
|
||||||
udp/IPageUpdate
|
ptk/UpdateEvent
|
||||||
ptk/UpdateEvent
|
(update [_ state]
|
||||||
(update [_ state]
|
(assoc-in state [:shapes id :name] name)))
|
||||||
(update-in state [:shapes id] merge shape))))
|
|
||||||
|
(defn rename-shape
|
||||||
|
[id name]
|
||||||
|
{:pre [(uuid? id) (string? name)]}
|
||||||
|
(RenameShape. id name))
|
||||||
|
|
||||||
;; --- Shape Transformations
|
;; --- Shape Transformations
|
||||||
|
|
||||||
|
@ -142,7 +149,6 @@
|
||||||
|
|
||||||
(declare apply-temporal-displacement)
|
(declare apply-temporal-displacement)
|
||||||
|
|
||||||
|
|
||||||
(deftype InitialShapeAlign [id]
|
(deftype InitialShapeAlign [id]
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state s]
|
(watch [_ state s]
|
||||||
|
@ -160,29 +166,40 @@
|
||||||
{:pre [(uuid? id)]}
|
{:pre [(uuid? id)]}
|
||||||
(InitialShapeAlign. id))
|
(InitialShapeAlign. id))
|
||||||
|
|
||||||
|
;; --- Update Rotation
|
||||||
|
|
||||||
|
(deftype UpdateShapeRotation [id rotation]
|
||||||
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:shapes id :rotation] rotation)))
|
||||||
|
|
||||||
(defn update-rotation
|
(defn update-rotation
|
||||||
[sid rotation]
|
[id rotation]
|
||||||
{:pre [(number? rotation)
|
{:pre [(uuid? id)
|
||||||
|
(number? rotation)
|
||||||
(>= rotation 0)
|
(>= rotation 0)
|
||||||
(>= 360 rotation)]}
|
(>= 360 rotation)]}
|
||||||
(reify
|
(UpdateShapeRotation. id rotation))
|
||||||
udp/IPageUpdate
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(update-in state [:shapes sid]
|
|
||||||
geom/rotate rotation))))
|
|
||||||
|
|
||||||
(defn update-size
|
;; --- Update Dimensions
|
||||||
|
|
||||||
|
(deftype UpdateDimensions [id dimensions]
|
||||||
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update-in state [:shapes id] geom/resize-dim dimensions)))
|
||||||
|
|
||||||
|
(s/def ::update-dimensions-opts
|
||||||
|
(s/keys :opt-un [::width ::height]))
|
||||||
|
|
||||||
|
(defn update-dimensions
|
||||||
"A helper event just for update the position
|
"A helper event just for update the position
|
||||||
of the shape using the width and height attrs
|
of the shape using the width and height attrs
|
||||||
instread final point of coordinates."
|
instread final point of coordinates."
|
||||||
[sid opts]
|
[id opts]
|
||||||
{:pre [(uuid? sid)]}
|
{:pre [(uuid? id) (us/valid? ::update-dimensions-opts opts)]}
|
||||||
(reify
|
(UpdateDimensions. id opts))
|
||||||
udp/IPageUpdate
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(update-in state [:shapes sid] geom/resize-dim opts))))
|
|
||||||
|
|
||||||
;; --- Apply Temporal Displacement
|
;; --- Apply Temporal Displacement
|
||||||
|
|
||||||
|
@ -246,22 +263,32 @@
|
||||||
{:pre [(uuid? id)]}
|
{:pre [(uuid? id)]}
|
||||||
(ApplyResize. id))
|
(ApplyResize. id))
|
||||||
|
|
||||||
|
;; --- Update Shape Position
|
||||||
|
|
||||||
|
(deftype UpdateShapePosition [id point]
|
||||||
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update-in state [:shapes id] geom/absolute-move point)))
|
||||||
|
|
||||||
(defn update-position
|
(defn update-position
|
||||||
"Update the start position coordenate of the shape."
|
"Update the start position coordenate of the shape."
|
||||||
[sid {:keys [x y] :as opts}]
|
[id point]
|
||||||
(reify
|
{:pre [(uuid? id) (gpt/point? point)]}
|
||||||
ptk/UpdateEvent
|
(UpdateShapePosition. id point))
|
||||||
(update [_ state]
|
|
||||||
(update-in state [:shapes sid] geom/absolute-move opts))))
|
;; --- Update Shape Text
|
||||||
|
|
||||||
|
(deftype UpdateShapeTextContent [id text]
|
||||||
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:shapes id :content] text)))
|
||||||
|
|
||||||
(defn update-text
|
(defn update-text
|
||||||
[sid {:keys [content]}]
|
[id text]
|
||||||
{:pre [(string? content)]}
|
{:pre [(uuid? id) (string? text)]}
|
||||||
(reify
|
(UpdateShapeTextContent. id text))
|
||||||
udp/IPageUpdate
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:shapes sid :content] content))))
|
|
||||||
|
|
||||||
;; --- Update Shape Attrs
|
;; --- Update Shape Attrs
|
||||||
|
|
||||||
|
@ -283,173 +310,206 @@
|
||||||
|
|
||||||
;; --- Shape Proportions
|
;; --- Shape Proportions
|
||||||
|
|
||||||
|
(deftype LockShapeProportions [id]
|
||||||
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [[width height] (-> (get-in state [:shapes id])
|
||||||
|
(geom/size)
|
||||||
|
(keep [:width :height]))
|
||||||
|
proportion (/ width height)]
|
||||||
|
(update-in state [:shapes id] assoc
|
||||||
|
:proportion proportion
|
||||||
|
:proportion-lock true))))
|
||||||
|
|
||||||
(defn lock-proportions
|
(defn lock-proportions
|
||||||
"Mark proportions of the shape locked and save the current
|
"Mark proportions of the shape locked and save the current
|
||||||
proportion as additional precalculated property."
|
proportion as additional precalculated property."
|
||||||
[sid]
|
[id]
|
||||||
{:pre [(uuid? sid)]}
|
{:pre [(uuid? id)]}
|
||||||
(reify
|
(LockShapeProportions. id))
|
||||||
udp/IPageUpdate
|
|
||||||
ptk/UpdateEvent
|
(deftype UnlockShapeProportions [id]
|
||||||
(update [_ state]
|
udp/IPageUpdate
|
||||||
(let [[width height] (-> (get-in state [:shapes sid])
|
ptk/UpdateEvent
|
||||||
(geom/size)
|
(update [_ state]
|
||||||
(keep [:width :height]))
|
(assoc-in state [:shapes id :proportion-lock] true)))
|
||||||
proportion (/ width height)]
|
|
||||||
(update-in state [:shapes sid] assoc
|
|
||||||
:proportion proportion
|
|
||||||
:proportion-lock true)))))
|
|
||||||
|
|
||||||
(defn unlock-proportions
|
(defn unlock-proportions
|
||||||
[sid]
|
[id]
|
||||||
{:pre [(uuid? sid)]}
|
{:pre [(uuid? id)]}
|
||||||
(reify
|
(UnlockShapeProportions. id))
|
||||||
udp/IPageUpdate
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(update-in state [:shapes sid] assoc
|
|
||||||
:proportion-lock false))))
|
|
||||||
|
|
||||||
;; --- Group Collapsing
|
;; --- Group Collapsing
|
||||||
|
|
||||||
|
(deftype CollapseGroupShape [id]
|
||||||
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update-in state [:shapes id] assoc :collapsed true)))
|
||||||
|
|
||||||
(defn collapse-shape
|
(defn collapse-shape
|
||||||
[id]
|
[id]
|
||||||
{:pre [(uuid? id)]}
|
{:pre [(uuid? id)]}
|
||||||
(reify
|
(CollapseGroupShape. id))
|
||||||
udp/IPageUpdate
|
|
||||||
ptk/UpdateEvent
|
(deftype UncollapseGroupShape [id]
|
||||||
(update [_ state]
|
udp/IPageUpdate
|
||||||
(update-in state [:shapes id] assoc :collapsed true))))
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update-in state [:shapes id] assoc :collapsed false)))
|
||||||
|
|
||||||
(defn uncollapse-shape
|
(defn uncollapse-shape
|
||||||
[id]
|
[id]
|
||||||
{:pre [(uuid? id)]}
|
{:pre [(uuid? id)]}
|
||||||
(reify
|
(UncollapseGroupShape. id))
|
||||||
udp/IPageUpdate
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(update-in state [:shapes id] assoc :collapsed false))))
|
|
||||||
|
|
||||||
;; --- Shape Visibility
|
;; --- Shape Visibility
|
||||||
|
|
||||||
(defn hide-shape
|
(deftype HideShape [id]
|
||||||
[sid]
|
udp/IPageUpdate
|
||||||
(reify
|
ptk/UpdateEvent
|
||||||
udp/IPageUpdate
|
(update [_ state]
|
||||||
ptk/UpdateEvent
|
(letfn [(mark-hidden [state id]
|
||||||
(update [_ state]
|
(let [shape (get-in state [:shapes id])]
|
||||||
(assoc-in state [:shapes sid :hidden] true))
|
(if (= :group (:type shape))
|
||||||
|
(as-> state $
|
||||||
|
(assoc-in $ [:shapes id :hidden] true)
|
||||||
|
(reduce mark-hidden $ (:items shape)))
|
||||||
|
(assoc-in state [:shapes id :hidden] true))))]
|
||||||
|
(mark-hidden state id))))
|
||||||
|
|
||||||
ptk/WatchEvent
|
(defn hide-shape
|
||||||
(watch [_ state s]
|
[id]
|
||||||
(let [shape (get-in state [:shapes sid])]
|
{:pre [(uuid? id)]}
|
||||||
(if-not (= (:type shape) :group)
|
(HideShape. id))
|
||||||
(rx/empty)
|
|
||||||
(rx/from-coll
|
(deftype ShowShape [id]
|
||||||
(map hide-shape (:items shape))))))))
|
udp/IPageUpdate
|
||||||
|
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
|
(defn show-shape
|
||||||
[sid]
|
[id]
|
||||||
(reify
|
{:pre [(uuid? id)]}
|
||||||
udp/IPageUpdate
|
(ShowShape. id))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:shapes sid :hidden] false))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
;; --- Shape Blocking
|
||||||
(watch [_ state s]
|
|
||||||
(let [shape (get-in state [:shapes sid])]
|
(deftype BlockShape [id]
|
||||||
(if-not (= (:type shape) :group)
|
udp/IPageUpdate
|
||||||
(rx/empty)
|
ptk/UpdateEvent
|
||||||
(rx/from-coll
|
(update [_ state]
|
||||||
(map show-shape (:items shape))))))))
|
(letfn [(mark-blocked [state id]
|
||||||
|
(let [shape (get-in state [:shapes id])]
|
||||||
|
(if (= :group (:type shape))
|
||||||
|
(as-> state $
|
||||||
|
(assoc-in $ [:shapes id :blocked] true)
|
||||||
|
(reduce mark-blocked $ (:items shape)))
|
||||||
|
(assoc-in state [:shapes id :blocked] true))))]
|
||||||
|
(mark-blocked state id))))
|
||||||
|
|
||||||
(defn block-shape
|
(defn block-shape
|
||||||
[sid]
|
[id]
|
||||||
(reify
|
{:pre [(uuid? id)]}
|
||||||
udp/IPageUpdate
|
(BlockShape. id))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:shapes sid :blocked] true))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
(deftype UnblockShape [id]
|
||||||
(watch [_ state s]
|
udp/IPageUpdate
|
||||||
(let [shape (get-in state [:shapes sid])]
|
ptk/UpdateEvent
|
||||||
(if-not (= (:type shape) :group)
|
(update [_ state]
|
||||||
(rx/empty)
|
(letfn [(mark-unblocked [state id]
|
||||||
(rx/from-coll
|
(let [shape (get-in state [:shapes id])]
|
||||||
(map block-shape (:items shape))))))))
|
(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
|
(defn unblock-shape
|
||||||
[sid]
|
[id]
|
||||||
(reify
|
{:pre [(uuid? id)]}
|
||||||
udp/IPageUpdate
|
(UnblockShape. id))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:shapes sid :blocked] false))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
;; --- Shape Locking
|
||||||
(watch [_ state s]
|
|
||||||
(let [shape (get-in state [:shapes sid])]
|
(deftype LockShape [id]
|
||||||
(if-not (= (:type shape) :group)
|
udp/IPageUpdate
|
||||||
(rx/empty)
|
ptk/UpdateEvent
|
||||||
(rx/from-coll
|
(update [_ state]
|
||||||
(map unblock-shape (:items shape))))))))
|
(letfn [(mark-locked [state id]
|
||||||
|
(let [shape (get-in state [:shapes id])]
|
||||||
|
(if (= :group (:type shape))
|
||||||
|
(as-> state $
|
||||||
|
(assoc-in $ [:shapes id :locked] true)
|
||||||
|
(reduce mark-locked $ (:items shape)))
|
||||||
|
(assoc-in state [:shapes id :locked] true))))]
|
||||||
|
(mark-locked state id))))
|
||||||
|
|
||||||
(defn lock-shape
|
(defn lock-shape
|
||||||
[sid]
|
[id]
|
||||||
(reify
|
{:pre [(uuid? id)]}
|
||||||
udp/IPageUpdate
|
(LockShape. id))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:shapes sid :locked] true))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
(deftype UnlockShape [id]
|
||||||
(watch [_ state s]
|
udp/IPageUpdate
|
||||||
(let [shape (get-in state [:shapes sid])]
|
ptk/UpdateEvent
|
||||||
(if-not (= (:type shape) :group)
|
(update [_ state]
|
||||||
(rx/empty)
|
(letfn [(mark-unlocked [state id]
|
||||||
(rx/from-coll
|
(let [shape (get-in state [:shapes id])]
|
||||||
(map lock-shape (:items shape))))))))
|
(if (= :group (:type shape))
|
||||||
|
(as-> state $
|
||||||
|
(assoc-in $ [:shapes id :locked] false)
|
||||||
|
(reduce mark-unlocked $ (:items shape)))
|
||||||
|
(assoc-in state [:shapes id :locked] false))))]
|
||||||
|
(mark-unlocked state id))))
|
||||||
|
|
||||||
(defn unlock-shape
|
(defn unlock-shape
|
||||||
[sid]
|
[id]
|
||||||
(reify
|
{:pre [(uuid? id)]}
|
||||||
udp/IPageUpdate
|
(UnlockShape. id))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(assoc-in state [:shapes sid :locked] false))
|
|
||||||
|
|
||||||
ptk/WatchEvent
|
;; --- Drop Shape
|
||||||
(watch [_ state s]
|
|
||||||
(let [shape (get-in state [:shapes sid])]
|
(deftype DropShape [sid tid loc]
|
||||||
(if-not (= (:type shape) :group)
|
udp/IPageUpdate
|
||||||
(rx/empty)
|
ptk/UpdateEvent
|
||||||
(rx/from-coll
|
(update [_ state]
|
||||||
(map unlock-shape (:items shape))))))))
|
(impl/drop-shape state sid tid loc)))
|
||||||
|
|
||||||
(defn drop-shape
|
(defn drop-shape
|
||||||
"Event used in drag and drop for transfer shape
|
"Event used in drag and drop for transfer shape
|
||||||
from one position to an other."
|
from one position to an other."
|
||||||
[sid tid loc]
|
[sid tid loc]
|
||||||
{:pre [(not (nil? tid))
|
{:pre [(uuid? sid)
|
||||||
(not (nil? sid))]}
|
(uuid? tid)
|
||||||
(reify
|
(keyword? loc)]}
|
||||||
udp/IPageUpdate
|
(DropShape. sid tid loc))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
;; --- Select First Shape
|
||||||
(impl/drop-shape state sid tid loc))))
|
|
||||||
|
(deftype SelectFirstShape []
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [page (get-in state [:workspace :page])
|
||||||
|
id (first (get-in state [:pages page :shapes]))]
|
||||||
|
(assoc-in state [:workspace :selected] #{id}))))
|
||||||
|
|
||||||
(defn select-first-shape
|
(defn select-first-shape
|
||||||
"Mark a shape selected for drawing in the canvas."
|
"Mark a shape selected for drawing in the canvas."
|
||||||
[]
|
[]
|
||||||
(reify
|
(SelectFirstShape.))
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [page (get-in state [:workspace :page])
|
|
||||||
id (first (get-in state [:pages page :shapes]))]
|
|
||||||
(assoc-in state [:workspace :selected] #{id})))))
|
|
||||||
|
|
||||||
|
;; --- Mark Shape Selected
|
||||||
|
|
||||||
(deftype SelectShape [id]
|
(deftype SelectShape [id]
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
|
@ -466,7 +526,7 @@
|
||||||
{:pre [(uuid? id)]}
|
{:pre [(uuid? id)]}
|
||||||
(SelectShape. id))
|
(SelectShape. id))
|
||||||
|
|
||||||
;; --- Select Shapes
|
;; --- Select Shapes (By selrect)
|
||||||
|
|
||||||
(deftype SelectShapesBySelrect [selrect]
|
(deftype SelectShapesBySelrect [selrect]
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
|
@ -578,25 +638,37 @@
|
||||||
[]
|
[]
|
||||||
(DeselectAll.))
|
(DeselectAll.))
|
||||||
|
|
||||||
|
;; --- Group Selected Shapes
|
||||||
|
|
||||||
|
(deftype GroupSelectedShapes []
|
||||||
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [id (get-in state [:workspace :page])
|
||||||
|
selected (get-in state [:workspace :selected])]
|
||||||
|
(assert (not (empty? selected)) "selected set is empty")
|
||||||
|
(assert (uuid? id) "selected page is not an uuid")
|
||||||
|
(impl/group-shapes state selected id))))
|
||||||
|
|
||||||
(defn group-selected
|
(defn group-selected
|
||||||
[]
|
[]
|
||||||
(reify
|
(GroupSelectedShapes.))
|
||||||
udp/IPageUpdate
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [pid (get-in state [:workspace :page])
|
|
||||||
selected (get-in state [:workspace :selected])]
|
|
||||||
(impl/group-shapes state selected pid)))))
|
|
||||||
|
|
||||||
(defn degroup-selected
|
;; --- Ungroup Selected Shapes
|
||||||
|
|
||||||
|
(deftype UngroupSelectedShapes []
|
||||||
|
udp/IPageUpdate
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [id (get-in state [:workspace :page])
|
||||||
|
selected (get-in state [:workspace :selected])]
|
||||||
|
(assert (not (empty? selected)) "selected set is empty")
|
||||||
|
(assert (uuid? id) "selected page is not an uuid")
|
||||||
|
(impl/degroup-shapes state selected id))))
|
||||||
|
|
||||||
|
(defn ungroup-selected
|
||||||
[]
|
[]
|
||||||
(reify
|
(UngroupSelectedShapes.))
|
||||||
udp/IPageUpdate
|
|
||||||
ptk/UpdateEvent
|
|
||||||
(update [_ state]
|
|
||||||
(let [pid (get-in state [:workspace :page])
|
|
||||||
selected (get-in state [:workspace :selected])]
|
|
||||||
(impl/degroup-shapes state selected pid)))))
|
|
||||||
|
|
||||||
;; --- Duplicate Selected
|
;; --- Duplicate Selected
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,7 @@
|
||||||
|
|
||||||
;; TODO: maybe we can consider apply the rotation
|
;; TODO: maybe we can consider apply the rotation
|
||||||
;; directly to the shape coordinates?
|
;; directly to the shape coordinates?
|
||||||
|
;; FIXME: deprecated, should be removed
|
||||||
|
|
||||||
(defn rotate
|
(defn rotate
|
||||||
"Apply the rotation to the shape."
|
"Apply the rotation to the shape."
|
||||||
|
|
|
@ -121,7 +121,7 @@
|
||||||
props {:x x1 :y y1 :width width :height height}]
|
props {:x x1 :y y1 :width width :height height}]
|
||||||
(letfn [(on-input [ev]
|
(letfn [(on-input [ev]
|
||||||
(let [content (dom/event->inner-text ev)]
|
(let [content (dom/event->inner-text ev)]
|
||||||
(st/emit! (uds/update-text id {:content content}))))]
|
(st/emit! (uds/update-text id content))))]
|
||||||
[:foreignObject props
|
[:foreignObject props
|
||||||
[:div {:style style
|
[:div {:style style
|
||||||
:ref "container"
|
:ref "container"
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
(defonce +shortcuts+
|
(defonce +shortcuts+
|
||||||
{:shift+g #(st/emit! (dw/toggle-flag :grid))
|
{:shift+g #(st/emit! (dw/toggle-flag :grid))
|
||||||
:ctrl+g #(st/emit! (uds/group-selected))
|
:ctrl+g #(st/emit! (uds/group-selected))
|
||||||
:ctrl+shift+g #(st/emit! (uds/degroup-selected))
|
:ctrl+shift+g #(st/emit! (uds/ungroup-selected))
|
||||||
:ctrl+shift+m #(st/emit! (dw/toggle-flag :sitemap))
|
:ctrl+shift+m #(st/emit! (dw/toggle-flag :sitemap))
|
||||||
:ctrl+shift+f #(st/emit! (dw/toggle-flag :drawtools))
|
:ctrl+shift+f #(st/emit! (dw/toggle-flag :drawtools))
|
||||||
:ctrl+shift+i #(st/emit! (dw/toggle-flag :icons))
|
:ctrl+shift+i #(st/emit! (dw/toggle-flag :icons))
|
||||||
|
|
|
@ -92,14 +92,13 @@
|
||||||
"A generic component that displays the shape name
|
"A generic component that displays the shape name
|
||||||
if it is available and allows inline edition of it."
|
if it is available and allows inline edition of it."
|
||||||
{:mixins [mx/static (mx/local)]}
|
{:mixins [mx/static (mx/local)]}
|
||||||
[{:keys [rum/local]} shape]
|
[{:keys [rum/local]} {:keys [id] :as shape}]
|
||||||
(letfn [(on-blur [event]
|
(letfn [(on-blur [event]
|
||||||
(let [target (dom/event->target event)
|
(let [target (dom/event->target event)
|
||||||
parent (.-parentNode target)
|
parent (.-parentNode target)
|
||||||
data {:id (:id shape)
|
name (dom/get-value target)]
|
||||||
:name (dom/get-value target)}]
|
|
||||||
(set! (.-draggable parent) true)
|
(set! (.-draggable parent) true)
|
||||||
(st/emit! (uds/update-shape data))
|
(st/emit! (uds/rename-shape id name))
|
||||||
(swap! local assoc :edition false)))
|
(swap! local assoc :edition false)))
|
||||||
(on-key-down [event]
|
(on-key-down [event]
|
||||||
(js/console.log event)
|
(js/console.log event)
|
||||||
|
@ -295,8 +294,8 @@
|
||||||
groups (into #{} xform selected)]
|
groups (into #{} xform selected)]
|
||||||
(= 1 (count groups))))
|
(= 1 (count groups))))
|
||||||
|
|
||||||
(defn- allow-degrouping?
|
(defn- allow-ungrouping?
|
||||||
"Check if the current situation allows degrouping
|
"Check if the current situation allows ungrouping
|
||||||
of the currently selected shapes."
|
of the currently selected shapes."
|
||||||
[selected shapes-map]
|
[selected shapes-map]
|
||||||
(let [xform (comp (map shapes-map)
|
(let [xform (comp (map shapes-map)
|
||||||
|
@ -310,11 +309,11 @@
|
||||||
[selected shapes-map]
|
[selected shapes-map]
|
||||||
(let [duplicate #(st/emit! (uds/duplicate-selected))
|
(let [duplicate #(st/emit! (uds/duplicate-selected))
|
||||||
group #(st/emit! (uds/group-selected))
|
group #(st/emit! (uds/group-selected))
|
||||||
degroup #(st/emit! (uds/degroup-selected))
|
ungroup #(st/emit! (uds/ungroup-selected))
|
||||||
delete #(st/emit! (uds/delete-selected))
|
delete #(st/emit! (uds/delete-selected))
|
||||||
|
|
||||||
allow-grouping? (allow-grouping? selected shapes-map)
|
allow-grouping? (allow-grouping? selected shapes-map)
|
||||||
allow-degrouping? (allow-degrouping? selected shapes-map)
|
allow-ungrouping? (allow-ungrouping? selected shapes-map)
|
||||||
allow-duplicate? (= 1 (count selected))
|
allow-duplicate? (= 1 (count selected))
|
||||||
allow-deletion? (pos? (count selected))]
|
allow-deletion? (pos? (count selected))]
|
||||||
[:div.layers-tools
|
[:div.layers-tools
|
||||||
|
@ -331,8 +330,8 @@
|
||||||
i/folder]
|
i/folder]
|
||||||
[:li.degroup-layer.tooltip.tooltip-top
|
[:li.degroup-layer.tooltip.tooltip-top
|
||||||
{:alt "Ungroup"
|
{:alt "Ungroup"
|
||||||
:class (when-not allow-degrouping? "disable")
|
:class (when-not allow-ungrouping? "disable")
|
||||||
:on-click degroup}
|
:on-click ungroup}
|
||||||
i/ungroup]
|
i/ungroup]
|
||||||
[:li.delete-layer.tooltip.tooltip-top
|
[:li.delete-layer.tooltip.tooltip-top
|
||||||
{:alt "Delete"
|
{:alt "Delete"
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
[uxbox.util.mixins :as mx :include-macros true]
|
[uxbox.util.mixins :as mx :include-macros true]
|
||||||
[uxbox.main.geom :as geom]
|
[uxbox.main.geom :as geom]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.util.math :refer (precision-or-0)]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.util.data :refer (parse-int parse-float read-string)]))
|
[uxbox.util.data :refer (parse-int parse-float read-string)]
|
||||||
|
[uxbox.util.math :refer (precision-or-0)]))
|
||||||
|
|
||||||
(mx/defc circle-measures-menu
|
(mx/defc circle-measures-menu
|
||||||
{:mixins [mx/static]}
|
{:mixins [mx/static]}
|
||||||
|
@ -30,7 +31,7 @@
|
||||||
value (parse-int value 0)
|
value (parse-int value 0)
|
||||||
sid (:id shape)
|
sid (:id shape)
|
||||||
props {attr value}]
|
props {attr value}]
|
||||||
(st/emit! (uds/update-size sid props))))
|
(st/emit! (uds/update-dimensions sid props))))
|
||||||
(on-rotation-change [event]
|
(on-rotation-change [event]
|
||||||
(let [value (dom/event->value event)
|
(let [value (dom/event->value event)
|
||||||
value (parse-int value 0)
|
value (parse-int value 0)
|
||||||
|
@ -40,8 +41,8 @@
|
||||||
(let [value (dom/event->value event)
|
(let [value (dom/event->value event)
|
||||||
value (parse-int value nil)
|
value (parse-int value nil)
|
||||||
sid (:id shape)
|
sid (:id shape)
|
||||||
props {attr value}]
|
point (gpt/point {attr value})]
|
||||||
(st/emit! (uds/update-position sid props))))
|
(st/emit! (uds/update-position sid point))))
|
||||||
(on-proportion-lock-change [event]
|
(on-proportion-lock-change [event]
|
||||||
(if (:proportion-lock shape)
|
(if (:proportion-lock shape)
|
||||||
(st/emit! (uds/unlock-proportions id))
|
(st/emit! (uds/unlock-proportions id))
|
||||||
|
|
|
@ -19,8 +19,9 @@
|
||||||
[uxbox.util.mixins :as mx :include-macros true]
|
[uxbox.util.mixins :as mx :include-macros true]
|
||||||
[uxbox.main.geom :as geom]
|
[uxbox.main.geom :as geom]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.util.math :refer (precision-or-0)]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.util.data :refer (parse-int parse-float read-string)]))
|
[uxbox.util.data :refer (parse-int parse-float read-string)]
|
||||||
|
[uxbox.util.math :refer (precision-or-0)]))
|
||||||
|
|
||||||
(defn- icon-measures-menu-render
|
(defn- icon-measures-menu-render
|
||||||
[own menu shape]
|
[own menu shape]
|
||||||
|
@ -29,7 +30,7 @@
|
||||||
value (parse-int value 0)
|
value (parse-int value 0)
|
||||||
sid (:id shape)
|
sid (:id shape)
|
||||||
props {attr value}]
|
props {attr value}]
|
||||||
(st/emit! (uds/update-size sid props))))
|
(st/emit! (uds/update-dimensions sid props))))
|
||||||
(on-rotation-change [event]
|
(on-rotation-change [event]
|
||||||
(let [value (dom/event->value event)
|
(let [value (dom/event->value event)
|
||||||
value (parse-int value 0)
|
value (parse-int value 0)
|
||||||
|
@ -39,8 +40,8 @@
|
||||||
(let [value (dom/event->value event)
|
(let [value (dom/event->value event)
|
||||||
value (parse-int value nil)
|
value (parse-int value nil)
|
||||||
sid (:id shape)
|
sid (:id shape)
|
||||||
props {attr value}]
|
point (gpt/point {attr value})]
|
||||||
(st/emit! (uds/update-position sid props))))
|
(st/emit! (uds/update-position sid point))))
|
||||||
(on-proportion-lock-change [event]
|
(on-proportion-lock-change [event]
|
||||||
(if (:proportion-lock shape)
|
(if (:proportion-lock shape)
|
||||||
(st/emit! (uds/unlock-proportions (:id shape)))
|
(st/emit! (uds/unlock-proportions (:id shape)))
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
(ns uxbox.main.ui.workspace.sidebar.options.rect-measures
|
(ns uxbox.main.ui.workspace.sidebar.options.rect-measures
|
||||||
(:require [lentes.core :as l]
|
(:require [lentes.core :as l]
|
||||||
[uxbox.util.i18n :refer (tr)]
|
[uxbox.util.i18n :refer [tr]]
|
||||||
[uxbox.util.router :as r]
|
[uxbox.util.router :as r]
|
||||||
[potok.core :as ptk]
|
[potok.core :as ptk]
|
||||||
[uxbox.main.store :as st]
|
[uxbox.main.store :as st]
|
||||||
|
@ -17,8 +17,9 @@
|
||||||
[uxbox.util.mixins :as mx :include-macros true]
|
[uxbox.util.mixins :as mx :include-macros true]
|
||||||
[uxbox.main.geom :as geom]
|
[uxbox.main.geom :as geom]
|
||||||
[uxbox.util.dom :as dom]
|
[uxbox.util.dom :as dom]
|
||||||
[uxbox.util.math :refer (precision-or-0)]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.util.data :refer (parse-int parse-float read-string)]))
|
[uxbox.util.data :refer [parse-int parse-float read-string]]
|
||||||
|
[uxbox.util.math :refer [precision-or-0]]))
|
||||||
|
|
||||||
(mx/defc rect-measures-menu
|
(mx/defc rect-measures-menu
|
||||||
{:mixins [mx/static]}
|
{:mixins [mx/static]}
|
||||||
|
@ -26,15 +27,16 @@
|
||||||
(letfn [(on-size-change [event attr]
|
(letfn [(on-size-change [event attr]
|
||||||
(let [value (-> (dom/event->value event)
|
(let [value (-> (dom/event->value event)
|
||||||
(parse-int 0))]
|
(parse-int 0))]
|
||||||
(st/emit! (uds/update-size id {attr value}))))
|
(st/emit! (uds/update-dimensions id {attr value}))))
|
||||||
(on-rotation-change [event]
|
(on-rotation-change [event]
|
||||||
(let [value (-> (dom/event->value event)
|
(let [value (-> (dom/event->value event)
|
||||||
(parse-int 0))]
|
(parse-int 0))]
|
||||||
(st/emit! (uds/update-rotation id value))))
|
(st/emit! (uds/update-rotation id value))))
|
||||||
(on-pos-change [event attr]
|
(on-pos-change [event attr]
|
||||||
(let [value (-> (dom/event->value event)
|
(let [value (-> (dom/event->value event)
|
||||||
(parse-int nil))]
|
(parse-int nil))
|
||||||
(st/emit! (uds/update-position id {attr value}))))
|
point (gpt/point {attr value})]
|
||||||
|
(st/emit! (uds/update-position id point))))
|
||||||
(on-proportion-lock-change [event]
|
(on-proportion-lock-change [event]
|
||||||
(if (:proportion-lock shape)
|
(if (:proportion-lock shape)
|
||||||
(st/emit! (uds/unlock-proportions id))
|
(st/emit! (uds/unlock-proportions id))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue