mirror of
https://github.com/penpot/penpot.git
synced 2025-05-12 16:37:15 +02:00
✨ Select path nodes in area
This commit is contained in:
parent
bb719d6211
commit
a06a8c648e
8 changed files with 112 additions and 26 deletions
|
@ -253,3 +253,4 @@
|
||||||
;; Intersection
|
;; Intersection
|
||||||
(d/export gin/overlaps?)
|
(d/export gin/overlaps?)
|
||||||
(d/export gin/has-point?)
|
(d/export gin/has-point?)
|
||||||
|
(d/export gin/has-point-rect?)
|
||||||
|
|
|
@ -285,6 +285,11 @@
|
||||||
(or (not path?) (overlaps-path? shape rect))
|
(or (not path?) (overlaps-path? shape rect))
|
||||||
(or (not circle?) (overlaps-ellipse? shape rect))))))
|
(or (not circle?) (overlaps-ellipse? shape rect))))))
|
||||||
|
|
||||||
|
(defn has-point-rect?
|
||||||
|
[rect point]
|
||||||
|
(let [lines (gpr/rect->lines rect)]
|
||||||
|
(is-point-inside-evenodd? point lines)))
|
||||||
|
|
||||||
(defn has-point?
|
(defn has-point?
|
||||||
"Check if the shape contains a point"
|
"Check if the shape contains a point"
|
||||||
[shape point]
|
[shape point]
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
(gpt/point (+ x width) (+ y height))
|
(gpt/point (+ x width) (+ y height))
|
||||||
(gpt/point x (+ y height))])
|
(gpt/point x (+ y height))])
|
||||||
|
|
||||||
|
(defn rect->lines [{:keys [x y width height]}]
|
||||||
|
[[(gpt/point x y) (gpt/point (+ x width) y)]
|
||||||
|
[(gpt/point (+ x width) y) (gpt/point (+ x width) (+ y height))]
|
||||||
|
[(gpt/point (+ x width) (+ y height)) (gpt/point x (+ y height))]
|
||||||
|
[(gpt/point x (+ y height)) (gpt/point x y)]])
|
||||||
|
|
||||||
(defn points->rect
|
(defn points->rect
|
||||||
[points]
|
[points]
|
||||||
(let [minx (transduce gco/map-x-xf min ##Inf points)
|
(let [minx (transduce gco/map-x-xf min ##Inf points)
|
||||||
|
|
|
@ -732,7 +732,23 @@
|
||||||
(-> state
|
(-> state
|
||||||
(update-in [:workspace-local :edit-path id :selected-handlers] (fnil conj #{}) [index type]))))))
|
(update-in [:workspace-local :edit-path id :selected-handlers] (fnil conj #{}) [index type]))))))
|
||||||
|
|
||||||
(defn select-node [position]
|
(defn select-node-area [shift?]
|
||||||
|
(ptk/reify ::select-node-area
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [selrect (get-in state [:workspace-local :selrect])
|
||||||
|
id (get-in state [:workspace-local :edition])
|
||||||
|
content (get-in state (get-path state :content))
|
||||||
|
selected-point? (fn [point]
|
||||||
|
(gsh/has-point-rect? selrect point))
|
||||||
|
positions (into #{}
|
||||||
|
(comp (map (comp gpt/point :params))
|
||||||
|
(filter selected-point?))
|
||||||
|
content)]
|
||||||
|
(-> state
|
||||||
|
(assoc-in [:workspace-local :edit-path id :selected-points] positions))))))
|
||||||
|
|
||||||
|
(defn select-node [position shift?]
|
||||||
(ptk/reify ::select-node
|
(ptk/reify ::select-node
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
|
@ -740,7 +756,7 @@
|
||||||
(-> state
|
(-> state
|
||||||
(assoc-in [:workspace-local :edit-path id :selected-points] #{position}))))))
|
(assoc-in [:workspace-local :edit-path id :selected-points] #{position}))))))
|
||||||
|
|
||||||
(defn deselect-node [position]
|
(defn deselect-node [position shift?]
|
||||||
(ptk/reify ::deselect-node
|
(ptk/reify ::deselect-node
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
|
@ -858,3 +874,54 @@
|
||||||
(rx/filter #(= % :interrupt))
|
(rx/filter #(= % :interrupt))
|
||||||
(rx/take 1)
|
(rx/take 1)
|
||||||
(rx/map #(stop-path-edit))))))))
|
(rx/map #(stop-path-edit))))))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn update-area-selection
|
||||||
|
[selrect]
|
||||||
|
(ptk/reify ::update-area-selection
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:workspace-local :selrect] selrect))))
|
||||||
|
|
||||||
|
(defn clear-area-selection
|
||||||
|
[]
|
||||||
|
(ptk/reify ::clear-area-selection
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(update state :workspace-local dissoc :selrect))))
|
||||||
|
|
||||||
|
(defn handle-selection
|
||||||
|
[shift?]
|
||||||
|
(letfn [(data->selrect [data]
|
||||||
|
(let [start (:start data)
|
||||||
|
stop (:stop data)
|
||||||
|
start-x (min (:x start) (:x stop))
|
||||||
|
start-y (min (:y start) (:y stop))
|
||||||
|
end-x (max (:x start) (:x stop))
|
||||||
|
end-y (max (:y start) (:y stop))]
|
||||||
|
{:x start-x
|
||||||
|
:y start-y
|
||||||
|
:width (mth/abs (- end-x start-x))
|
||||||
|
:height (mth/abs (- end-y start-y))}))]
|
||||||
|
(ptk/reify ::handle-selection
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
(let [stop? (fn [event] (or (dwc/interrupt? event) (ms/mouse-up? event)))
|
||||||
|
stoper (->> stream (rx/filter stop?))]
|
||||||
|
(rx/concat
|
||||||
|
#_(when-not preserve?
|
||||||
|
(rx/of (deselect-all)))
|
||||||
|
(->> ms/mouse-position
|
||||||
|
(rx/scan (fn [data pos]
|
||||||
|
(if data
|
||||||
|
(assoc data :stop pos)
|
||||||
|
{:start pos :stop pos}))
|
||||||
|
nil)
|
||||||
|
(rx/map data->selrect)
|
||||||
|
(rx/filter #(or (> (:width %) 10)
|
||||||
|
(> (:height %) 10)))
|
||||||
|
(rx/map update-area-selection)
|
||||||
|
(rx/take-until stoper))
|
||||||
|
(rx/of (select-node-area shift?)
|
||||||
|
(clear-area-selection))
|
||||||
|
#_(rx/of (select-shapes-by-current-selrect preserve?))))))))
|
||||||
|
|
|
@ -60,9 +60,8 @@
|
||||||
(ptk/reify ::handle-selection
|
(ptk/reify ::handle-selection
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [stoper (rx/filter #(or (dwc/interrupt? %)
|
(let [stop? (fn [event] (or (dwc/interrupt? event) (ms/mouse-up? event)))
|
||||||
(ms/mouse-up? %))
|
stoper (->> stream (rx/filter stop?))]
|
||||||
stream)]
|
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(when-not preserve?
|
(when-not preserve?
|
||||||
(rx/of (deselect-all)))
|
(rx/of (deselect-all)))
|
||||||
|
|
|
@ -15,7 +15,9 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.geom.path :as ugp]
|
[app.util.geom.path :as ugp]
|
||||||
[goog.events :as events]
|
[goog.events :as events]
|
||||||
[rumext.alpha :as mf])
|
[rumext.alpha :as mf]
|
||||||
|
|
||||||
|
[app.util.keyboard :as kbd])
|
||||||
(:import goog.events.EventType))
|
(:import goog.events.EventType))
|
||||||
|
|
||||||
(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path? last-p?]}]
|
(mf/defc path-point [{:keys [position zoom edit-mode hover? selected? preview? start-path? last-p?]}]
|
||||||
|
@ -35,12 +37,13 @@
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(dom/prevent-default event)
|
(dom/prevent-default event)
|
||||||
|
|
||||||
(cond
|
(let [shift? (kbd/shift? event)]
|
||||||
(and (= edit-mode :move) (not selected?))
|
(cond
|
||||||
(st/emit! (drp/select-node position))
|
(and (= edit-mode :move) (not selected?))
|
||||||
|
(st/emit! (drp/select-node position shift?))
|
||||||
|
|
||||||
(and (= edit-mode :move) selected?)
|
(and (= edit-mode :move) selected?)
|
||||||
(st/emit! (drp/deselect-node position)))))
|
(st/emit! (drp/deselect-node position shift?))))))
|
||||||
|
|
||||||
|
|
||||||
on-mouse-down
|
on-mouse-down
|
||||||
|
@ -177,23 +180,24 @@
|
||||||
last-p (->> content last ugp/command->point)
|
last-p (->> content last ugp/command->point)
|
||||||
handlers (ugp/content->handlers content)
|
handlers (ugp/content->handlers content)
|
||||||
|
|
||||||
handle-click-outside
|
;;handle-click-outside
|
||||||
(fn [event]
|
;;(fn [event]
|
||||||
(let [current (dom/get-target event)
|
;; (let [current (dom/get-target event)
|
||||||
editor-dom (mf/ref-val editor-ref)]
|
;; editor-dom (mf/ref-val editor-ref)]
|
||||||
(when-not (or (.contains editor-dom current)
|
;; (when-not (or (.contains editor-dom current)
|
||||||
(dom/class? current "viewport-actions-entry"))
|
;; (dom/class? current "viewport-actions-entry"))
|
||||||
(st/emit! (drp/deselect-all)))))
|
;; (st/emit! (drp/deselect-all)))))
|
||||||
|
|
||||||
handle-double-click-outside
|
handle-double-click-outside
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (= edit-mode :move)
|
(when (= edit-mode :move)
|
||||||
(st/emit! :interrupt)))]
|
(st/emit! :interrupt)))
|
||||||
|
]
|
||||||
|
|
||||||
(mf/use-layout-effect
|
(mf/use-layout-effect
|
||||||
(mf/deps edit-mode)
|
(mf/deps edit-mode)
|
||||||
(fn []
|
(fn []
|
||||||
(let [keys [(events/listen (dom/get-root) EventType.CLICK handle-click-outside)
|
(let [keys [;;(events/listen (dom/get-root) EventType.CLICK handle-click-outside)
|
||||||
(events/listen (dom/get-root) EventType.DBLCLICK handle-double-click-outside)]]
|
(events/listen (dom/get-root) EventType.DBLCLICK handle-double-click-outside)]]
|
||||||
#(doseq [key keys]
|
#(doseq [key keys]
|
||||||
(events/unlistenByKey key)))))
|
(events/unlistenByKey key)))))
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
|
|
||||||
on-click (actions/on-click hover selected edition drawing-path? drawing-tool)
|
on-click (actions/on-click hover selected edition drawing-path? drawing-tool)
|
||||||
on-context-menu (actions/on-context-menu hover)
|
on-context-menu (actions/on-context-menu hover)
|
||||||
on-double-click (actions/on-double-click hover hover-ids drawing-path? objects)
|
on-double-click (actions/on-double-click hover hover-ids drawing-path? objects edition)
|
||||||
on-drag-enter (actions/on-drag-enter)
|
on-drag-enter (actions/on-drag-enter)
|
||||||
on-drag-over (actions/on-drag-over)
|
on-drag-over (actions/on-drag-over)
|
||||||
on-drop (actions/on-drop file viewport-ref zoom)
|
on-drop (actions/on-drop file viewport-ref zoom)
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.streams :as ms]
|
[app.main.streams :as ms]
|
||||||
[app.main.ui.workspace.viewport.utils :as utils]
|
[app.main.ui.workspace.viewport.utils :as utils]
|
||||||
|
[app.main.data.workspace.drawing.path :as dwdp]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.dom.dnd :as dnd]
|
[app.util.dom.dnd :as dnd]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
|
@ -57,13 +58,16 @@
|
||||||
(st/emit! dw/clear-edition-mode))
|
(st/emit! dw/clear-edition-mode))
|
||||||
|
|
||||||
(when (and (or (not edition) (not= edition id)) (not blocked) (not hidden) (not (#{:comments :path} drawing-tool)))
|
(when (and (or (not edition) (not= edition id)) (not blocked) (not hidden) (not (#{:comments :path} drawing-tool)))
|
||||||
|
(not= edition id))
|
||||||
|
(not blocked)
|
||||||
|
(not hidden))
|
||||||
(cond
|
(cond
|
||||||
drawing-tool
|
drawing-tool
|
||||||
(st/emit! (dd/start-drawing drawing-tool))
|
(st/emit! (dd/start-drawing drawing-tool))
|
||||||
|
|
||||||
(and edit-path (contains? edit-path edition))
|
(and edit-path (contains? edit-path edition))
|
||||||
;; Handle node select-drawing. NOP at the moment
|
;; Handle path node area selection
|
||||||
nil
|
(st/emit! (dwdp/handle-selection shift?))
|
||||||
|
|
||||||
(or (not id) (and frame? (not selected?)))
|
(or (not id) (and frame? (not selected?)))
|
||||||
(st/emit! (dw/handle-selection shift?))
|
(st/emit! (dw/handle-selection shift?))
|
||||||
|
@ -142,9 +146,9 @@
|
||||||
(st/emit! (dw/select-shape (:id @hover)))))))))
|
(st/emit! (dw/select-shape (:id @hover)))))))))
|
||||||
|
|
||||||
(defn on-double-click
|
(defn on-double-click
|
||||||
[hover hover-ids drawing-path? objects]
|
[hover hover-ids drawing-path? objects edition]
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps @hover @hover-ids drawing-path?)
|
(mf/deps @hover @hover-ids drawing-path? edition)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [ctrl? (kbd/ctrl? event)
|
(let [ctrl? (kbd/ctrl? event)
|
||||||
|
@ -170,7 +174,7 @@
|
||||||
(reset! hover-ids (into [] (rest @hover-ids)))
|
(reset! hover-ids (into [] (rest @hover-ids)))
|
||||||
(st/emit! (dw/select-shape (:id selected))))
|
(st/emit! (dw/select-shape (:id selected))))
|
||||||
|
|
||||||
(or text? path?)
|
(and (not= id edition) (or text? path?))
|
||||||
(st/emit! (dw/select-shape id)
|
(st/emit! (dw/select-shape id)
|
||||||
(dw/start-editing-selected))
|
(dw/start-editing-selected))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue