0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-04-15 16:31:25 -05:00

🐛 Fix box selection for components and nested frames

This commit is contained in:
alonso.torres 2024-01-24 10:03:52 +01:00 committed by Andrey Antukh
parent 9e24ba7b39
commit 942f6167b0
4 changed files with 67 additions and 32 deletions
frontend/src/app
main
data/workspace
streams.cljs
ui/workspace/viewport
worker

View file

@ -59,7 +59,7 @@
(assoc-in state [:workspace-local :selrect] selrect))))
(defn handle-area-selection
[preserve? ignore-groups?]
[preserve?]
(ptk/reify ::handle-area-selection
ptk/WatchEvent
(watch [_ state stream]
@ -114,7 +114,20 @@
(rx/buffer-time 100)
(rx/map last)
(rx/pipe (rxo/distinct-contiguous))
(rx/map #(select-shapes-by-current-selrect preserve? ignore-groups?))))
(rx/with-latest-from ms/keyboard-mod ms/keyboard-shift)
(rx/map
(fn [[_ mod? shift?]]
(select-shapes-by-current-selrect shift? mod?))))
;; The last "tick" from the mouse cannot be buffered so we are sure
;; a selection is returned. Without this we can have empty selections on
;; very fast movement
(->> selrect-stream
(rx/last)
(rx/with-latest-from ms/keyboard-mod ms/keyboard-shift)
(rx/map
(fn [[_ mod? shift?]]
(select-shapes-by-current-selrect shift? mod? false)))))
(->> (rx/of (update-selrect nil))
;; We need the async so the current event finishes before updating the selrect
@ -307,34 +320,39 @@
;; --- Select Shapes (By selrect)
(defn select-shapes-by-current-selrect
[preserve? ignore-groups?]
(ptk/reify ::select-shapes-by-current-selrect
ptk/WatchEvent
(watch [_ state _]
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state)
selected (wsh/lookup-selected state)
initial-set (if preserve?
selected
lks/empty-linked-set)
selrect (dm/get-in state [:workspace-local :selrect])
blocked? (fn [id] (dm/get-in objects [id :blocked] false))]
([preserve? ignore-groups?]
(select-shapes-by-current-selrect preserve? ignore-groups? true))
([preserve? ignore-groups? buffered?]
(ptk/reify ::select-shapes-by-current-selrect
ptk/WatchEvent
(watch [_ state _]
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state)
selected (wsh/lookup-selected state)
initial-set (if preserve?
selected
lks/empty-linked-set)
selrect (dm/get-in state [:workspace-local :selrect])
blocked? (fn [id] (dm/get-in objects [id :blocked] false))
(when selrect
(rx/empty)
(->> (uw/ask-buffered!
{:cmd :selection/query
:page-id page-id
:rect selrect
:include-frames? true
:ignore-groups? ignore-groups?
:full-frame? true
:using-selrect? true})
(rx/map #(cfh/clean-loops objects %))
(rx/map #(into initial-set (comp
(filter (complement blocked?))
(remove (partial cfh/hidden-parent? objects))) %))
(rx/map select-shapes)))))))
ask-worker (if buffered? uw/ask-buffered! uw/ask!)]
(if (some? selrect)
(->> (ask-worker
{:cmd :selection/query
:page-id page-id
:rect selrect
:include-frames? true
:ignore-groups? ignore-groups?
:full-frame? true
:using-selrect? true})
(rx/filter some?)
(rx/map #(cfh/clean-loops objects %))
(rx/map #(into initial-set (comp
(filter (complement blocked?))
(remove (partial cfh/hidden-parent? objects))) %))
(rx/map select-shapes))
(rx/empty)))))))
(defn select-inside-group
[group-id position]

View file

@ -112,6 +112,20 @@
(rx/sub! ob sub)
sub))
(defonce keyboard-shift
(let [sub (rx/behavior-subject nil)
ob (->> keyboard
(rx/filter kbd/shift-key?)
(rx/map kbd/key-down-event?)
;; Fix a situation caused by using `ctrl+alt` kind of
;; shortcuts, that makes keyboard-alt stream
;; registering the key pressed but on blurring the
;; window (unfocus) the key down is never arrived.
(rx/merge window-blur)
(rx/pipe (rxo/distinct-contiguous)))]
(rx/sub! ob sub)
sub))
(defonce keyboard-meta
(let [sub (rx/behavior-subject nil)
ob (->> keyboard

View file

@ -106,7 +106,7 @@
(st/emit! (dd/start-drawing drawing-tool)))
(or (not id) mod?)
(st/emit! (dw/handle-area-selection shift? mod?))
(st/emit! (dw/handle-area-selection shift?))
(not drawing-tool)
(when-not workspace-read-only?

View file

@ -127,7 +127,7 @@
match-criteria?
(fn [shape]
(and (not (:hidden shape))
(or (= :frame (:type shape)) ;; We return frames even if blocked
(or (cfh/frame-shape? shape) ;; We return frames even if blocked
(not (:blocked shape)))
(or (not frame-id) (= frame-id (:frame-id shape)))
(case (:type shape)
@ -135,8 +135,11 @@
(:bool :group) (not ignore-groups?)
true)
;; This condition controls when to check for overlapping. Otherwise the
;; shape needs to be fully contained.
(or (not full-frame?)
(not= :frame (:type shape))
(and (not ignore-groups?) (contains? shape :component-id))
(and (not ignore-groups?) (not (cfh/root-frame? shape)))
(and (d/not-empty? (:shapes shape))
(gsh/rect-contains-shape? rect shape))
(and (empty? (:shapes shape))