diff --git a/frontend/resources/images/cursors/zoom-in.svg b/frontend/resources/images/cursors/zoom-in.svg new file mode 100644 index 000000000..ecd153448 --- /dev/null +++ b/frontend/resources/images/cursors/zoom-in.svg @@ -0,0 +1 @@ + diff --git a/frontend/resources/images/cursors/zoom-out.svg b/frontend/resources/images/cursors/zoom-out.svg new file mode 100644 index 000000000..65a5a300f --- /dev/null +++ b/frontend/resources/images/cursors/zoom-out.svg @@ -0,0 +1 @@ + diff --git a/frontend/resources/images/cursors/zoom.svg b/frontend/resources/images/cursors/zoom.svg new file mode 100644 index 000000000..9650153fe --- /dev/null +++ b/frontend/resources/images/cursors/zoom.svg @@ -0,0 +1 @@ + diff --git a/frontend/resources/styles/main/partials/debug-icons-preview.scss b/frontend/resources/styles/main/partials/debug-icons-preview.scss index 8ddba1688..afca85123 100644 --- a/frontend/resources/styles/main/partials/debug-icons-preview.scss +++ b/frontend/resources/styles/main/partials/debug-icons-preview.scss @@ -2,7 +2,9 @@ display: flex; flex-direction: column; overflow: scroll; + height: 100%; } + .debug-icons-preview { display: flex; flex-wrap: wrap; diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 46b554a22..264874a94 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -47,7 +47,7 @@ (assoc-in state [:workspace-local :selrect] selrect)))) (defn handle-area-selection - [preserve?] + [preserve? ignore-groups?] (letfn [(data->selrect [data] (let [start (:start data) stop (:stop data) @@ -91,7 +91,7 @@ (rx/buffer-time 100) (rx/map #(last %)) (rx/dedupe) - (rx/map #(select-shapes-by-current-selrect preserve?)))) + (rx/map #(select-shapes-by-current-selrect preserve? ignore-groups?)))) (rx/of (update-selrect nil)))))))) @@ -218,7 +218,7 @@ ;; --- Select Shapes (By selrect) (defn select-shapes-by-current-selrect - [preserve?] + [preserve? ignore-groups?] (ptk/reify ::select-shapes-by-current-selrect ptk/WatchEvent (watch [_ state _] @@ -237,6 +237,7 @@ :page-id page-id :rect selrect :include-frames? true + :ignore-groups? ignore-groups? :full-frame? true}) (rx/map #(cp/clean-loops objects %)) (rx/map #(into initial-set (filter (comp not blocked?)) %)) diff --git a/frontend/src/app/main/ui/cursors.cljs b/frontend/src/app/main/ui/cursors.cljs index a57575099..2d571ed06 100644 --- a/frontend/src/app/main/ui/cursors.cljs +++ b/frontend/src/app/main/ui/cursors.cljs @@ -30,6 +30,9 @@ (def pointer-node (cursor-ref :pointer-node 0 0 10 32)) (def resize-alt (cursor-ref :resize-alt)) (def text (cursor-ref :text)) +(def zoom (cursor-ref :zoom)) +(def zoom-in (cursor-ref :zoom-in)) +(def zoom-out (cursor-ref :zoom-out)) ;; Dynamic cursors (def resize-ew (cursor-fn :resize-h 0)) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index f88972c48..def9a0852 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -115,21 +115,21 @@ node-editing? (and edition (not= :text (get-in base-objects [edition :type]))) text-editing? (and edition (= :text (get-in base-objects [edition :type]))) - on-click (actions/on-click hover selected edition drawing-path? drawing-tool) + on-click (actions/on-click hover selected edition drawing-path? drawing-tool space?) on-context-menu (actions/on-context-menu hover hover-ids) on-double-click (actions/on-double-click hover hover-ids drawing-path? base-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) on-mouse-down (actions/on-mouse-down @hover selected edition drawing-tool text-editing? node-editing? - drawing-path? create-comment? space? viewport-ref zoom) + drawing-path? create-comment? space? viewport-ref zoom panning) on-mouse-up (actions/on-mouse-up disable-paste) on-pointer-down (actions/on-pointer-down) on-pointer-enter (actions/on-pointer-enter in-viewport?) on-pointer-leave (actions/on-pointer-leave in-viewport?) on-pointer-move (actions/on-pointer-move viewport-ref zoom move-stream) on-pointer-up (actions/on-pointer-up) - on-move-selected (actions/on-move-selected hover hover-ids selected) + on-move-selected (actions/on-move-selected hover hover-ids selected space?) on-menu-selected (actions/on-menu-selected hover hover-ids selected) on-frame-enter (actions/on-frame-enter frame-hover) @@ -162,15 +162,13 @@ (hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport?) (hooks/setup-viewport-size viewport-ref) - (hooks/setup-cursor cursor alt? panning drawing-tool drawing-path? node-editing?) + (hooks/setup-cursor cursor alt? ctrl? space? panning drawing-tool drawing-path? node-editing?) (hooks/setup-keyboard alt? ctrl? space?) (hooks/setup-hover-shapes page-id move-stream base-objects transform selected ctrl? hover hover-ids @hover-disabled? zoom) (hooks/setup-viewport-modifiers modifiers base-objects) (hooks/setup-shortcuts node-editing? drawing-path?) (hooks/setup-active-frames base-objects vbox hover active-frames) - - [:div.viewport [:div.viewport-overlays @@ -245,7 +243,7 @@ [:& outline/shape-outlines {:objects base-objects :selected selected - :hover (when (not= :frame (:type @hover)) + :hover (when (or @ctrl? (not= :frame (:type @hover))) #{(or @frame-hover (:id @hover))}) :edition edition :zoom zoom}]) @@ -262,7 +260,7 @@ :shapes selected-shapes :zoom zoom :edition edition - :disable-handlers (or drawing-tool edition) + :disable-handlers (or drawing-tool edition @space?) :on-move-selected on-move-selected :on-context-menu on-menu-selected}]) diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index 486288374..084f9ec8f 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -28,10 +28,11 @@ (defn on-mouse-down [{:keys [id blocked hidden type]} selected edition drawing-tool text-editing? - node-editing? drawing-path? create-comment? space? viewport-ref zoom] + node-editing? drawing-path? create-comment? space? viewport-ref zoom panning] (mf/use-callback (mf/deps id blocked hidden type selected edition drawing-tool text-editing? - node-editing? drawing-path? create-comment? space? viewport-ref zoom) + node-editing? drawing-path? create-comment? @space? viewport-ref zoom + panning) (fn [bevent] (when (or (dom/class? (dom/get-target bevent) "viewport-controls") (dom/class? (dom/get-target bevent) "viewport-selrect")) @@ -42,62 +43,75 @@ shift? (kbd/shift? event) alt? (kbd/alt? event) - left-click? (= 1 (.-which event)) - middle-click? (= 2 (.-which event)) + left-click? (and (not panning) (= 1 (.-which event))) + middle-click? (and (not panning) (= 2 (.-which event))) frame? (= :frame type) selected? (contains? selected id)] - (when middle-click? - (dom/prevent-default bevent) - (if ctrl? - (let [raw-pt (dom/get-client-position event) - viewport (mf/ref-val viewport-ref) - pt (utils/translate-point-to-viewport viewport zoom raw-pt)] - (st/emit! (dw/start-zooming pt))) - (st/emit! (dw/start-panning)))) + (cond + middle-click? + (do + (dom/prevent-default bevent) + (if ctrl? + (let [raw-pt (dom/get-client-position event) + viewport (mf/ref-val viewport-ref) + pt (utils/translate-point-to-viewport viewport zoom raw-pt)] + (st/emit! (dw/start-zooming pt))) + (st/emit! (dw/start-panning)))) - (when left-click? - (st/emit! (ms/->MouseEvent :down ctrl? shift? alt?)) - (when (and (not= edition id) text-editing?) - (st/emit! dw/clear-edition-mode)) + left-click? + (do + (st/emit! (ms/->MouseEvent :down ctrl? shift? alt?)) - (when (and (not text-editing?) - (not blocked) - (not hidden) - (not create-comment?) - (not drawing-path?)) - (cond - drawing-tool - (st/emit! (dd/start-drawing drawing-tool)) + (when (and (not= edition id) text-editing?) + (st/emit! dw/clear-edition-mode)) - node-editing? - ;; Handle path node area selection - (st/emit! (dwdp/handle-area-selection shift?)) + (when (and (not text-editing?) + (not blocked) + (not hidden) + (not create-comment?) + (not drawing-path?)) + (cond + node-editing? + ;; Handle path node area selection + (st/emit! (dwdp/handle-area-selection shift?)) - @space? - (st/emit! (dw/start-panning)) + (and @space? ctrl?) + (let [raw-pt (dom/get-client-position event) + viewport (mf/ref-val viewport-ref) + pt (utils/translate-point-to-viewport viewport zoom raw-pt)] + (st/emit! (dw/start-zooming pt))) - (or (not id) (and frame? (not selected?))) - (st/emit! (dw/handle-area-selection shift?)) + @space? + (st/emit! (dw/start-panning)) - (not drawing-tool) - (st/emit! (when (or shift? (not selected?)) - (dw/select-shape id shift?)) - (dw/start-move-selected)))))))))) + drawing-tool + (st/emit! (dd/start-drawing drawing-tool)) + + (or (not id) (and frame? (not selected?)) ctrl?) + (st/emit! (dw/handle-area-selection shift? ctrl?)) + + (not drawing-tool) + (st/emit! (when (or shift? (not selected?)) + (dw/select-shape id shift?)) + (dw/start-move-selected))))))))))) (defn on-move-selected - [hover hover-ids selected] + [hover hover-ids selected space?] (mf/use-callback - (mf/deps @hover @hover-ids selected) + (mf/deps @hover @hover-ids selected @space?) (fn [bevent] (let [event (.-nativeEvent bevent) shift? (kbd/shift? event) + ctrl? (kbd/ctrl? event) left-click? (= 1 (.-which event))] (when (and left-click? + (not ctrl?) (not shift?) + (not @space?) (or (not @hover) (= :frame (:type @hover)) (some #(contains? selected %) @hover-ids))) @@ -130,9 +144,9 @@ (reset! frame-hover nil)))) (defn on-click - [hover selected edition drawing-path? drawing-tool] + [hover selected edition drawing-path? drawing-tool space?] (mf/use-callback - (mf/deps @hover selected edition drawing-path? drawing-tool) + (mf/deps @hover selected edition drawing-path? drawing-tool @space?) (fn [event] (when (or (dom/class? (dom/get-target event) "viewport-controls") (dom/class? (dom/get-target event) "viewport-selrect")) @@ -147,7 +161,8 @@ (when (and hovering? (not shift?) - (not frame?) + (or ctrl? (not frame?)) + (not @space?) (not selected?) (not edition) (not drawing-path?) @@ -229,17 +244,17 @@ middle-click? (= 2 (.-which event))] (when left-click? - (st/emit! (dw/finish-panning) - (ms/->MouseEvent :up ctrl? shift? alt?))) + (st/emit! (ms/->MouseEvent :up ctrl? shift? alt?))) (when middle-click? (dom/prevent-default event) ;; We store this so in Firefox the middle button won't do a paste of the content (reset! disable-paste true) - (timers/schedule #(reset! disable-paste false)) - (st/emit! (dw/finish-panning) - (dw/finish-zooming))))))) + (timers/schedule #(reset! disable-paste false))) + + (st/emit! (dw/finish-panning) + (dw/finish-zooming)))))) (defn on-pointer-enter [in-viewport?] (mf/use-callback diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index 21ea3e700..49c1d9315 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -57,13 +57,14 @@ ;; We schedule the event so it fires after `initialize-page` event (timers/schedule #(st/emit! (dw/initialize-viewport size))))))) -(defn setup-cursor [cursor alt? panning drawing-tool drawing-path? path-editing?] +(defn setup-cursor [cursor alt? ctrl? space? panning drawing-tool drawing-path? path-editing?] (mf/use-effect - (mf/deps @cursor @alt? panning drawing-tool drawing-path? path-editing?) + (mf/deps @cursor @alt? @ctrl? @space? panning drawing-tool drawing-path? path-editing?) (fn [] (let [new-cursor (cond - panning (utils/get-cursor :hand) + (and @ctrl? @space?) (utils/get-cursor :zoom) + (or panning @space?) (utils/get-cursor :hand) (= drawing-tool :comments) (utils/get-cursor :comments) (= drawing-tool :frame) (utils/get-cursor :create-artboard) (= drawing-tool :rect) (utils/get-cursor :create-rectangle) diff --git a/frontend/src/app/main/ui/workspace/viewport/utils.cljs b/frontend/src/app/main/ui/workspace/viewport/utils.cljs index 9c0734afa..873061070 100644 --- a/frontend/src/app/main/ui/workspace/viewport/utils.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/utils.cljs @@ -179,4 +179,7 @@ :pencil cur/pencil :create-shape cur/create-shape :duplicate cur/duplicate + :zoom cur/zoom + :zoom-in cur/zoom-in + :zooom-out cur/zoom-out cur/pointer-inner)) diff --git a/frontend/src/app/worker/selection.cljs b/frontend/src/app/worker/selection.cljs index d0b229034..ed0412f86 100644 --- a/frontend/src/app/worker/selection.cljs +++ b/frontend/src/app/worker/selection.cljs @@ -105,7 +105,7 @@ (assoc data :index index :z-index z-index))) (defn- query-index - [{index :index z-index :z-index} rect frame-id full-frame? include-frames? clip-children? reverse?] + [{index :index z-index :z-index} rect frame-id full-frame? include-frames? ignore-groups? clip-children? reverse?] (let [result (-> (qdt/search index (clj->js rect)) (es6-iterator-seq)) @@ -117,6 +117,7 @@ (or (not frame-id) (= frame-id (:frame-id shape))) (case (:type shape) :frame include-frames? + (:bool :group) (not ignore-groups?) true) (or (not full-frame?) @@ -189,10 +190,10 @@ nil) (defmethod impl/handler :selection/query - [{:keys [page-id rect frame-id reverse? full-frame? include-frames? clip-children?] + [{:keys [page-id rect frame-id reverse? full-frame? include-frames? ignore-groups? clip-children?] :or {reverse? false full-frame? false include-frames? false clip-children? true} :as message}] (when-let [index (get @state page-id)] - (query-index index rect frame-id full-frame? include-frames? clip-children? reverse?))) + (query-index index rect frame-id full-frame? include-frames? ignore-groups? clip-children? reverse?))) (defmethod impl/handler :selection/query-z-index [{:keys [page-id objects ids]}]