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