mirror of
https://github.com/penpot/penpot.git
synced 2025-01-24 23:49:45 -05:00
✨ Show tools on path creation. Change snap while drawing
This commit is contained in:
parent
0632111e96
commit
75d6e21af8
7 changed files with 79 additions and 80 deletions
|
@ -60,7 +60,7 @@
|
|||
(point v v)
|
||||
|
||||
(point-like? v)
|
||||
(map->Point v)
|
||||
(Point. (:x v) (:y v))
|
||||
|
||||
:else
|
||||
(ex/raise :hint "invalid arguments (on pointer constructor)" :value v)))
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.flex-layout :as gsl]
|
||||
[app.common.geom.shapes.path :as upg]
|
||||
[app.common.path.commands :as upc]
|
||||
[app.common.path.shapes-to-path :as upsp]
|
||||
[app.common.spec :as us]
|
||||
|
@ -125,14 +124,11 @@
|
|||
(ptk/reify ::close-path-drag-start
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [id (st/get-path-id state)
|
||||
stop-stream
|
||||
(let [stop-stream
|
||||
(->> stream (rx/filter #(or (helpers/end-path-event? %)
|
||||
(ms/mouse-up? %))))
|
||||
|
||||
content (st/get-path state :content)
|
||||
snap-toggled (get-in state [:workspace-local :edit-path id :snap-toggled])
|
||||
points (upg/content->points content)
|
||||
|
||||
handlers (-> (upc/content->handlers content)
|
||||
(get position))
|
||||
|
@ -141,7 +137,7 @@
|
|||
(first handlers))
|
||||
|
||||
drag-events-stream
|
||||
(->> (streams/position-stream snap-toggled points)
|
||||
(->> (streams/position-stream)
|
||||
(rx/take-until stop-stream)
|
||||
(rx/map #(drag-handler position idx prefix %)))]
|
||||
|
||||
|
@ -164,16 +160,10 @@
|
|||
(defn start-path-from-point [position]
|
||||
(ptk/reify ::start-path-from-point
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(watch [_ _ stream]
|
||||
(let [mouse-up (->> stream (rx/filter #(or (helpers/end-path-event? %)
|
||||
(ms/mouse-up? %))))
|
||||
content (st/get-path state :content)
|
||||
points (upg/content->points content)
|
||||
|
||||
id (st/get-path-id state)
|
||||
snap-toggled (get-in state [:workspace-local :edit-path id :snap-toggled])
|
||||
|
||||
drag-events (->> (streams/position-stream snap-toggled points)
|
||||
drag-events (->> (streams/position-stream)
|
||||
(rx/take-until mouse-up)
|
||||
(rx/map #(drag-handler %)))]
|
||||
|
||||
|
@ -192,11 +182,11 @@
|
|||
(rx/merge-map #(rx/empty))))
|
||||
|
||||
(defn make-drag-stream
|
||||
[stream snap-toggled _zoom points down-event]
|
||||
[stream down-event]
|
||||
(let [mouse-up (->> stream (rx/filter #(or (helpers/end-path-event? %)
|
||||
(ms/mouse-up? %))))
|
||||
|
||||
drag-events (->> (streams/position-stream snap-toggled points)
|
||||
drag-events (->> (streams/position-stream)
|
||||
(rx/take-until mouse-up)
|
||||
(rx/map #(drag-handler %)))]
|
||||
|
||||
|
@ -217,20 +207,13 @@
|
|||
(assoc-in [:workspace-local :edit-path id :edit-mode] :draw))))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [zoom (get-in state [:workspace-local :zoom])
|
||||
mouse-down (->> stream (rx/filter ms/mouse-down?))
|
||||
(watch [_ _ stream]
|
||||
(let [mouse-down (->> stream (rx/filter ms/mouse-down?))
|
||||
end-path-events (->> stream (rx/filter helpers/end-path-event?))
|
||||
|
||||
content (st/get-path state :content)
|
||||
points (upg/content->points content)
|
||||
|
||||
id (st/get-path-id state)
|
||||
snap-toggled (get-in state [:workspace-local :edit-path id :snap-toggled])
|
||||
|
||||
;; Mouse move preview
|
||||
mousemove-events
|
||||
(->> (streams/position-stream snap-toggled points)
|
||||
(->> (streams/position-stream)
|
||||
(rx/take-until end-path-events)
|
||||
(rx/map #(preview-next-point %)))
|
||||
|
||||
|
@ -238,12 +221,12 @@
|
|||
mousedown-events
|
||||
(->> mouse-down
|
||||
(rx/take-until end-path-events)
|
||||
(rx/with-latest merge (streams/position-stream snap-toggled points))
|
||||
(rx/with-latest merge (streams/position-stream))
|
||||
|
||||
;; We change to the stream that emits the first event
|
||||
(rx/switch-map
|
||||
#(rx/race (make-node-events-stream stream)
|
||||
(make-drag-stream stream snap-toggled zoom points %))))]
|
||||
(make-drag-stream stream %))))]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (undo/start-path-undo))
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.data.workspace.path.edition
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.path :as upg]
|
||||
[app.common.path.commands :as upc]
|
||||
|
@ -35,8 +36,8 @@
|
|||
(let [content (st/get-path state :content)
|
||||
modifiers (helpers/move-handler-modifiers content index prefix false match-opposite? dx dy)
|
||||
[cx cy] (if (= prefix :c1) [:c1x :c1y] [:c2x :c2y])
|
||||
point (gpt/point (+ (get-in content [index :params cx]) dx)
|
||||
(+ (get-in content [index :params cy]) dy))]
|
||||
point (gpt/point (+ (dm/get-in content [index :params cx]) dx)
|
||||
(+ (dm/get-in content [index :params cy]) dy))]
|
||||
|
||||
(-> state
|
||||
(update-in [:workspace-local :edit-path id :content-modifiers] merge modifiers)
|
||||
|
@ -51,7 +52,7 @@
|
|||
id (st/get-path-id state)
|
||||
page-id (:current-page-id state)
|
||||
shape (st/get-path state)
|
||||
content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers])
|
||||
content-modifiers (dm/get-in state [:workspace-local :edit-path id :content-modifiers])
|
||||
|
||||
content (:content shape)
|
||||
new-content (upc/apply-content-modifiers content content-modifiers)
|
||||
|
@ -98,7 +99,7 @@
|
|||
(let [id (st/get-path-id state)
|
||||
content (st/get-path state :content)
|
||||
modifiers-reducer (partial modify-content-point content move-modifier)
|
||||
content-modifiers (get-in state [:workspace-local :edit-path id :content-modifiers] {})
|
||||
content-modifiers (dm/get-in state [:workspace-local :edit-path id :content-modifiers] {})
|
||||
content-modifiers (->> points
|
||||
(reduce modifiers-reducer content-modifiers))]
|
||||
|
||||
|
@ -115,9 +116,9 @@
|
|||
|
||||
modifiers-reducer (partial modify-content-point content delta)
|
||||
|
||||
points (get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
|
||||
modifiers (get-in state [:workspace-local :edit-path id :content-modifiers] {})
|
||||
modifiers (dm/get-in state [:workspace-local :edit-path id :content-modifiers] {})
|
||||
modifiers (->> points
|
||||
(reduce modifiers-reducer modifiers))]
|
||||
|
||||
|
@ -132,8 +133,8 @@
|
|||
(ptk/reify ::start-move-path-point
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [id (get-in state [:workspace-local :edition])
|
||||
selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
(let [id (dm/get-in state [:workspace-local :edition])
|
||||
selected-points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
selected? (contains? selected-points position)]
|
||||
(streams/drag-stream
|
||||
(rx/of
|
||||
|
@ -148,10 +149,9 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [stopper (->> stream (rx/filter ms/mouse-up?))
|
||||
id (get-in state [:workspace-local :edition])
|
||||
snap-toggled (get-in state [:workspace-local :edit-path id :snap-toggled])
|
||||
id (dm/get-in state [:workspace-local :edition])
|
||||
|
||||
selected-points (get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
selected-points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
|
||||
content (st/get-path state :content)
|
||||
points (upg/content->points content)]
|
||||
|
@ -159,7 +159,7 @@
|
|||
(rx/concat
|
||||
;; This stream checks the consecutive mouse positions to do the dragging
|
||||
(->> points
|
||||
(streams/move-points-stream snap-toggled start-position selected-points)
|
||||
(streams/move-points-stream start-position selected-points)
|
||||
(rx/map #(move-selected-path-point start-position %))
|
||||
(rx/take-until stopper))
|
||||
(rx/of (apply-content-modifiers)))))))
|
||||
|
@ -178,7 +178,7 @@
|
|||
(ptk/reify ::finish-move-selected
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (get-in state [:workspace-local :edition])]
|
||||
(let [id (dm/get-in state [:workspace-local :edition])]
|
||||
(-> state
|
||||
(update-in [:workspace-local :edit-path id] dissoc :current-move))))))
|
||||
|
||||
|
@ -192,8 +192,8 @@
|
|||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [id (get-in state [:workspace-local :edition])
|
||||
current-move (get-in state [:workspace-local :edit-path id :current-move])]
|
||||
(let [id (dm/get-in state [:workspace-local :edition])
|
||||
current-move (dm/get-in state [:workspace-local :edit-path id :current-move])]
|
||||
(if (nil? current-move)
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :edit-path id :moving-nodes] true)
|
||||
|
@ -202,11 +202,11 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [id (get-in state [:workspace-local :edition])
|
||||
current-move (get-in state [:workspace-local :edit-path id :current-move])]
|
||||
(let [id (dm/get-in state [:workspace-local :edition])
|
||||
current-move (dm/get-in state [:workspace-local :edit-path id :current-move])]
|
||||
;; id can be null if we just selected the tool but we didn't start drawing
|
||||
(if (and id (= same-event current-move))
|
||||
(let [points (get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
(let [points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{})
|
||||
|
||||
move-events (->> stream
|
||||
(rx/filter (ptk/type? ::move-selected))
|
||||
|
@ -238,13 +238,13 @@
|
|||
(ptk/reify ::start-move-handler
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [id (get-in state [:workspace-local :edition])
|
||||
(let [id (dm/get-in state [:workspace-local :edition])
|
||||
cx (d/prefix-keyword prefix :x)
|
||||
cy (d/prefix-keyword prefix :y)
|
||||
start-point @ms/mouse-position
|
||||
modifiers (get-in state [:workspace-local :edit-path id :content-modifiers])
|
||||
start-delta-x (get-in modifiers [index cx] 0)
|
||||
start-delta-y (get-in modifiers [index cy] 0)
|
||||
modifiers (dm/get-in state [:workspace-local :edit-path id :content-modifiers])
|
||||
start-delta-x (dm/get-in modifiers [index cx] 0)
|
||||
start-delta-y (dm/get-in modifiers [index cy] 0)
|
||||
|
||||
content (st/get-path state :content)
|
||||
points (upg/content->points content)
|
||||
|
@ -253,14 +253,12 @@
|
|||
handler (-> content (get index) (upc/get-handler prefix))
|
||||
|
||||
[op-idx op-prefix] (upc/opposite-index content index prefix)
|
||||
opposite (upc/handler->point content op-idx op-prefix)
|
||||
|
||||
snap-toggled (get-in state [:workspace-local :edit-path id :snap-toggled])]
|
||||
opposite (upc/handler->point content op-idx op-prefix)]
|
||||
|
||||
(streams/drag-stream
|
||||
(rx/concat
|
||||
(rx/of (dch/update-shapes [id] upsp/convert-to-path))
|
||||
(->> (streams/move-handler-stream snap-toggled start-point point handler opposite points)
|
||||
(->> (streams/move-handler-stream start-point point handler opposite points)
|
||||
(rx/take-until (->> stream (rx/filter #(or (ms/mouse-up? %)
|
||||
(streams/finish-edition? %)))))
|
||||
(rx/map
|
||||
|
@ -283,7 +281,7 @@
|
|||
(ptk/reify ::start-path-edit
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [edit-path (get-in state [:workspace-local :edit-path id])
|
||||
(let [edit-path (dm/get-in state [:workspace-local :edit-path id])
|
||||
content (st/get-path state :content)
|
||||
state (st/set-content state (ups/close-subpaths content))]
|
||||
(cond-> state
|
||||
|
@ -297,7 +295,7 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [mode (get-in state [:workspace-local :edit-path id :edit-mode])
|
||||
(let [mode (dm/get-in state [:workspace-local :edit-path id :edit-mode])
|
||||
stopper (->> stream
|
||||
(rx/filter #(or
|
||||
(= (ptk/type %) ::dwe/clear-edition-mode)
|
||||
|
|
|
@ -6,10 +6,11 @@
|
|||
|
||||
(ns app.main.data.workspace.path.streams
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.path :as upg]
|
||||
[app.main.constants :refer [zoom-half-pixel-precision]]
|
||||
[app.main.data.workspace.path.state :as state]
|
||||
[app.main.data.workspace.path.state :as pst]
|
||||
[app.main.snap :as snap]
|
||||
[app.main.store :as st]
|
||||
[app.main.streams :as ms]
|
||||
|
@ -71,15 +72,23 @@
|
|||
(->> position-stream
|
||||
(rx/merge-map (fn [] to-stream)))))))
|
||||
|
||||
(defn snap-toggled-stream
|
||||
[]
|
||||
(let [get-snap (fn [state]
|
||||
(let [id (pst/get-path-id state)]
|
||||
(dm/get-in state [:workspace-local :edit-path id :snap-toggled])))]
|
||||
(-> (l/derived get-snap st/state)
|
||||
(rx/from-atom {:emit-current-value? true}))))
|
||||
|
||||
(defn move-points-stream
|
||||
[snap-toggled start-point selected-points points]
|
||||
[start-point selected-points points]
|
||||
|
||||
(let [zoom (get-in @st/state [:workspace-local :zoom] 1)
|
||||
ranges (snap/create-ranges points selected-points)
|
||||
d-pos (/ snap/snap-path-accuracy zoom)
|
||||
|
||||
check-path-snap
|
||||
(fn [position]
|
||||
(fn [[position snap-toggled]]
|
||||
(if snap-toggled
|
||||
(let [delta (gpt/subtract position start-point)
|
||||
moved-points (->> selected-points (mapv #(gpt/add % delta)))
|
||||
|
@ -88,6 +97,7 @@
|
|||
position))]
|
||||
(->> ms/mouse-position
|
||||
(rx/map to-pixel-snap)
|
||||
(rx/with-latest-from (snap-toggled-stream))
|
||||
(rx/map check-path-snap))))
|
||||
|
||||
(defn get-angle [node handler opposite]
|
||||
|
@ -99,7 +109,7 @@
|
|||
[rot-angle rot-sign])))
|
||||
|
||||
(defn move-handler-stream
|
||||
[snap-toggled start-point node handler opposite points]
|
||||
[start-point node handler opposite points]
|
||||
|
||||
(let [zoom (get-in @st/state [:workspace-local :zoom] 1)
|
||||
ranges (snap/create-ranges points)
|
||||
|
@ -108,7 +118,7 @@
|
|||
[initial-angle] (get-angle node handler opposite)
|
||||
|
||||
check-path-snap
|
||||
(fn [position]
|
||||
(fn [[position snap-toggled]]
|
||||
(if snap-toggled
|
||||
(let [delta (gpt/subtract position start-point)
|
||||
handler (gpt/add handler delta)
|
||||
|
@ -134,13 +144,14 @@
|
|||
(rx/map to-pixel-snap)
|
||||
(rx/with-latest merge (->> ms/mouse-position-shift (rx/map #(hash-map :shift? %))))
|
||||
(rx/with-latest merge (->> ms/mouse-position-alt (rx/map #(hash-map :alt? %))))
|
||||
(rx/with-latest-from (snap-toggled-stream))
|
||||
(rx/map check-path-snap))))
|
||||
|
||||
(defn position-stream
|
||||
[snap-toggled _points]
|
||||
[]
|
||||
(let [zoom (get-in @st/state [:workspace-local :zoom] 1)
|
||||
d-pos (/ snap/snap-path-accuracy zoom)
|
||||
get-content #(state/get-path % :content)
|
||||
get-content #(pst/get-path % :content)
|
||||
|
||||
content-stream
|
||||
(-> (l/derived get-content st/state)
|
||||
|
@ -154,7 +165,8 @@
|
|||
(->> ms/mouse-position
|
||||
(rx/map to-pixel-snap)
|
||||
(rx/with-latest vector ranges-stream)
|
||||
(rx/map (fn [[position ranges]]
|
||||
(rx/with-latest-from (snap-toggled-stream))
|
||||
(rx/map (fn [[[position ranges] snap-toggled]]
|
||||
(if snap-toggled
|
||||
(let [snap (snap/get-snap-delta [position] ranges d-pos)]
|
||||
(gpt/add position snap))
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
|
||||
(ns app.main.ui.workspace.shapes.path.common
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.main.data.workspace.path.state :as pst]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
|
@ -17,10 +20,11 @@
|
|||
(def gray-color "var(--color-gray-20)")
|
||||
|
||||
(def current-edit-path-ref
|
||||
(let [selfn (fn [local]
|
||||
(let [id (:edition local)]
|
||||
(get-in local [:edit-path id])))]
|
||||
(l/derived selfn refs/workspace-local)))
|
||||
(l/derived
|
||||
(fn [state]
|
||||
(let [id (pst/get-path-id state)]
|
||||
(dm/get-in state [:workspace-local :edit-path id])))
|
||||
st/state))
|
||||
|
||||
(defn make-edit-path-ref [id]
|
||||
(mf/use-memo
|
||||
|
|
|
@ -327,14 +327,15 @@
|
|||
|
||||
[:g.path-node {:key (dm/str index "-" (:x position) "-" (:y position))}
|
||||
[:g.point-handlers {:pointer-events (when (= edit-mode :draw) "none")}
|
||||
(for [[index prefix] pos-handlers]
|
||||
(let [handler-position (upc/handler->point content index prefix)
|
||||
handler-hover? (contains? hover-handlers [index prefix])
|
||||
(for [[hindex prefix] pos-handlers]
|
||||
(let [handler-position (upc/handler->point content hindex prefix)
|
||||
handler-hover? (contains? hover-handlers [hindex prefix])
|
||||
moving-handler? (= handler-position moving-handler)
|
||||
matching-handler? (matching-handler? content position pos-handlers)]
|
||||
[:& path-handler {:point position
|
||||
[:& path-handler {:key (dm/str (dm/str index "-" (:x position) "-" (:y position)) "-" hindex "-" (d/name prefix))
|
||||
:point position
|
||||
:handler handler-position
|
||||
:index index
|
||||
:index hindex
|
||||
:prefix prefix
|
||||
:zoom zoom
|
||||
:hover? handler-hover?
|
||||
|
|
|
@ -50,12 +50,13 @@
|
|||
(mf/defc viewport-actions
|
||||
{::mf/wrap [mf/memo]}
|
||||
[]
|
||||
(let [edition (mf/deref refs/selected-edition)
|
||||
selected (mf/deref refs/selected-objects)
|
||||
shape (-> selected first)]
|
||||
(when (and (= (count selected) 1)
|
||||
(= (:id shape) edition)
|
||||
(not= :text (:type shape)))
|
||||
(let [edition (mf/deref refs/selected-edition)
|
||||
selected (mf/deref refs/selected-objects)
|
||||
drawing (mf/deref refs/workspace-drawing)
|
||||
drawing-obj (:object drawing)
|
||||
shape (or drawing-obj (-> selected first))]
|
||||
(when (or (and (= (count selected) 1) (= (:id shape) edition) (not= :text (:type shape)))
|
||||
(and (some? drawing-obj) (= :path (:type drawing-obj))))
|
||||
[:div.viewport-actions
|
||||
[:& path-actions {:shape shape}]])))
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue