From 5f0020a95c99ebaa54527be20de82050cd7fd3cd Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 12 Jan 2021 11:20:36 +0100 Subject: [PATCH] :sparkles: Changes to the selection in workspace and layers --- common/app/common/geom/shapes.cljc | 1 + frontend/src/app/main/data/workspace.cljs | 2 + .../app/main/data/workspace/selection.cljs | 73 +++++++++++++++---- .../src/app/main/ui/workspace/effects.cljs | 48 ++++++++---- .../app/main/ui/workspace/shapes/common.cljs | 1 + .../app/main/ui/workspace/shapes/svg_raw.cljs | 4 +- .../app/main/ui/workspace/sidebar/layers.cljs | 3 + .../src/app/main/ui/workspace/viewport.cljs | 4 +- 8 files changed, 104 insertions(+), 32 deletions(-) diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index ccc26db3d..113cc741b 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -261,6 +261,7 @@ (d/export gco/center-selrect) (d/export gco/center-rect) (d/export gco/center-points) +(d/export gco/make-centered-rect) (d/export gpr/rect->selrect) (d/export gpr/rect->points) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 313bffaa7..600157360 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1527,9 +1527,11 @@ (d/export dws/select-all) (d/export dws/deselect-all) (d/export dwc/select-shapes) +(d/export dws/shift-select-shapes) (d/export dws/duplicate-selected) (d/export dws/handle-selection) (d/export dws/select-inside-group) +(d/export dws/select-last-layer) (d/export dwd/select-for-drawing) (d/export dwc/clear-edition-mode) (d/export dwc/add-shape) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index b12c44f80..adba8ac9e 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -105,6 +105,20 @@ objects (dwc/lookup-page-objects state page-id)] (rx/of (dwc/expand-all-parents [id] objects))))))) +(defn shift-select-shapes + ([id] + (ptk/reify ::shift-select-shapes + ptk/UpdateEvent + (update [_ state] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + selection (-> state + (get-in [:workspace-local :selected] #{}) + (conj id))] + (-> state + (assoc-in [:workspace-local :selected] + (cp/expand-region-selection objects selection)))))))) + (defn select-shapes [ids] (us/verify ::ordered-set-of-uuid ids) @@ -184,24 +198,51 @@ (rx/map select-shapes)))))))) (defn select-inside-group - [group-id position] - (ptk/reify ::select-inside-group - ptk/WatchEvent - (watch [_ state stream] - (let [page-id (:current-page-id state) - objects (dwc/lookup-page-objects state page-id) - group (get objects group-id) - children (map #(get objects %) (:shapes group)) + ([group-id position] (select-inside-group group-id position false)) + ([group-id position deep-children] + (ptk/reify ::select-inside-group + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + group (get objects group-id) + children (map #(get objects %) (:shapes group)) - ;; We need to reverse the children because if two children - ;; overlap we want to select the one that's over (and it's - ;; in the later vector position - selected (->> children - reverse - (d/seek #(geom/has-point? % position)))] - (when selected - (rx/of (deselect-all) (select-shape (:id selected)))))))) + ;; We need to reverse the children because if two children + ;; overlap we want to select the one that's over (and it's + ;; in the later vector position + selected (->> children + reverse + (d/seek #(geom/has-point? % position)))] + (when selected + (rx/of (deselect-all) (select-shape (:id selected))))))))) +(defn select-last-layer + ([position] + (ptk/reify ::select-last-layer + ptk/WatchEvent + (watch [_ state stream] + (let [page-id (:current-page-id state) + objects (dwc/lookup-page-objects state page-id) + find-shape + (fn [selection] + (when (seq selection) + (let [id (first selection) + shape (get objects id)] + (let [child-id (->> (cp/get-children id objects) + (map #(get objects %)) + (remove (comp empty :shapes)) + (filter #(geom/has-point? % position)) + (first) + :id)] + (or child-id id)))))] + (->> (uw/ask! {:cmd :selection/query + :page-id page-id + :rect (geom/make-centered-rect position 1 1)}) + (rx/first) + (rx/map find-shape) + (rx/filter #(not (nil? %))) + (rx/map #(select-shape % false)))))))) ;; --- Duplicate Shapes (declare prepare-duplicate-change) diff --git a/frontend/src/app/main/ui/workspace/effects.cljs b/frontend/src/app/main/ui/workspace/effects.cljs index 8937e7513..dbc85952a 100644 --- a/frontend/src/app/main/ui/workspace/effects.cljs +++ b/frontend/src/app/main/ui/workspace/effects.cljs @@ -50,13 +50,12 @@ edition @refs/selected-edition selected? (contains? selected id) drawing? @refs/selected-drawing-tool - button (.-which (.-nativeEvent event))] + button (.-which (.-nativeEvent event)) + shift? (kbd/shift? event) + ctrl? (kbd/ctrl? event)] (when-not blocked (cond - (not= 1 button) - nil - - drawing? + (or (not= 1 button) drawing? ctrl?) nil (= type :frame) @@ -68,13 +67,34 @@ :else (do (dom/stop-propagation event) - (if selected? - (when (kbd/shift? event) - (st/emit! (dw/select-shape id true))) - (do - (when-not (or (empty? selected) (kbd/shift? event)) - (st/emit! (dw/deselect-all))) - (st/emit! (dw/select-shape id)))) - (when (not= edition id) - (st/emit! (dw/start-move-selected)))))))))) + (let [toggle-selected? (and selected? shift?) + deselect? (and (not selected?) (not (empty? selected)) (not shift?))] + (apply + st/emit! + (cond-> [] + ;; Deselect shapes before doing a selection or click outside + deselect? + (conj (dw/deselect-all)) + + ;; Shift click to add a shape to the selection + toggle-selected? + (conj (dw/select-shape id true)) + + ;; Simple click to select + (not selected?) + (conj (dw/select-shape id)) + + ;; Mouse down to start moving a shape + (not= edition id) + (conj (dw/start-move-selected)))))))))))) + +(defn use-double-click + "This effect will consume the event and stop the propagation so double clicks on shapes + will not select the frame" + [{:keys [id]}] + (mf/use-callback + (mf/deps id) + (fn [event] + (dom/stop-propagation event) + (dom/prevent-default event)))) diff --git a/frontend/src/app/main/ui/workspace/shapes/common.cljs b/frontend/src/app/main/ui/workspace/shapes/common.cljs index af4986035..26db44abc 100644 --- a/frontend/src/app/main/ui/workspace/shapes/common.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/common.cljs @@ -21,6 +21,7 @@ (let [shape (unchecked-get props "shape")] [:> shape-container {:shape shape :on-mouse-down (we/use-mouse-down shape) + :on-double-click (we/use-double-click shape) :on-context-menu (we/use-context-menu shape) :on-pointer-over (we/use-pointer-enter shape) :on-pointer-out (we/use-pointer-leave shape)} diff --git a/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs b/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs index 037b76e37..4a92c4b0c 100644 --- a/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/svg_raw.cljs @@ -50,10 +50,11 @@ tag (get-in shape [:content :tag]) - handle-mouse-down (we/use-mouse-down shape) + handle-mouse-down (we/use-mouse-down shape) handle-context-menu (we/use-context-menu shape) handle-pointer-enter (we/use-pointer-enter shape) handle-pointer-leave (we/use-pointer-leave shape) + handle-double-click (we/use-double-click shape) def-ctx? (mf/use-ctx muc/def-ctx)] @@ -74,6 +75,7 @@ :height height :fill "transparent" :on-mouse-down handle-mouse-down + :on-double-click handle-double-click :on-context-menu handle-context-menu :on-pointer-over handle-pointer-enter :on-pointer-out handle-pointer-leave}])] diff --git a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs index ed2855291..82c8fdb3d 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/layers.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/layers.cljs @@ -141,6 +141,9 @@ nil (.-shiftKey event) + (st/emit! (dw/shift-select-shapes id)) + + (.-ctrlKey event) (st/emit! (dw/select-shape id true)) (> (count selected) 1) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 288ef617b..ef6a7e354 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -326,7 +326,9 @@ (let [ctrl? (kbd/ctrl? event) shift? (kbd/shift? event) alt? (kbd/alt? event)] - (st/emit! (ms/->MouseEvent :click ctrl? shift? alt?))))) + (if ctrl? + (st/emit! (dw/select-last-layer @ms/mouse-position)) + (st/emit! (ms/->MouseEvent :click ctrl? shift? alt?)))))) on-double-click (mf/use-callback