mirror of
https://github.com/penpot/penpot.git
synced 2025-07-26 00:27:18 +02:00
♻️ Refactor transforms
This commit is contained in:
parent
2c50bb16dc
commit
af68c26aea
32 changed files with 1085 additions and 685 deletions
|
@ -14,6 +14,7 @@
|
|||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.proportions :as gpr]
|
||||
[app.common.geom.align :as gal]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages :as cp]
|
||||
|
@ -30,6 +31,7 @@
|
|||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.texts :as dwtxt]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[app.main.data.workspace.drawing :as dwd]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.main.streams :as ms]
|
||||
|
@ -472,10 +474,10 @@
|
|||
(let [vbox (update vbox :x + (:left-offset vbox))
|
||||
new-zoom (if (fn? zoom) (zoom (:zoom local)) zoom)
|
||||
old-zoom (:zoom local)
|
||||
center (if center center (gsh/center vbox))
|
||||
center (if center center (gsh/center-rect vbox))
|
||||
scale (/ old-zoom new-zoom)
|
||||
mtx (gmt/scale-matrix (gpt/point scale) center)
|
||||
vbox' (gsh/transform vbox mtx)
|
||||
vbox' (gsh/transform-rect vbox mtx)
|
||||
vbox' (update vbox' :x - (:left-offset vbox))]
|
||||
(-> local
|
||||
(assoc :zoom new-zoom)
|
||||
|
@ -546,50 +548,6 @@
|
|||
|
||||
;; --- Add shape to Workspace
|
||||
|
||||
(declare start-edition-mode)
|
||||
|
||||
(defn add-shape
|
||||
[attrs]
|
||||
(us/verify ::shape-attrs attrs)
|
||||
(ptk/reify ::add-shape
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (dwc/lookup-page-objects state page-id)
|
||||
|
||||
id (uuid/next)
|
||||
shape (geom/setup-proportions attrs)
|
||||
|
||||
unames (dwc/retrieve-used-names objects)
|
||||
name (dwc/generate-unique-name unames (:name shape))
|
||||
|
||||
frame-id (or (:frame-id attrs)
|
||||
(cph/frame-id-by-position objects attrs))
|
||||
|
||||
shape (merge
|
||||
(if (= :frame (:type shape))
|
||||
cp/default-frame-attrs
|
||||
cp/default-shape-attrs)
|
||||
(assoc shape
|
||||
:id id
|
||||
:name name))
|
||||
|
||||
rchange {:type :add-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:frame-id frame-id
|
||||
:obj shape}
|
||||
uchange {:type :del-obj
|
||||
:page-id page-id
|
||||
:id id}]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (dwc/commit-changes [rchange] [uchange] {:commit-local? true})
|
||||
(dws/select-shapes (d/ordered-set id)))
|
||||
(when (= :text (:type attrs))
|
||||
(->> (rx/of (start-edition-mode id))
|
||||
(rx/observe-on :async))))))))
|
||||
|
||||
(defn- viewport-center
|
||||
[state]
|
||||
(let [{:keys [x y width height]} (get-in state [:workspace-local :vbox])]
|
||||
|
@ -615,8 +573,8 @@
|
|||
(merge data)
|
||||
(merge {:x x :y y})
|
||||
(assoc :frame-id frame-id)
|
||||
(rx/of (add-shape shape))))))
|
||||
(gsh/setup-selrect))]
|
||||
(rx/of (dwc/add-shape shape))))))
|
||||
|
||||
;; --- Update Shape Attrs
|
||||
|
||||
|
@ -954,7 +912,7 @@
|
|||
|
||||
(defn align-objects
|
||||
[axis]
|
||||
(us/verify ::geom/align-axis axis)
|
||||
(us/verify ::gal/align-axis axis)
|
||||
(ptk/reify :align-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
@ -992,17 +950,17 @@
|
|||
[objects object-id axis]
|
||||
(let [object (get objects object-id)
|
||||
frame (get objects (:frame-id object))]
|
||||
(geom/align-to-rect object frame axis objects)))
|
||||
(gal/align-to-rect object frame axis objects)))
|
||||
|
||||
(defn align-objects-list
|
||||
[objects selected axis]
|
||||
(let [selected-objs (map #(get objects %) selected)
|
||||
rect (geom/selection-rect selected-objs)]
|
||||
(mapcat #(geom/align-to-rect % rect axis objects) selected-objs)))
|
||||
rect (gsh/selection-rect selected-objs)]
|
||||
(mapcat #(gal/align-to-rect % rect axis objects) selected-objs)))
|
||||
|
||||
(defn distribute-objects
|
||||
[axis]
|
||||
(us/verify ::geom/dist-axis axis)
|
||||
(us/verify ::gal/dist-axis axis)
|
||||
(ptk/reify :align-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
@ -1010,7 +968,7 @@
|
|||
objects (dwc/lookup-page-objects state page-id)
|
||||
selected (get-in state [:workspace-local :selected])
|
||||
moved (-> (map #(get objects %) selected)
|
||||
(geom/distribute-space axis objects))]
|
||||
(gal/distribute-space axis objects))]
|
||||
(loop [moved (seq moved)
|
||||
rchanges []
|
||||
uchanges []]
|
||||
|
@ -1035,62 +993,6 @@
|
|||
:operations ops2
|
||||
:id (:id curr)})))))))))
|
||||
|
||||
;; --- Start shape "edition mode"
|
||||
|
||||
(declare clear-edition-mode)
|
||||
|
||||
(defn start-edition-mode
|
||||
[id]
|
||||
(us/assert ::us/uuid id)
|
||||
(ptk/reify ::start-edition-mode
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-local :edition] id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> stream
|
||||
(rx/filter dwc/interrupt?)
|
||||
(rx/take 1)
|
||||
(rx/map (constantly clear-edition-mode))))))
|
||||
|
||||
(def clear-edition-mode
|
||||
(ptk/reify ::clear-edition-mode
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-local dissoc :edition))))
|
||||
|
||||
;; --- Select for Drawing
|
||||
|
||||
(def clear-drawing
|
||||
(ptk/reify ::clear-drawing
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-drawing dissoc :tool :object))))
|
||||
|
||||
(defn select-for-drawing
|
||||
([tool] (select-for-drawing tool nil))
|
||||
([tool data]
|
||||
(ptk/reify ::select-for-drawing
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-drawing assoc :tool tool :object data))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [stoper (rx/filter (ptk/type? ::clear-drawing) stream)]
|
||||
(rx/merge
|
||||
(rx/of (dws/deselect-all))
|
||||
|
||||
;; NOTE: comments are a special case and they manage they
|
||||
;; own interrupt cycle.
|
||||
(when (not= tool :comments)
|
||||
(->> stream
|
||||
(rx/filter dwc/interrupt?)
|
||||
(rx/take 1)
|
||||
(rx/map (constantly clear-drawing))
|
||||
(rx/take-until stoper)))))))))
|
||||
|
||||
;; --- Update Dimensions
|
||||
|
||||
;; Event mainly used for handling user modification of the size of the
|
||||
|
@ -1104,7 +1006,7 @@
|
|||
(ptk/reify ::update-dimensions
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of (dwc/update-shapes ids #(geom/resize-rect % attr value))))))
|
||||
(rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value))))))
|
||||
|
||||
|
||||
;; --- Shape Proportions
|
||||
|
@ -1118,7 +1020,7 @@
|
|||
(if-not lock
|
||||
(assoc shape :proportion-lock false)
|
||||
(-> (assoc shape :proportion-lock true)
|
||||
(geom/assign-proportions)))))))))
|
||||
(gpr/assign-proportions)))))))))
|
||||
;; --- Update Shape Position
|
||||
|
||||
(s/def ::x number?)
|
||||
|
@ -1157,7 +1059,7 @@
|
|||
(let [page-id (:current-page-id state)]
|
||||
(-> state
|
||||
(update-in [:workspace-data page-id :objects id :segments index] gpt/add delta)
|
||||
(update-in [:workspace-data page-id :objects id] geom/update-path-selrect))))))
|
||||
(update-in [:workspace-data page-id :objects id] gsh/update-path-selrect))))))
|
||||
|
||||
;; --- Shape attrs (Layers Sidebar)
|
||||
|
||||
|
@ -1290,7 +1192,7 @@
|
|||
;; When the parent frame is not selected we change to relative
|
||||
;; coordinates
|
||||
(let [frame (get objects (:frame-id shape))]
|
||||
(geom/translate-to-frame shape frame))
|
||||
(gsh/translate-to-frame shape frame))
|
||||
shape))
|
||||
|
||||
(prepare [result objects selected id]
|
||||
|
@ -1329,7 +1231,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [selected-objs (map #(get objects %) selected)
|
||||
wrapper (geom/selection-rect selected-objs)
|
||||
wrapper (gsh/selection-rect selected-objs)
|
||||
orig-pos (gpt/point (:x1 wrapper) (:y1 wrapper))
|
||||
mouse-pos @ms/mouse-position
|
||||
|
||||
|
@ -1359,7 +1261,7 @@
|
|||
(map #(get-in % [:obj :id]))
|
||||
(into (d/ordered-set)))]
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dws/select-shapes selected))))))
|
||||
(dwc/select-shapes selected))))))
|
||||
|
||||
(defn- image-uploaded
|
||||
[image]
|
||||
|
@ -1446,7 +1348,7 @@
|
|||
page-id (:current-page-id state)
|
||||
frame-id (-> (dwc/lookup-page-objects state page-id)
|
||||
(cph/frame-id-by-position @ms/mouse-position))
|
||||
shape (geom/setup-selrect
|
||||
shape (gsh/setup-selrect
|
||||
{:id id
|
||||
:type :text
|
||||
:name "Text"
|
||||
|
@ -1459,7 +1361,7 @@
|
|||
:content (as-content text)})]
|
||||
(rx/of dwc/start-undo-transaction
|
||||
(dws/deselect-all)
|
||||
(add-shape shape)
|
||||
(dwc/add-shape shape)
|
||||
dwc/commit-undo-transaction)))))
|
||||
|
||||
(defn update-shape-flags
|
||||
|
@ -1490,7 +1392,7 @@
|
|||
(when-not (empty? shapes)
|
||||
(let [[group rchanges uchanges] (dws/prepare-create-group page-id shapes "Group-" false)]
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dws/select-shapes (d/ordered-set (:id group))))))))))
|
||||
(dwc/select-shapes (d/ordered-set (:id group))))))))))
|
||||
|
||||
(def ungroup-selected
|
||||
(ptk/reify ::ungroup-selected
|
||||
|
@ -1568,7 +1470,7 @@
|
|||
:val (:fill-color mask)}]}))]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dws/select-shapes (d/ordered-set (:id group))))))))))
|
||||
(dwc/select-shapes (d/ordered-set (:id group))))))))))
|
||||
|
||||
(def unmask-group
|
||||
(ptk/reify ::unmask-group
|
||||
|
@ -1595,7 +1497,7 @@
|
|||
:val (:masked-group? group)}]}]]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dws/select-shapes (d/ordered-set (:id group))))))))))
|
||||
(dwc/select-shapes (d/ordered-set (:id group))))))))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -1718,10 +1620,14 @@
|
|||
|
||||
(def select-shape dws/select-shape)
|
||||
(def deselect-all dws/deselect-all)
|
||||
(def select-shapes dws/select-shapes)
|
||||
(def select-shapes dwc/select-shapes)
|
||||
(def duplicate-selected dws/duplicate-selected)
|
||||
(def handle-selection dws/handle-selection)
|
||||
(def select-inside-group dws/select-inside-group)
|
||||
(def select-for-drawing dwd/select-for-drawing)
|
||||
(def clear-edition-mode dwc/clear-edition-mode)
|
||||
(def add-shape dwc/add-shape)
|
||||
(def start-edition-mode dwc/start-edition-mode)
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
@ -1753,12 +1659,12 @@
|
|||
"ctrl+shift+z" #(st/emit! dwc/redo)
|
||||
"ctrl+y" #(st/emit! dwc/redo)
|
||||
"ctrl+q" #(st/emit! dwc/reinitialize-undo)
|
||||
"a" #(st/emit! (select-for-drawing :frame))
|
||||
"b" #(st/emit! (select-for-drawing :rect))
|
||||
"e" #(st/emit! (select-for-drawing :circle))
|
||||
"a" #(st/emit! (dwd/select-for-drawing :frame))
|
||||
"b" #(st/emit! (dwd/select-for-drawing :rect))
|
||||
"e" #(st/emit! (dwd/select-for-drawing :circle))
|
||||
"t" #(st/emit! dwtxt/start-edit-if-selected
|
||||
(select-for-drawing :text))
|
||||
"w" #(st/emit! (select-for-drawing :path))
|
||||
(dwd/select-for-drawing :text))
|
||||
"w" #(st/emit! (dwd/select-for-drawing :path))
|
||||
"ctrl+c" #(st/emit! copy-selected)
|
||||
"ctrl+v" #(st/emit! paste)
|
||||
"ctrl+x" #(st/emit! copy-selected delete-selected)
|
||||
|
@ -1778,4 +1684,3 @@
|
|||
"right" #(st/emit! (dwt/move-selected :right false))
|
||||
"left" #(st/emit! (dwt/move-selected :left false))
|
||||
"i" #(st/emit! (mdc/picker-for-selected-shape ))})
|
||||
|
||||
|
|
|
@ -20,8 +20,12 @@
|
|||
[app.common.uuid :as uuid]
|
||||
[app.main.worker :as uw]
|
||||
[app.util.timers :as ts]
|
||||
[app.common.geom.shapes :as geom]))
|
||||
[app.common.geom.proportions :as gpr]
|
||||
[app.common.geom.shapes :as gsh]))
|
||||
|
||||
(s/def ::shape-attrs ::cp/shape-attrs)
|
||||
(s/def ::set-of-string (s/every string? :kind set?))
|
||||
(s/def ::ordered-set-of-uuid (s/every uuid? :kind d/ordered-set?))
|
||||
;; --- Protocols
|
||||
|
||||
(declare setup-selection-index)
|
||||
|
@ -158,7 +162,7 @@
|
|||
(defn get-frame-at-point
|
||||
[objects point]
|
||||
(let [frames (cph/select-frames objects)]
|
||||
(d/seek #(geom/has-point? % point) frames)))
|
||||
(d/seek #(gsh/has-point? % point) frames)))
|
||||
|
||||
|
||||
(defn- extract-numeric-suffix
|
||||
|
@ -171,8 +175,6 @@
|
|||
[objects]
|
||||
(into #{} (map :name) (vals objects)))
|
||||
|
||||
(s/def ::set-of-string
|
||||
(s/every string? :kind set?))
|
||||
|
||||
(defn generate-unique-name
|
||||
"A unique name generator"
|
||||
|
@ -434,3 +436,85 @@
|
|||
[rchanges uchanges] (impl-gen-changes objects page-id (seq ids))]
|
||||
(rx/of (commit-changes rchanges uchanges {:commit-local? true})))))))
|
||||
|
||||
|
||||
(defn select-shapes
|
||||
[ids]
|
||||
(us/verify ::ordered-set-of-uuid ids)
|
||||
(ptk/reify ::select-shapes
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-local :selected] ids))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (lookup-page-objects state page-id)]
|
||||
(rx/of (expand-all-parents ids objects))))))
|
||||
|
||||
;; --- Start shape "edition mode"
|
||||
|
||||
(declare clear-edition-mode)
|
||||
|
||||
(defn start-edition-mode
|
||||
[id]
|
||||
(us/assert ::us/uuid id)
|
||||
(ptk/reify ::start-edition-mode
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-local :edition] id))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> stream
|
||||
(rx/filter interrupt?)
|
||||
(rx/take 1)
|
||||
(rx/map (constantly clear-edition-mode))))))
|
||||
|
||||
(def clear-edition-mode
|
||||
(ptk/reify ::clear-edition-mode
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-local dissoc :edition))))
|
||||
|
||||
|
||||
(defn add-shape
|
||||
[attrs]
|
||||
(us/verify ::shape-attrs attrs)
|
||||
(ptk/reify ::add-shape
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (lookup-page-objects state page-id)
|
||||
|
||||
id (uuid/next)
|
||||
shape (gpr/setup-proportions attrs)
|
||||
|
||||
unames (retrieve-used-names objects)
|
||||
name (generate-unique-name unames (:name shape))
|
||||
|
||||
frame-id (or (:frame-id attrs)
|
||||
(cph/frame-id-by-position objects attrs))
|
||||
|
||||
shape (merge
|
||||
(if (= :frame (:type shape))
|
||||
cp/default-frame-attrs
|
||||
cp/default-shape-attrs)
|
||||
(assoc shape
|
||||
:id id
|
||||
:name name))
|
||||
|
||||
rchange {:type :add-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:frame-id frame-id
|
||||
:obj shape}
|
||||
uchange {:type :del-obj
|
||||
:page-id page-id
|
||||
:id id}]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (commit-changes [rchange] [uchange] {:commit-local? true})
|
||||
(select-shapes (d/ordered-set id)))
|
||||
(when (= :text (:type attrs))
|
||||
(->> (rx/of (start-edition-mode id))
|
||||
(rx/observe-on :async))))))))
|
||||
|
|
|
@ -12,15 +12,48 @@
|
|||
(:require
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]
|
||||
[app.common.spec :as us]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.drawing.common :as common]
|
||||
[app.main.data.workspace.drawing.path :as path]
|
||||
[app.main.data.workspace.drawing.curve :as curve]
|
||||
[app.main.data.workspace.drawing.box :as box]))
|
||||
|
||||
(declare start-drawing)
|
||||
(declare handle-drawing)
|
||||
|
||||
;; --- Select for Drawing
|
||||
|
||||
(defn select-for-drawing
|
||||
([tool] (select-for-drawing tool nil))
|
||||
([tool data]
|
||||
(ptk/reify ::select-for-drawing
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-drawing assoc :tool tool :object data))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [stoper (rx/filter (ptk/type? ::clear-drawing) stream)]
|
||||
(rx/merge
|
||||
(rx/of (dws/deselect-all))
|
||||
|
||||
(when (= tool :path)
|
||||
(rx/of (start-drawing :path)))
|
||||
|
||||
;; NOTE: comments are a special case and they manage they
|
||||
;; own interrupt cycle.
|
||||
(when (not= tool :comments)
|
||||
(->> stream
|
||||
(rx/filter dwc/interrupt?)
|
||||
(rx/take 1)
|
||||
(rx/map (constantly common/clear-drawing))
|
||||
(rx/take-until stoper)))))))))
|
||||
|
||||
|
||||
;; NOTE/TODO: when an exception is raised in some point of drawing the
|
||||
;; draw lock is not released so the user need to refresh in order to
|
||||
;; be able draw again. THIS NEED TO BE REVISITED
|
||||
|
@ -68,3 +101,4 @@
|
|||
;; Export
|
||||
(def close-drawing-path path/close-drawing-path)
|
||||
|
||||
|
||||
|
|
|
@ -74,7 +74,8 @@
|
|||
;; Initial SNAP
|
||||
(->> (snap/closest-snap-point page-id [shape] layout initial)
|
||||
(rx/map (fn [{:keys [x y]}]
|
||||
#(update-in % [:workspace-drawing :object] assoc :x x :y y))))
|
||||
#(update-in % [:workspace-drawing :object] gsh/absolute-move (gpt/point x y))
|
||||
)))
|
||||
|
||||
(->> ms/mouse-position
|
||||
(rx/filter #(> (gpt/distance % initial) 2))
|
||||
|
|
|
@ -13,17 +13,23 @@
|
|||
[potok.core :as ptk]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.streams :as ms]))
|
||||
|
||||
(def clear-drawing
|
||||
(ptk/reify ::clear-drawing
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-drawing dissoc :tool :object))))
|
||||
|
||||
(def handle-finish-drawing
|
||||
(ptk/reify ::handle-finish-drawing
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [shape (get-in state [:workspace-drawing :object])]
|
||||
(rx/concat
|
||||
(rx/of dw/clear-drawing)
|
||||
(rx/of clear-drawing)
|
||||
(when (:initialized? shape)
|
||||
(let [shape-click-width (case (:type shape)
|
||||
:text 3
|
||||
|
@ -52,5 +58,5 @@
|
|||
(rx/of dwc/start-undo-transaction)
|
||||
(rx/empty))
|
||||
|
||||
(rx/of (dw/deselect-all)
|
||||
(dw/add-shape shape))))))))))
|
||||
(rx/of (dws/deselect-all)
|
||||
(dwc/add-shape shape))))))))))
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
(:require
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.main.streams :as ms]
|
||||
[app.util.geom.path :as path]
|
||||
|
@ -27,13 +28,18 @@
|
|||
(defn insert-point-segment [state point]
|
||||
(update-in state [:workspace-drawing :object :segments] (fnil conj []) point))
|
||||
|
||||
(defn update-selrect [{:keys [segments] :as shape}]
|
||||
(let [points (->> segments
|
||||
(map #(apply gpt/point %)))]
|
||||
(assoc shape :selrect (gsh/points->selrect points))))
|
||||
|
||||
(defn finish-drawing-curve [state]
|
||||
(update-in
|
||||
state [:workspace-drawing :object]
|
||||
(fn [shape]
|
||||
(-> shape
|
||||
(update :segments #(path/simplify % simplify-tolerance))
|
||||
(gsh/update-path-selrect)))))
|
||||
(update-selrect)))))
|
||||
|
||||
(defn handle-drawing-curve []
|
||||
(ptk/reify ::handle-drawing-curve
|
||||
|
|
|
@ -17,23 +17,23 @@
|
|||
[app.util.geom.path :as path]
|
||||
[app.main.data.workspace.drawing.common :as common]))
|
||||
|
||||
(defn stoper-event? [{:keys [type shift] :as event}]
|
||||
(defn finish-event? [{:keys [type shift] :as event}]
|
||||
(or (= event ::end-path-drawing)
|
||||
(= event :interrupt)
|
||||
(and (ms/mouse-event? event)
|
||||
#_(and (ms/mouse-event? event)
|
||||
(or (= type :double-click)
|
||||
(= type :context-menu)))
|
||||
(and (ms/keyboard-event? event)
|
||||
(= type :down)
|
||||
(= 13 (:key event)))))
|
||||
|
||||
(defn init-path []
|
||||
#_(defn init-path []
|
||||
(fn [state]
|
||||
(update-in state [:workspace-drawing :object]
|
||||
assoc :content []
|
||||
:initialized? true)))
|
||||
|
||||
(defn add-path-command [command]
|
||||
#_(defn add-path-command [command]
|
||||
(fn [state]
|
||||
(update-in state [:workspace-drawing :object :content] conj command)))
|
||||
|
||||
|
@ -43,7 +43,7 @@
|
|||
(cond-> state
|
||||
exists? (assoc-in [:workspace-drawing :object :segments index] point))))
|
||||
|
||||
(defn finish-drawing-path []
|
||||
#_(defn finish-drawing-path []
|
||||
(fn [state]
|
||||
(update-in
|
||||
state [:workspace-drawing :object]
|
||||
|
@ -52,17 +52,109 @@
|
|||
(gsh/update-path-selrect))))))
|
||||
|
||||
|
||||
(defn handle-drawing-path []
|
||||
(defn calculate-selrect [shape]
|
||||
(let [points (->> shape
|
||||
:content
|
||||
(mapv #(gpt/point
|
||||
(-> % :params :x)
|
||||
(-> % :params :y))))]
|
||||
(assoc shape
|
||||
:points points
|
||||
:selrect (gsh/points->selrect points))))
|
||||
|
||||
(defn init-path []
|
||||
(ptk/reify ::init-path
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :initialized?] true)
|
||||
(assoc-in [:workspace-drawing :object :last-point] nil)))))
|
||||
|
||||
(defn finish-path []
|
||||
(ptk/reify ::finish-path
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :last-point] nil)
|
||||
(update-in [:workspace-drawing :object] calculate-selrect)))))
|
||||
|
||||
(defn add-node [{:keys [x y]}]
|
||||
(ptk/reify ::add-node
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [point {:x x :y y}
|
||||
last-point (get-in state [:workspace-drawing :object :last-point])
|
||||
command (if last-point
|
||||
{:command :line-to
|
||||
:params point}
|
||||
{:command :move-to
|
||||
:params point})]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :last-point] point)
|
||||
(update-in [:workspace-drawing :object :content] (fnil conj []) command))))))
|
||||
|
||||
(defn drag-handler [{:keys [x y]}]
|
||||
(ptk/reify ::drag-handler
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state))))
|
||||
|
||||
(defn make-click-stream
|
||||
[stream down-event]
|
||||
(->> stream
|
||||
(rx/filter ms/mouse-click?)
|
||||
(rx/debounce 200)
|
||||
(rx/first)
|
||||
(rx/map #(add-node down-event))))
|
||||
|
||||
(defn make-drag-stream
|
||||
[stream down-event]
|
||||
(let [mouse-up (->> stream (rx/filter ms/mouse-up?))
|
||||
drag-events (->> ms/mouse-position
|
||||
(rx/take-until mouse-up)
|
||||
(rx/map #(drag-handler %)))]
|
||||
(->> (rx/timer 400)
|
||||
(rx/merge-map #(rx/concat
|
||||
(add-node down-event)
|
||||
drag-events)))))
|
||||
|
||||
(defn make-dbl-click-stream
|
||||
[stream down-event]
|
||||
(->> stream
|
||||
(rx/filter ms/mouse-double-click?)
|
||||
(rx/first)
|
||||
(rx/merge-map
|
||||
#(rx/of (add-node down-event)
|
||||
::end-path-drawing))))
|
||||
|
||||
(defn handle-drawing-path []
|
||||
(ptk/reify ::handle-drawing-path
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
||||
;; clicks stream<[MouseEvent, Position]>
|
||||
clicks (->> stream
|
||||
(rx/filter ms/mouse-click?)
|
||||
(rx/with-latest vector ms/mouse-position))
|
||||
(let [
|
||||
|
||||
mouse-down (->> stream (rx/filter ms/mouse-down?))
|
||||
finish-events (->> stream (rx/filter finish-event?))
|
||||
|
||||
events (->> mouse-down
|
||||
(rx/take-until finish-events)
|
||||
(rx/throttle 100)
|
||||
(rx/with-latest merge ms/mouse-position)
|
||||
|
||||
;; We change to the stream that emits the first event
|
||||
(rx/switch-map
|
||||
#(rx/race (make-click-stream stream %)
|
||||
(make-drag-stream stream %)
|
||||
(make-dbl-click-stream stream %))))]
|
||||
|
||||
|
||||
(rx/concat
|
||||
(rx/of (init-path))
|
||||
events
|
||||
(rx/of (finish-path))
|
||||
(rx/of common/handle-finish-drawing)))
|
||||
|
||||
|
||||
)))
|
||||
|
|
|
@ -251,7 +251,7 @@
|
|||
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dws/select-shapes (d/ordered-set (:id group))))))))))
|
||||
(dwc/select-shapes (d/ordered-set (:id group))))))))))
|
||||
|
||||
(defn rename-component
|
||||
[id new-name]
|
||||
|
@ -407,7 +407,7 @@
|
|||
new-shapes)]
|
||||
|
||||
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})
|
||||
(dws/select-shapes (d/ordered-set (:id new-shape))))))))
|
||||
(dwc/select-shapes (d/ordered-set (:id new-shape))))))))
|
||||
|
||||
(defn detach-component
|
||||
"Remove all references to components in the shape with the given id,
|
||||
|
|
|
@ -80,7 +80,8 @@
|
|||
(defn start-resize
|
||||
[handler initial ids shape]
|
||||
(letfn [(resize [shape initial resizing-shapes [point lock? point-snap]]
|
||||
(let [{:keys [width height rotation]} shape
|
||||
(let [{:keys [width height]} (:selrect shape)
|
||||
{:keys [rotation]} shape
|
||||
shapev (-> (gpt/point width height))
|
||||
|
||||
rotation (if (#{:curve :path} (:type shape)) 0 rotation)
|
||||
|
@ -101,9 +102,11 @@
|
|||
shape-transform (:transform shape (gmt/matrix))
|
||||
shape-transform-inverse (:transform-inverse shape (gmt/matrix))
|
||||
|
||||
shape-center (gsh/center-shape shape)
|
||||
|
||||
;; Resize origin point given the selected handler
|
||||
origin (-> (handler-resize-origin shape handler)
|
||||
(gsh/transform-shape-point shape shape-transform))]
|
||||
origin (-> (handler-resize-origin (:selrect shape) handler)
|
||||
(gsh/transform-point-center shape-center shape-transform))]
|
||||
|
||||
(rx/of (set-modifiers ids
|
||||
{:resize-vector scalev
|
||||
|
@ -170,7 +173,7 @@
|
|||
(watch [_ state stream]
|
||||
(let [stoper (rx/filter ms/mouse-up? stream)
|
||||
group (gsh/selection-rect shapes)
|
||||
group-center (gsh/center group)
|
||||
group-center (gsh/center-selrect group)
|
||||
initial-angle (gpt/angle @ms/mouse-position group-center)
|
||||
calculate-angle (fn [pos ctrl?]
|
||||
(let [angle (- (gpt/angle pos group-center) initial-angle)
|
||||
|
@ -403,7 +406,7 @@
|
|||
#(reduce update-shape % ids-with-children)))))))
|
||||
|
||||
(defn rotation-modifiers [center shape angle]
|
||||
(let [displacement (let [shape-center (gsh/center shape)]
|
||||
(let [displacement (let [shape-center (gsh/center-shape shape)]
|
||||
(-> (gmt/matrix)
|
||||
(gmt/rotate angle center)
|
||||
(gmt/rotate (- angle) shape-center)))]
|
||||
|
@ -416,7 +419,7 @@
|
|||
|
||||
(defn set-rotation
|
||||
([delta-rotation shapes]
|
||||
(set-rotation delta-rotation shapes (-> shapes gsh/selection-rect gsh/center)))
|
||||
(set-rotation delta-rotation shapes (-> shapes gsh/selection-rect gsh/center-selrect)))
|
||||
|
||||
([delta-rotation shapes center]
|
||||
(letfn [(rotate-shape [objects angle shape center]
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
(let [shapes (cph/select-toplevel-shapes objects {:include-frames? true})]
|
||||
(->> (gsh/selection-rect shapes)
|
||||
(gal/adjust-to-viewport vport)
|
||||
(gsh/fix-invalid-rect-values))))
|
||||
#_(gsh/fix-invalid-rect-values))))
|
||||
|
||||
(declare shape-wrapper-factory)
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@
|
|||
(rx/merge-map
|
||||
(fn [[frame selrect]]
|
||||
(let [areas (->> (gsh/selrect->areas (or (:selrect frame)
|
||||
(gsh/rect->rect-shape @refs/vbox)) selrect)
|
||||
(gsh/rect->selrect @refs/vbox)) selrect)
|
||||
(d/mapm #(select-shapes-area page-id shapes objects %2)))
|
||||
snap-x (search-snap-distance selrect :x (:left areas) (:right areas))
|
||||
snap-y (search-snap-distance selrect :y (:top areas) (:bottom areas))]
|
||||
|
|
|
@ -41,11 +41,10 @@
|
|||
|
||||
(when *assert*
|
||||
(defonce debug-subscription
|
||||
(as-> stream $
|
||||
#_(rx/filter ptk/event? $)
|
||||
(rx/filter (fn [s] (debug? :events)) $)
|
||||
(rx/subscribe $ (fn [event]
|
||||
(println "[stream]: " (repr-event event)))))))
|
||||
(->> stream
|
||||
(rx/filter ptk/event?)
|
||||
(rx/filter (fn [s] (debug? :events)))
|
||||
(rx/subs #(println "[stream]: " (repr-event %))))))
|
||||
(defn emit!
|
||||
([] nil)
|
||||
([event]
|
||||
|
@ -73,6 +72,11 @@
|
|||
(defn ^:export dump-state []
|
||||
(logjs "state" @state))
|
||||
|
||||
(defn ^:export get-state [str-path]
|
||||
(let [path (->> (str/split str-path " ")
|
||||
(map d/read-string))]
|
||||
(clj->js (get-in @state path))))
|
||||
|
||||
(defn ^:export dump-objects []
|
||||
(let [page-id (get @state :current-page-id)]
|
||||
(logjs "state" (get-in @state [:workspace-data :pages-index page-id :objects]))))
|
||||
|
|
|
@ -23,7 +23,8 @@
|
|||
(let [shape (unchecked-get props "shape")
|
||||
base-props (unchecked-get props "base-props")
|
||||
elem-name (unchecked-get props "elem-name")
|
||||
{:keys [x y width height]} (geom/shape->rect-shape shape)
|
||||
;; {:keys [x y width height]} (geom/shape->rect-shape shape)
|
||||
{:keys [x y width height]} (:selrect shape)
|
||||
mask-id (mf/use-ctx mask-id-ctx)
|
||||
stroke-id (mf/use-var (uuid/next))
|
||||
stroke-style (:stroke-style shape :none)
|
||||
|
|
|
@ -15,10 +15,12 @@
|
|||
[app.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]
|
||||
[app.main.ui.shapes.group :refer [mask-id-ctx]]
|
||||
[app.common.geom.shapes :as geom]
|
||||
[app.util.object :as obj]))
|
||||
[app.util.object :as obj]
|
||||
[app.util.geom.path :as ugp]))
|
||||
|
||||
;; --- Path Shape
|
||||
|
||||
;; LEGACY FORMAT
|
||||
(defn- render-path
|
||||
[{:keys [segments close?] :as shape}]
|
||||
(let [numsegs (count segments)]
|
||||
|
@ -45,10 +47,14 @@
|
|||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
background? (unchecked-get props "background?")
|
||||
{:keys [id x y width height]} (geom/shape->rect-shape shape)
|
||||
;; {:keys [id x y width height]} (geom/shape->rect-shape shape)
|
||||
{:keys [id x y width height]} (:selrect shape)
|
||||
mask-id (mf/use-ctx mask-id-ctx)
|
||||
transform (geom/transform-matrix shape)
|
||||
pdata (render-path shape)
|
||||
pdata (if (:content shape)
|
||||
(ugp/content->path (:content shape))
|
||||
(render-path shape))
|
||||
|
||||
props (-> (attrs/extract-style-attrs shape)
|
||||
(obj/merge!
|
||||
#js {:transform transform
|
||||
|
|
|
@ -181,7 +181,7 @@
|
|||
on-rotate (obj/get props "on-rotate")
|
||||
current-transform (mf/deref refs/current-transform)
|
||||
|
||||
selrect (geom/shape->rect-shape shape)
|
||||
selrect (:selrect shape)
|
||||
transform (geom/transform-matrix shape)
|
||||
|
||||
tr-shape (geom/transform-shape shape)]
|
||||
|
@ -269,8 +269,8 @@
|
|||
|
||||
(mf/defc multiple-selection-handlers
|
||||
[{:keys [shapes selected zoom color show-distances] :as props}]
|
||||
(let [shape (geom/selection-rect shapes)
|
||||
shape-center (geom/center shape)
|
||||
(let [shape (geom/setup {:type :rect} (geom/selection-rect shapes))
|
||||
shape-center (geom/center-shape shape)
|
||||
|
||||
hover-id (-> (mf/deref refs/current-hover) first)
|
||||
hover-id (when-not (d/seek #(= hover-id (:id %)) shapes) hover-id)
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
(let [shape (unchecked-get props "shape")
|
||||
frame (unchecked-get props "frame")
|
||||
selrect (-> shape :selrect)
|
||||
shape-center (geom/center shape)
|
||||
shape-center (geom/center-shape shape)
|
||||
line-color (rdcolor #js {:seed (str (:id shape))})
|
||||
zoom (mf/deref refs/selected-zoom)]
|
||||
[:g.bounding-box
|
||||
|
|
|
@ -141,8 +141,9 @@
|
|||
(fn [[selrect selected frame]]
|
||||
(let [lt-side (if (= coord :x) :left :top)
|
||||
gt-side (if (= coord :x) :right :bottom)
|
||||
areas (gsh/selrect->areas (or (:selrect frame)
|
||||
(gsh/rect->rect-shape @refs/vbox)) selrect)
|
||||
container-selrec (or (:selrect frame)
|
||||
(gsh/rect->selrect @refs/vbox))
|
||||
areas (gsh/selrect->areas container-selrec selrect)
|
||||
query-side (fn [side]
|
||||
(->> (uw/ask! {:cmd :selection/query
|
||||
:page-id page-id
|
||||
|
|
|
@ -232,8 +232,9 @@
|
|||
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt?))
|
||||
(cond
|
||||
(and (= 1 (.-which event)))
|
||||
|
||||
(if drawing-tool
|
||||
(when (not= drawing-tool :comments)
|
||||
(when (not (#{:comments :path} drawing-tool))
|
||||
(st/emit! (dd/start-drawing drawing-tool)))
|
||||
(st/emit! dw/handle-selection))
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@
|
|||
[app.util.worker :as uw]))
|
||||
|
||||
(defn on-error
|
||||
[instance error]
|
||||
(js/console.error "Error on worker" (.-data error)))
|
||||
[error]
|
||||
(js/console.error "Error on worker" error))
|
||||
|
||||
(defonce instance
|
||||
(when (not= *target* "nodejs")
|
||||
|
|
|
@ -27,9 +27,9 @@
|
|||
(defn shape-snap-points
|
||||
[shape]
|
||||
(let [shape (gsh/transform-shape shape)
|
||||
shape-center (gsh/center shape)]
|
||||
shape-center (gsh/center-shape shape)]
|
||||
(if (= :frame (:type shape))
|
||||
(-> shape
|
||||
(gsh/shape->rect-shape)
|
||||
:selrect
|
||||
(frame-snap-points))
|
||||
(into #{shape-center} (:points shape)))))
|
||||
|
|
|
@ -38,10 +38,12 @@
|
|||
(fn [event]
|
||||
(let [data (.-data event)
|
||||
data (t/decode data)]
|
||||
(rx/push! bus data))))
|
||||
(if (:error data)
|
||||
(on-error (:error data))
|
||||
(rx/push! bus data)))))
|
||||
(.addEventListener ins "error"
|
||||
(fn [error]
|
||||
(on-error wrk error)))
|
||||
(on-error wrk (.-data error))))
|
||||
|
||||
wrk))
|
||||
|
||||
|
|
|
@ -65,8 +65,7 @@
|
|||
|
||||
(defn- create-index
|
||||
[objects]
|
||||
(let [shapes (->> (cph/select-toplevel-shapes objects {:include-frames? true})
|
||||
(map #(merge % (select-keys % [:x :y :width :height]))))
|
||||
(let [shapes (cph/select-toplevel-shapes objects {:include-frames? true})
|
||||
bounds (geom/selection-rect shapes)
|
||||
bounds #js {:x (:x bounds)
|
||||
:y (:y bounds)
|
||||
|
@ -77,7 +76,8 @@
|
|||
shapes)))
|
||||
|
||||
(defn- index-object
|
||||
[index {:keys [id x y width height] :as obj}]
|
||||
(let [rect #js {:x x :y y :width width :height height}]
|
||||
[index obj]
|
||||
(let [{:keys [id x y width height]} (:selrect obj)
|
||||
rect #js {:x x :y y :width width :height height}]
|
||||
(qdt/insert index rect obj)))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue