mirror of
https://github.com/penpot/penpot.git
synced 2025-07-21 18:28:10 +02:00
✨ Path edition mode
This commit is contained in:
parent
275f6e3dc2
commit
8db7078ce8
20 changed files with 436 additions and 108 deletions
|
@ -32,6 +32,7 @@
|
|||
[app.main.data.workspace.texts :as dwtxt]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[app.main.data.workspace.drawing :as dwd]
|
||||
[app.main.data.workspace.drawing.path :as dwdp]
|
||||
[app.main.repo :as rp]
|
||||
[app.main.store :as st]
|
||||
[app.main.streams :as ms]
|
||||
|
@ -1629,6 +1630,8 @@
|
|||
(def add-shape dwc/add-shape)
|
||||
(def start-edition-mode dwc/start-edition-mode)
|
||||
|
||||
(defn start-path-edit [id] (dwdp/start-path-edit id))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Shortcuts
|
||||
|
|
|
@ -99,6 +99,6 @@
|
|||
(box/handle-drawing-box))))))
|
||||
|
||||
;; Export
|
||||
(def close-drawing-path path/close-drawing-path)
|
||||
#_(def close-drawing-path path/close-drawing-path)
|
||||
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
[app.util.data :as d]
|
||||
[app.util.geom.path :as ugp]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.data.workspace.drawing.common :as common]))
|
||||
[app.main.data.workspace.common :as dwc]
|
||||
[app.main.data.workspace.drawing.common :as common]
|
||||
[app.common.geom.shapes.path :as gsp]))
|
||||
|
||||
;;;;
|
||||
|
||||
|
@ -149,14 +151,14 @@
|
|||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :initialized?] true)
|
||||
(assoc-in [:workspace-drawing :object :last-point] nil)))))
|
||||
(assoc-in [:workspace-local :edit-path :last-point] nil)))))
|
||||
|
||||
(defn finish-path []
|
||||
(ptk/reify ::finish-path
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:workspace-drawing :object :last-point] nil)
|
||||
(update :workspace-local dissoc :edit-path)
|
||||
(update-in [:workspace-drawing :object] calculate-selrect)))))
|
||||
|
||||
(defn preview-next-point [{:keys [x y]}]
|
||||
|
@ -164,9 +166,9 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [position (gpt/point x y)
|
||||
{:keys [last-point prev-handler] :as shape} (get-in state [:workspace-drawing :object])
|
||||
{:keys [last-point prev-handler] :as shape} (get-in state [:workspace-local :edit-path])
|
||||
command (next-node shape position last-point prev-handler)]
|
||||
(assoc-in state [:workspace-drawing :object :preview] command)))))
|
||||
(assoc-in state [:workspace-local :edit-path :preview] command)))))
|
||||
|
||||
(defn add-node [{:keys [x y]}]
|
||||
(ptk/reify ::add-node
|
||||
|
@ -174,14 +176,11 @@
|
|||
(update [_ state]
|
||||
|
||||
(let [position (gpt/point x y)
|
||||
{:keys [last-point prev-handler]} (get-in state [:workspace-drawing :object])]
|
||||
(update-in
|
||||
state
|
||||
[:workspace-drawing :object]
|
||||
#(-> %
|
||||
(append-node position last-point prev-handler)
|
||||
(assoc :last-point position)
|
||||
(dissoc :prev-handler)))))))
|
||||
{:keys [last-point prev-handler]} (get-in state [:workspace-local :edit-path])]
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :edit-path :last-point] position)
|
||||
(update-in [:workspace-local :edit-path] dissoc :prev-handler)
|
||||
(update-in [:workspace-drawing :object] append-node position last-point prev-handler))))))
|
||||
|
||||
(defn drag-handler [{:keys [x y]}]
|
||||
(ptk/reify ::drag-handler
|
||||
|
@ -193,16 +192,16 @@
|
|||
index (dec (count (:content shape)))]
|
||||
(-> state
|
||||
(update-in [:workspace-drawing :object] move-handler index :next true position)
|
||||
(assoc-in [:workspace-drawing :object :drag-handler] position))))))
|
||||
(assoc-in [:workspace-local :edit-path :drag-handler] position))))))
|
||||
|
||||
(defn finish-drag []
|
||||
(ptk/reify ::finish-drag
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [handler (get-in state [:workspace-drawing :object :drag-handler])]
|
||||
(let [handler (get-in state [:workspace-local :edit-path :drag-handler])]
|
||||
(-> state
|
||||
(update-in [:workspace-drawing :object] dissoc :drag-handler)
|
||||
(assoc-in [:workspace-drawing :object :prev-handler] handler))))))
|
||||
(update-in [:workspace-local :edit-path] dissoc :drag-handler)
|
||||
(assoc-in [:workspace-local :edit-path :prev-handler] handler))))))
|
||||
|
||||
(defn make-click-stream
|
||||
[stream down-event]
|
||||
|
@ -238,7 +237,6 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
|
||||
;; clicks stream<[MouseEvent, Position]>
|
||||
(let [mouse-down (->> stream (rx/filter ms/mouse-down?))
|
||||
finish-events (->> stream (rx/filter finish-event?))
|
||||
|
||||
|
@ -266,10 +264,7 @@
|
|||
(rx/merge mousemove-events
|
||||
mousedown-events)
|
||||
(rx/of (finish-path))
|
||||
(rx/of common/handle-finish-drawing)))
|
||||
|
||||
|
||||
)))
|
||||
(rx/of common/handle-finish-drawing))))))
|
||||
|
||||
#_(def handle-drawing-path
|
||||
(ptk/reify ::handle-drawing-path
|
||||
|
@ -331,7 +326,7 @@
|
|||
(rx/of finish-drawing-path
|
||||
common/handle-finish-drawing)))))))
|
||||
|
||||
(defn close-drawing-path []
|
||||
#_(defn close-drawing-path []
|
||||
(ptk/reify ::close-drawing-path
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
@ -340,3 +335,121 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(rx/of ::end-path-drawing))))
|
||||
|
||||
|
||||
(defn stop-path-edit []
|
||||
(ptk/reify ::stop-path-edit
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(update state :workspace-local dissoc :edit-path))))
|
||||
|
||||
(defn start-path-edit
|
||||
[id]
|
||||
(ptk/reify ::start-path-edit
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(assoc-in state [:workspace-local :edit-path] {}))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(->> stream
|
||||
(rx/filter #(= % :interrupt))
|
||||
(rx/take 1)
|
||||
(rx/map #(stop-path-edit))))))
|
||||
|
||||
(defn modify-point [index dx dy]
|
||||
(ptk/reify ::modify-point
|
||||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
||||
(-> state
|
||||
(update-in [:workspace-local :edit-path :content-modifiers (inc index)] assoc
|
||||
:c1x dx :c1y dy)
|
||||
(update-in [:workspace-local :edit-path :content-modifiers index] assoc
|
||||
:x dx :y dy :c2x dx :c2y dy)
|
||||
))))
|
||||
|
||||
(defn modify-handler [index type dx dy]
|
||||
(ptk/reify ::modify-point
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [s1 (if (= type :prev) -1 1)
|
||||
s2 (if (= type :prev) 1 -1)]
|
||||
(-> state
|
||||
(update-in [:workspace-local :edit-path :content-modifiers (inc index)] assoc
|
||||
:c1x (* s1 dx) :c1y (* s1 dy))
|
||||
(update-in [:workspace-local :edit-path :content-modifiers index] assoc
|
||||
:c2x (* s2 dx) :c2y (* s2 dy) ))
|
||||
))))
|
||||
|
||||
(defn apply-content-modifiers []
|
||||
(ptk/reify ::apply-content-modifiers
|
||||
;;ptk/UpdateEvent
|
||||
;;(update [_ state]
|
||||
;; (update-in state [:workspace-local :edit-path] dissoc :content-modifiers))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [id (get-in state [:workspace-local :edition])
|
||||
page-id (:current-page-id state)
|
||||
old-content (get-in state [:workspace-data :pages-index page-id :objects id :content])
|
||||
old-selrect (get-in state [:workspace-data :pages-index page-id :objects id :selrect])
|
||||
content-modifiers (get-in state [:workspace-local :edit-path :content-modifiers])
|
||||
new-content (gsp/apply-content-modifiers old-content content-modifiers)
|
||||
new-selrect (gsh/content->selrect new-content)
|
||||
rch [{:type :mod-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:operations [{:type :set :attr :content :val new-content}
|
||||
{:type :set :attr :selrect :val new-selrect}]}]
|
||||
|
||||
uch [{:type :mod-obj
|
||||
:id id
|
||||
:page-id page-id
|
||||
:operations [{:type :set :attr :content :val old-content}
|
||||
{:type :set :attr :selrect :val old-selrect}]}]]
|
||||
|
||||
(rx/of (dwc/commit-changes rch uch {:commit-local? true})
|
||||
(fn [state] (update-in state [:workspace-local :edit-path] dissoc :content-modifiers)))))))
|
||||
|
||||
(defn start-move-path-point
|
||||
[index]
|
||||
(ptk/reify ::start-move-path-point
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [start-point @ms/mouse-position
|
||||
start-delta-x (get-in state [:workspace-local :edit-path :content-modifiers index :x] 0)
|
||||
start-delta-y (get-in state [:workspace-local :edit-path :content-modifiers index :y] 0)]
|
||||
(rx/concat
|
||||
(->> ms/mouse-position
|
||||
(rx/take-until (->> stream (rx/filter ms/mouse-up?)))
|
||||
(rx/map #(modify-point
|
||||
index
|
||||
(+ start-delta-x (- (:x %) (:x start-point)))
|
||||
(+ start-delta-y (- (:y %) (:y start-point))))))
|
||||
(rx/concat (rx/of (apply-content-modifiers)))
|
||||
)))))
|
||||
|
||||
(defn start-move-handler
|
||||
[index type]
|
||||
(ptk/reify ::start-move-handler
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [[cx cy] (if (= :prev type) [:c2x :c2y] [:c1x :c1y])
|
||||
cidx (if (= :prev type) index (inc index))
|
||||
|
||||
start-point @ms/mouse-position
|
||||
start-delta-x (get-in state [:workspace-local :edit-path :content-modifiers cidx cx] 0)
|
||||
start-delta-y (get-in state [:workspace-local :edit-path :content-modifiers cidx cy] 0)]
|
||||
|
||||
(rx/concat
|
||||
(->> ms/mouse-position
|
||||
(rx/take-until (->> stream (rx/filter ms/mouse-up?)))
|
||||
(rx/map #(modify-handler
|
||||
index
|
||||
type
|
||||
(+ start-delta-x (- (:x %) (:x start-point)))
|
||||
(+ start-delta-y (- (:y %) (:y start-point)))))
|
||||
)
|
||||
(rx/concat (rx/of (apply-content-modifiers))))))))
|
||||
|
|
|
@ -128,6 +128,14 @@
|
|||
(def checkbox-checked (icon-xref :checkbox-checked))
|
||||
(def checkbox-unchecked (icon-xref :checkbox-unchecked))
|
||||
(def code (icon-xref :code))
|
||||
(def nodes-add (icon-xref :nodes-add))
|
||||
(def nodes-corner (icon-xref :nodes-corner))
|
||||
(def nodes-curve (icon-xref :nodes-curve))
|
||||
(def nodes-join (icon-xref :nodes-join))
|
||||
(def nodes-merge (icon-xref :nodes-merge))
|
||||
(def nodes-remove (icon-xref :nodes-remove))
|
||||
(def nodes-separate (icon-xref :nodes-separate))
|
||||
(def nodes-snap (icon-xref :nodes-snap))
|
||||
|
||||
(def loader-pencil
|
||||
(mf/html
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
[app.main.ui.workspace.rules :refer [horizontal-rule vertical-rule]]
|
||||
[app.main.ui.workspace.scroll :as scroll]
|
||||
[app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]]
|
||||
[app.main.ui.workspace.viewport :refer [viewport coordinates]]
|
||||
[app.main.ui.workspace.viewport :refer [viewport viewport-actions coordinates]]
|
||||
[app.util.dom :as dom]
|
||||
[beicon.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
|
@ -65,6 +65,7 @@
|
|||
(when (contains? layout :rules)
|
||||
[:& workspace-rules {:local local}])
|
||||
|
||||
[:& viewport-actions]
|
||||
[:& viewport {:file file
|
||||
:local local
|
||||
:layout layout}]]]
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
[app.common.geom.matrix :as gmt]
|
||||
[app.util.debug :refer [debug?]]
|
||||
[app.main.ui.workspace.shapes.outline :refer [outline]]
|
||||
[app.main.ui.measurements :as msr]))
|
||||
[app.main.ui.measurements :as msr]
|
||||
[app.main.ui.workspace.shapes.path :refer [path-editor]]))
|
||||
|
||||
(def rotation-handler-size 25)
|
||||
(def resize-point-radius 4)
|
||||
|
@ -366,8 +367,13 @@
|
|||
[:& text-edition-selection-handlers {:shape shape
|
||||
:zoom zoom
|
||||
:color color}]
|
||||
(and (or (= type :path)
|
||||
(= type :curve))
|
||||
|
||||
(= (= type :path)
|
||||
(= edition (:id shape)))
|
||||
[:& path-editor {:zoom zoom
|
||||
:shape shape}]
|
||||
|
||||
(and (= type :curve)
|
||||
(= edition (:id shape)))
|
||||
[:& path-edition-selection-handlers {:shape shape
|
||||
:zoom zoom
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
(defn- on-mouse-down
|
||||
[event {:keys [id type] :as shape}]
|
||||
(let [selected @refs/selected-shapes
|
||||
edition @refs/selected-edition
|
||||
selected? (contains? selected id)
|
||||
drawing? @refs/selected-drawing-tool
|
||||
button (.-which (.-nativeEvent event))]
|
||||
|
@ -35,9 +36,8 @@
|
|||
nil
|
||||
|
||||
(= type :frame)
|
||||
(when selected?
|
||||
(dom/stop-propagation event)
|
||||
(st/emit! (dw/start-move-selected)))
|
||||
(do (dom/stop-propagation event)
|
||||
(st/emit! (dw/start-move-selected)))
|
||||
|
||||
:else
|
||||
(do
|
||||
|
@ -50,7 +50,8 @@
|
|||
(st/emit! (dw/deselect-all)))
|
||||
(st/emit! (dw/select-shape id))))
|
||||
|
||||
(st/emit! (dw/start-move-selected)))))))
|
||||
(when (not= edition id)
|
||||
(st/emit! (dw/start-move-selected))))))))
|
||||
|
||||
(defn on-context-menu
|
||||
[event shape]
|
||||
|
|
|
@ -10,22 +10,40 @@
|
|||
(ns app.main.ui.workspace.shapes.path
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[app.common.data :as d]
|
||||
[okulary.core :as l]
|
||||
[app.util.data :as d]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.timers :as ts]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.streams :as ms]
|
||||
[app.main.constants :as c]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.data.workspace.drawing :as dr]
|
||||
[app.main.data.workspace.drawing.path :as drp]
|
||||
[app.main.ui.keyboard :as kbd]
|
||||
[app.main.ui.shapes.path :as path]
|
||||
[app.main.ui.shapes.filters :as filters]
|
||||
[app.main.ui.shapes.shape :refer [shape-container]]
|
||||
[app.main.ui.workspace.shapes.common :as common]
|
||||
[app.util.geom.path :as ugp]
|
||||
[app.common.geom.shapes.path :as gsp]))
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.path :as gsp]
|
||||
[app.main.ui.cursors :as cur]
|
||||
[app.main.ui.icons :as i]))
|
||||
|
||||
(def primary-color "#1FDEA7")
|
||||
(def secondary-color "#DB00FF")
|
||||
(def black-color "#000000")
|
||||
(def white-color "#FFFFFF")
|
||||
(def gray-color "#B1B2B5")
|
||||
|
||||
(def edit-path-ref
|
||||
(l/derived :edit-path refs/workspace-local))
|
||||
|
||||
(def content-modifiers-ref
|
||||
(l/derived :content-modifiers edit-path-ref))
|
||||
|
||||
(mf/defc path-wrapper
|
||||
{::mf/wrap-props false}
|
||||
|
@ -43,12 +61,15 @@
|
|||
on-double-click (mf/use-callback
|
||||
(mf/deps shape)
|
||||
(fn [event]
|
||||
(prn "?? PATH")
|
||||
(when (and (not (::dr/initialized? shape)) (hover? (:id shape)))
|
||||
(when (not (::dr/initialized? shape))
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (dw/start-edition-mode (:id shape)))))))]
|
||||
(st/emit! (dw/start-edition-mode (:id shape))
|
||||
(dw/start-path-edit (:id shape)))))))
|
||||
|
||||
content-modifiers (mf/deref content-modifiers-ref)
|
||||
shape (update shape :content gsp/apply-content-modifiers content-modifiers)]
|
||||
|
||||
[:> shape-container {:shape shape
|
||||
:on-double-click on-double-click
|
||||
|
@ -57,75 +78,142 @@
|
|||
[:& path/path-shape {:shape shape
|
||||
:background? true}]]))
|
||||
|
||||
(mf/defc path-actions [{:keys [shape]}]
|
||||
[:div.path-actions
|
||||
[:div.viewport-actions-group
|
||||
[:div.viewport-actions-entry i/nodes-add]
|
||||
[:div.viewport-actions-entry i/nodes-remove]]
|
||||
|
||||
(mf/defc path-handler [{:keys [point handler zoom selected]}]
|
||||
[:div.viewport-actions-group
|
||||
[:div.viewport-actions-entry i/nodes-merge]
|
||||
[:div.viewport-actions-entry i/nodes-join]
|
||||
[:div.viewport-actions-entry i/nodes-separate]]
|
||||
|
||||
[:div.viewport-actions-group
|
||||
[:div.viewport-actions-entry i/nodes-corner]
|
||||
[:div.viewport-actions-entry i/nodes-curve]]
|
||||
|
||||
[:div.viewport-actions-group
|
||||
[:div.viewport-actions-entry i/nodes-snap]]])
|
||||
|
||||
|
||||
(mf/defc path-preview [{:keys [zoom command from]}]
|
||||
(when (not= :move-to (:command command))
|
||||
[:path {:style {:fill "transparent"
|
||||
:stroke secondary-color
|
||||
:stroke-width (/ 1 zoom)}
|
||||
:d (ugp/content->path [{:command :move-to
|
||||
:params {:x (:x from)
|
||||
:y (:y from)}}
|
||||
command])}]))
|
||||
|
||||
(mf/defc path-point [{:keys [index position stroke-color fill-color zoom]}]
|
||||
(let [{:keys [x y]} position
|
||||
on-click (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event))
|
||||
on-mouse-down (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (drp/start-move-path-point index)))]
|
||||
[:circle
|
||||
{:cx x
|
||||
:cy y
|
||||
:r (/ 3 zoom)
|
||||
:on-click on-click
|
||||
:on-mouse-down on-mouse-down
|
||||
:style {:cursor cur/resize-alt
|
||||
:stroke-width (/ 1 zoom)
|
||||
:stroke (or stroke-color black-color)
|
||||
:fill (or fill-color white-color)}}]))
|
||||
|
||||
(mf/defc path-handler [{:keys [index point handler zoom selected type]}]
|
||||
(when (and point handler)
|
||||
(let [{:keys [x y]} handler]
|
||||
[:g.handler
|
||||
(let [{:keys [x y]} handler
|
||||
on-click (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event))
|
||||
on-mouse-down (fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(dom/prevent-default event)
|
||||
(st/emit! (drp/start-move-handler index type)))]
|
||||
[:g.handler {:class (name type)}
|
||||
[:line
|
||||
{:x1 (:x point)
|
||||
:y1 (:y point)
|
||||
:x2 x
|
||||
:y2 y
|
||||
:style {:stroke "#B1B2B5"
|
||||
:style {:stroke gray-color
|
||||
:stroke-width (/ 1 zoom)}}]
|
||||
[:rect
|
||||
{:x (- x (/ 3 zoom))
|
||||
:y (- y (/ 3 zoom))
|
||||
:width (/ 6 zoom)
|
||||
:height (/ 6 zoom)
|
||||
:style {:stroke-width (/ 1 zoom)
|
||||
:stroke (if selected "#000000" "#1FDEA7")
|
||||
:fill (if selected "#1FDEA7" "#FFFFFF")}}]])))
|
||||
:on-click on-click
|
||||
:on-mouse-down on-mouse-down
|
||||
:style {:cursor cur/resize-alt
|
||||
:stroke-width (/ 1 zoom)
|
||||
:stroke (if selected black-color primary-color)
|
||||
:fill (if selected primary-color white-color)}}]])))
|
||||
|
||||
(mf/defc path-editor
|
||||
[{:keys [shape zoom]}]
|
||||
|
||||
(let [points (gsp/content->points (:content shape))
|
||||
drag-handler (:drag-handler shape)
|
||||
prev-handler (:prev-handler shape)
|
||||
last-command (last (:content shape))
|
||||
selected false
|
||||
(let [{:keys [content]} shape
|
||||
{:keys [drag-handler prev-handler preview content-modifiers]} (mf/deref edit-path-ref)
|
||||
content (gsp/apply-content-modifiers content content-modifiers)
|
||||
points (gsp/content->points content)
|
||||
last-command (last content)
|
||||
last-p (last points)
|
||||
handlers (ugp/extract-handlers (:content shape))
|
||||
handlers (if (and prev-handler (not drag-handler))
|
||||
(conj handlers {:point last-p :prev prev-handler})
|
||||
handlers)
|
||||
]
|
||||
selected false]
|
||||
|
||||
[:g.path-editor
|
||||
(when (and (:preview shape) (not (:drag-handler shape)))
|
||||
[:*
|
||||
[:path {:style {:fill "transparent"
|
||||
:stroke "#DB00FF"
|
||||
:stroke-width (/ 1 zoom)}
|
||||
:d (ugp/content->path [{:command :move-to
|
||||
:params {:x (:x last-p)
|
||||
:y (:y last-p)}}
|
||||
(:preview shape)])}]
|
||||
[:circle
|
||||
{:cx (-> shape :preview :params :x)
|
||||
:cy (-> shape :preview :params :y)
|
||||
:r (/ 3 zoom)
|
||||
:style {:stroke-width (/ 1 zoom)
|
||||
:stroke "#DB00FF"
|
||||
:fill "#FFFFFF"}}]])
|
||||
(when (and preview (not drag-handler))
|
||||
[:g.preview {:style {:pointer-events "none"}}
|
||||
[:& path-preview {:command preview
|
||||
:from last-p
|
||||
:zoom zoom}]
|
||||
[:& path-point {:position (:params preview)
|
||||
:fill-color secondary-color
|
||||
:zoom zoom}]])
|
||||
|
||||
(for [{:keys [point prev next]} handlers]
|
||||
[:*
|
||||
[:& path-handler {:point point
|
||||
:handler prev
|
||||
:zoom zoom
|
||||
:type :prev
|
||||
:selected false}]
|
||||
[:& path-handler {:point point
|
||||
:handler next
|
||||
:zoom zoom
|
||||
:type :next
|
||||
:selected false}]])
|
||||
(for [[index [cmd next]] (d/enumerate (d/with-next content))]
|
||||
(let [point (gpt/point (:params cmd))]
|
||||
[:g.path-node
|
||||
(when (= :curve-to (:command cmd))
|
||||
[:& path-handler {:point point
|
||||
:handler (gpt/point (-> cmd :params :c2x) (-> cmd :params :c2y))
|
||||
:zoom zoom
|
||||
:type :prev
|
||||
:index index
|
||||
:selected false}])
|
||||
|
||||
(when (= :curve-to (:command next))
|
||||
[:& path-handler {:point point
|
||||
:handler (gpt/point (-> next :params :c1x) (-> next :params :c1y))
|
||||
:zoom zoom
|
||||
:type :next
|
||||
:index index
|
||||
:selected false}])
|
||||
|
||||
(when (and (= index (dec (count content)))
|
||||
prev-handler (not drag-handler))
|
||||
[:& path-handler {:point point
|
||||
:handler prev-handler
|
||||
:zoom zoom
|
||||
:type :prev
|
||||
:index index
|
||||
:selected false}])
|
||||
|
||||
[:& path-point {:position point
|
||||
:stroke-color (when-not selected primary-color)
|
||||
:fill-color (when selected primary-color)
|
||||
:index index
|
||||
:zoom zoom}]]))
|
||||
|
||||
(when drag-handler
|
||||
[:*
|
||||
[:g.drag-handler
|
||||
(when (not= :move-to (:command last-command))
|
||||
[:& path-handler {:point last-p
|
||||
:handler (ugp/opposite-handler last-p drag-handler)
|
||||
|
@ -136,14 +224,4 @@
|
|||
:handler drag-handler
|
||||
:zoom zoom
|
||||
:type :drag
|
||||
:selected false}]])
|
||||
|
||||
(for [{:keys [x y] :as point} points]
|
||||
[:circle
|
||||
{:cx x
|
||||
:cy y
|
||||
:r (/ 3 zoom)
|
||||
:style {:stroke-width (/ 1 zoom)
|
||||
:stroke (if selected "#000000" "#1FDEA7")
|
||||
:fill (if selected "#1FDEA7" "#FFFFFF")}
|
||||
}])]))
|
||||
:selected false}]])]))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
|
@ -52,7 +52,8 @@
|
|||
[goog.events :as events]
|
||||
[potok.core :as ptk]
|
||||
[promesa.core :as p]
|
||||
[rumext.alpha :as mf])
|
||||
[rumext.alpha :as mf]
|
||||
[app.main.ui.workspace.shapes.path :refer [path-actions]])
|
||||
(:import goog.events.EventType))
|
||||
|
||||
;; --- Coordinates Widget
|
||||
|
@ -222,7 +223,6 @@
|
|||
drawing-obj (:object drawing)
|
||||
zoom (or zoom 1)
|
||||
|
||||
|
||||
on-mouse-down
|
||||
(mf/use-callback
|
||||
(mf/deps drawing-tool edition)
|
||||
|
@ -234,15 +234,13 @@
|
|||
alt? (kbd/alt? event)]
|
||||
(st/emit! (ms/->MouseEvent :down ctrl? shift? alt?))
|
||||
(cond
|
||||
(and (= 1 (.-which event)))
|
||||
|
||||
(and (= 1 (.-which event)) (not edition))
|
||||
(if drawing-tool
|
||||
(when (not (#{:comments :path} drawing-tool))
|
||||
(st/emit! (dd/start-drawing drawing-tool)))
|
||||
(st/emit! dw/handle-selection))
|
||||
|
||||
(and (not edition)
|
||||
(= 2 (.-which event)))
|
||||
(and (= 2 (.-which event)))
|
||||
(handle-viewport-positioning viewport-ref)))))
|
||||
|
||||
on-context-menu
|
||||
|
@ -294,12 +292,16 @@
|
|||
|
||||
on-double-click
|
||||
(mf/use-callback
|
||||
(mf/deps edition)
|
||||
(fn [event]
|
||||
(dom/stop-propagation event)
|
||||
(let [ctrl? (kbd/ctrl? event)
|
||||
shift? (kbd/shift? event)
|
||||
alt? (kbd/alt? event)]
|
||||
(st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt?)))))
|
||||
(st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt?))
|
||||
|
||||
(if edition
|
||||
(st/emit! dw/clear-edition-mode)))))
|
||||
|
||||
on-key-down
|
||||
(mf/use-callback
|
||||
|
@ -610,3 +612,13 @@
|
|||
(when (= options-mode :prototype)
|
||||
[:& interactions {:selected selected}])]]))
|
||||
|
||||
|
||||
(mf/defc viewport-actions []
|
||||
(let [edition (mf/deref refs/selected-edition)
|
||||
selected (mf/deref refs/selected-objects)
|
||||
shape (-> selected first)]
|
||||
(when (and (= (count selected) 1)
|
||||
(= (:id shape) edition)
|
||||
(= :path (:type shape)))
|
||||
[:div.viewport-actions
|
||||
[:& path-actions {:shape shape}]])))
|
||||
|
|
|
@ -213,9 +213,3 @@
|
|||
opposite (gpt/add point (gpt/negate phv))]
|
||||
opposite))
|
||||
|
||||
(defn extract-handlers [content]
|
||||
(let [extract (fn [{param1 :params :as cmd1} {param2 :params :as cmd2}]
|
||||
{:point (gpt/point (:x param1) (:y param1))
|
||||
:prev (when (:c2x param1) (gpt/point (:c2x param1) (:c2y param1)))
|
||||
:next (when (:c1x param2) (gpt/point (:c1x param2) (:c1y param2)))})]
|
||||
(map extract content (d/concat [] (rest content) [nil]))))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue