mirror of
https://github.com/penpot/penpot.git
synced 2025-05-20 16:56:11 +02:00
🎉 Zoom lense tool
This commit is contained in:
parent
a8c0d437ce
commit
c25cf043fa
10 changed files with 103 additions and 42 deletions
|
@ -17,6 +17,7 @@
|
||||||
- Add copy invitation link to the invitation options [Taiga #4213](https://tree.taiga.io/project/penpot/us/4213)
|
- Add copy invitation link to the invitation options [Taiga #4213](https://tree.taiga.io/project/penpot/us/4213)
|
||||||
- Dynamic alignment only in sight [Taiga #3537](https://tree.taiga.io/project/penpot/us/3537)
|
- Dynamic alignment only in sight [Taiga #3537](https://tree.taiga.io/project/penpot/us/3537)
|
||||||
- Improve naming of layers [Taiga #4036](https://tree.taiga.io/project/penpot/us/4036)
|
- Improve naming of layers [Taiga #4036](https://tree.taiga.io/project/penpot/us/4036)
|
||||||
|
- Add zoom lense [Taiga #4691](https://tree.taiga.io/project/penpot/us/4691)
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
|
|
|
@ -245,7 +245,7 @@
|
||||||
:command "t"
|
:command "t"
|
||||||
:subsections [:tools]
|
:subsections [:tools]
|
||||||
:fn #(emit-when-no-readonly dwtxt/start-edit-if-selected
|
:fn #(emit-when-no-readonly dwtxt/start-edit-if-selected
|
||||||
(dwd/select-for-drawing :text))}
|
(dwd/select-for-drawing :text))}
|
||||||
|
|
||||||
:draw-path {:tooltip "P"
|
:draw-path {:tooltip "P"
|
||||||
:command "p"
|
:command "p"
|
||||||
|
@ -419,14 +419,14 @@
|
||||||
:subsections [:panels]
|
:subsections [:panels]
|
||||||
:fn #(do (r/set-resize-type! :bottom)
|
:fn #(do (r/set-resize-type! :bottom)
|
||||||
(emit-when-no-readonly (dw/remove-layout-flag :textpalette)
|
(emit-when-no-readonly (dw/remove-layout-flag :textpalette)
|
||||||
(toggle-layout-flag :colorpalette)))}
|
(toggle-layout-flag :colorpalette)))}
|
||||||
|
|
||||||
:toggle-textpalette {:tooltip (ds/alt "T")
|
:toggle-textpalette {:tooltip (ds/alt "T")
|
||||||
:command (ds/a-mod "t")
|
:command (ds/a-mod "t")
|
||||||
:subsections [:panels]
|
:subsections [:panels]
|
||||||
:fn #(do (r/set-resize-type! :bottom)
|
:fn #(do (r/set-resize-type! :bottom)
|
||||||
(emit-when-no-readonly (dw/remove-layout-flag :colorpalette)
|
(emit-when-no-readonly (dw/remove-layout-flag :colorpalette)
|
||||||
(toggle-layout-flag :textpalette)))}
|
(toggle-layout-flag :textpalette)))}
|
||||||
|
|
||||||
:hide-ui {:tooltip "\\"
|
:hide-ui {:tooltip "\\"
|
||||||
:command "\\"
|
:command "\\"
|
||||||
|
@ -460,6 +460,16 @@
|
||||||
:subsections [:zoom-workspace]
|
:subsections [:zoom-workspace]
|
||||||
:fn #(st/emit! dw/zoom-to-selected-shape)}
|
:fn #(st/emit! dw/zoom-to-selected-shape)}
|
||||||
|
|
||||||
|
:zoom-lense-increase {:tooltip "Z"
|
||||||
|
:command "z"
|
||||||
|
:subsections [:zoom-workspace]
|
||||||
|
:fn identity}
|
||||||
|
|
||||||
|
:zoom-lense-decrease {:tooltip (ds/alt "Z")
|
||||||
|
:command "alt+z"
|
||||||
|
:subsections [:zoom-workspace]
|
||||||
|
:fn identity}
|
||||||
|
|
||||||
;; NAVIGATION
|
;; NAVIGATION
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -194,3 +194,14 @@
|
||||||
(rx/dedupe))]
|
(rx/dedupe))]
|
||||||
(rx/subscribe-with ob sub)
|
(rx/subscribe-with ob sub)
|
||||||
sub))
|
sub))
|
||||||
|
|
||||||
|
(defonce keyboard-z
|
||||||
|
(let [sub (rx/behavior-subject nil)
|
||||||
|
ob (->> st/stream
|
||||||
|
(rx/filter keyboard-event?)
|
||||||
|
(rx/filter kbd/z?)
|
||||||
|
(rx/filter (comp not kbd/editing?))
|
||||||
|
(rx/map #(= :down (:type %)))
|
||||||
|
(rx/dedupe))]
|
||||||
|
(rx/subscribe-with ob sub)
|
||||||
|
sub))
|
||||||
|
|
|
@ -106,6 +106,7 @@
|
||||||
alt? (mf/use-state false)
|
alt? (mf/use-state false)
|
||||||
mod? (mf/use-state false)
|
mod? (mf/use-state false)
|
||||||
space? (mf/use-state false)
|
space? (mf/use-state false)
|
||||||
|
z? (mf/use-state false)
|
||||||
cursor (mf/use-state (utils/get-cursor :pointer-inner))
|
cursor (mf/use-state (utils/get-cursor :pointer-inner))
|
||||||
hover-ids (mf/use-state nil)
|
hover-ids (mf/use-state nil)
|
||||||
hover (mf/use-state nil)
|
hover (mf/use-state nil)
|
||||||
|
@ -154,9 +155,9 @@
|
||||||
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
|
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
mode-inspect? (= options-mode :inspect)
|
mode-inspect? (= options-mode :inspect)
|
||||||
|
|
||||||
on-click (actions/on-click hover selected edition drawing-path? drawing-tool space? selrect)
|
on-click (actions/on-click hover selected edition drawing-path? drawing-tool space? selrect z?)
|
||||||
on-context-menu (actions/on-context-menu hover hover-ids workspace-read-only?)
|
on-context-menu (actions/on-context-menu hover hover-ids workspace-read-only?)
|
||||||
on-double-click (actions/on-double-click hover hover-ids drawing-path? base-objects edition workspace-read-only?)
|
on-double-click (actions/on-double-click hover hover-ids drawing-path? base-objects edition drawing-tool z? workspace-read-only?)
|
||||||
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)
|
on-drop (actions/on-drop file)
|
||||||
|
@ -212,8 +213,8 @@
|
||||||
|
|
||||||
(hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport? workspace-read-only?)
|
(hooks/setup-dom-events viewport-ref zoom disable-paste in-viewport? workspace-read-only?)
|
||||||
(hooks/setup-viewport-size viewport-ref)
|
(hooks/setup-viewport-size viewport-ref)
|
||||||
(hooks/setup-cursor cursor alt? mod? space? panning drawing-tool drawing-path? node-editing? workspace-read-only?)
|
(hooks/setup-cursor cursor alt? mod? space? panning drawing-tool drawing-path? node-editing? z? workspace-read-only?)
|
||||||
(hooks/setup-keyboard alt? mod? space?)
|
(hooks/setup-keyboard alt? mod? space? z?)
|
||||||
(hooks/setup-hover-shapes page-id move-stream base-objects transform selected mod? hover hover-ids hover-top-frame-id @hover-disabled? focus zoom show-measures?)
|
(hooks/setup-hover-shapes page-id move-stream base-objects transform selected mod? hover hover-ids hover-top-frame-id @hover-disabled? focus zoom show-measures?)
|
||||||
(hooks/setup-viewport-modifiers modifiers base-objects)
|
(hooks/setup-viewport-modifiers modifiers base-objects)
|
||||||
(hooks/setup-shortcuts node-editing? drawing-path?)
|
(hooks/setup-shortcuts node-editing? drawing-path?)
|
||||||
|
|
|
@ -34,8 +34,7 @@
|
||||||
|
|
||||||
(defn on-mouse-down
|
(defn on-mouse-down
|
||||||
[{:keys [id blocked hidden type]} selected edition drawing-tool text-editing?
|
[{:keys [id blocked hidden type]} selected edition drawing-tool text-editing?
|
||||||
node-editing? drawing-path? create-comment? space? panning
|
node-editing? drawing-path? create-comment? space? panning workspace-read-only?]
|
||||||
workspace-read-only?]
|
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps id blocked hidden type selected edition drawing-tool text-editing?
|
(mf/deps id blocked hidden type selected edition drawing-tool text-editing?
|
||||||
node-editing? drawing-path? create-comment? @space?
|
node-editing? drawing-path? create-comment? @space?
|
||||||
|
@ -140,9 +139,9 @@
|
||||||
(reset! frame-hover nil))))
|
(reset! frame-hover nil))))
|
||||||
|
|
||||||
(defn on-click
|
(defn on-click
|
||||||
[hover selected edition drawing-path? drawing-tool space? selrect]
|
[hover selected edition drawing-path? drawing-tool space? selrect z?]
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps @hover selected edition drawing-path? drawing-tool @space? selrect)
|
(mf/deps @hover selected edition drawing-path? drawing-tool @space? selrect @z?)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(when (and (nil? selrect)
|
(when (and (nil? selrect)
|
||||||
(or (dom/class? (dom/get-target event) "viewport-controls")
|
(or (dom/class? (dom/get-target event) "viewport-controls")
|
||||||
|
@ -151,7 +150,9 @@
|
||||||
shift? (kbd/shift? event)
|
shift? (kbd/shift? event)
|
||||||
alt? (kbd/alt? event)
|
alt? (kbd/alt? event)
|
||||||
meta? (kbd/meta? event)
|
meta? (kbd/meta? event)
|
||||||
hovering? (some? @hover)]
|
hovering? (some? @hover)
|
||||||
|
raw-pt (dom/get-client-position event)
|
||||||
|
pt (uwvv/point->viewport raw-pt)]
|
||||||
(st/emit! (ms/->MouseEvent :click ctrl? shift? alt? meta?))
|
(st/emit! (ms/->MouseEvent :click ctrl? shift? alt? meta?))
|
||||||
|
|
||||||
(when (and hovering?
|
(when (and hovering?
|
||||||
|
@ -159,42 +160,52 @@
|
||||||
(not edition)
|
(not edition)
|
||||||
(not drawing-path?)
|
(not drawing-path?)
|
||||||
(not drawing-tool))
|
(not drawing-tool))
|
||||||
(st/emit! (dw/select-shape (:id @hover) shift?))))))))
|
(st/emit! (dw/select-shape (:id @hover) shift?)))
|
||||||
|
|
||||||
|
(when (and @z?
|
||||||
|
(not @space?)
|
||||||
|
(not edition)
|
||||||
|
(not drawing-path?)
|
||||||
|
(not drawing-tool))
|
||||||
|
(if alt?
|
||||||
|
(st/emit! (dw/decrease-zoom pt))
|
||||||
|
(st/emit! (dw/increase-zoom pt)))))))))
|
||||||
|
|
||||||
(defn on-double-click
|
(defn on-double-click
|
||||||
[hover hover-ids drawing-path? objects edition workspace-read-only?]
|
[hover hover-ids drawing-path? objects edition drawing-tool z? workspace-read-only?]
|
||||||
|
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
(mf/deps @hover @hover-ids drawing-path? edition workspace-read-only?)
|
(mf/deps @hover @hover-ids drawing-path? edition drawing-tool @z? workspace-read-only?)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(dom/stop-propagation event)
|
(dom/stop-propagation event)
|
||||||
(let [ctrl? (kbd/ctrl? event)
|
(when (not z?)
|
||||||
shift? (kbd/shift? event)
|
(let [ctrl? (kbd/ctrl? event)
|
||||||
alt? (kbd/alt? event)
|
shift? (kbd/shift? event)
|
||||||
meta? (kbd/meta? event)
|
alt? (kbd/alt? event)
|
||||||
|
meta? (kbd/meta? event)
|
||||||
|
|
||||||
{:keys [id type] :as shape} (or @hover (get objects (first @hover-ids)))
|
{:keys [id type] :as shape} (or @hover (get objects (first @hover-ids)))
|
||||||
|
|
||||||
editable? (contains? #{:text :rect :path :image :circle} type)]
|
editable? (contains? #{:text :rect :path :image :circle} type)]
|
||||||
|
|
||||||
(st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt? meta?))
|
(st/emit! (ms/->MouseEvent :double-click ctrl? shift? alt? meta?))
|
||||||
|
|
||||||
;; Emit asynchronously so the double click to exit shapes won't break
|
;; Emit asynchronously so the double click to exit shapes won't break
|
||||||
(timers/schedule
|
(timers/schedule
|
||||||
(fn []
|
(fn []
|
||||||
(when (and (not drawing-path?) shape)
|
(when (and (not drawing-path?) shape)
|
||||||
(cond
|
(cond
|
||||||
(and editable? (not= id edition) (not workspace-read-only?))
|
(and editable? (not= id edition) (not workspace-read-only?))
|
||||||
(st/emit! (dw/select-shape id)
|
(st/emit! (dw/select-shape id)
|
||||||
(dw/start-editing-selected))
|
(dw/start-editing-selected))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [;; We only get inside childrens of the hovering shape
|
(let [;; We only get inside childrens of the hovering shape
|
||||||
hover-ids (->> @hover-ids (filter (partial cph/is-child? objects id)))
|
hover-ids (->> @hover-ids (filter (partial cph/is-child? objects id)))
|
||||||
selected (get objects (first hover-ids))]
|
selected (get objects (first hover-ids))]
|
||||||
(when (some? selected)
|
(when (some? selected)
|
||||||
(reset! hover selected)
|
(reset! hover selected)
|
||||||
(st/emit! (dw/select-shape (:id selected)))))))))))))
|
(st/emit! (dw/select-shape (:id selected))))))))))))))
|
||||||
|
|
||||||
(defn on-context-menu
|
(defn on-context-menu
|
||||||
[hover hover-ids workspace-read-only?]
|
[hover hover-ids workspace-read-only?]
|
||||||
|
|
|
@ -71,13 +71,18 @@
|
||||||
;; We schedule the event so it fires after `initialize-page` event
|
;; We schedule the event so it fires after `initialize-page` event
|
||||||
(timers/schedule #(st/emit! (dw/initialize-viewport size)))))))
|
(timers/schedule #(st/emit! (dw/initialize-viewport size)))))))
|
||||||
|
|
||||||
(defn setup-cursor [cursor alt? mod? space? panning drawing-tool drawing-path? path-editing? workspace-read-only?]
|
(defn setup-cursor [cursor alt? mod? space? panning drawing-tool drawing-path? path-editing? z? workspace-read-only?]
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps @cursor @alt? @mod? @space? panning drawing-tool drawing-path? path-editing? workspace-read-only?)
|
(mf/deps @cursor @alt? @mod? @space? panning drawing-tool drawing-path? path-editing? z? workspace-read-only?)
|
||||||
(fn []
|
(fn []
|
||||||
(let [show-pen? (or (= drawing-tool :path)
|
(let [show-pen? (or (= drawing-tool :path)
|
||||||
(and drawing-path?
|
(and drawing-path?
|
||||||
(not= drawing-tool :curve)))
|
(not= drawing-tool :curve)))
|
||||||
|
show-zoom? (and @z?
|
||||||
|
(not @space?)
|
||||||
|
(not drawing-path?)
|
||||||
|
(not drawing-tool))
|
||||||
|
|
||||||
new-cursor
|
new-cursor
|
||||||
(cond
|
(cond
|
||||||
(and @mod? @space?) (utils/get-cursor :zoom)
|
(and @mod? @space?) (utils/get-cursor :zoom)
|
||||||
|
@ -86,6 +91,8 @@
|
||||||
(= drawing-tool :frame) (utils/get-cursor :create-artboard)
|
(= drawing-tool :frame) (utils/get-cursor :create-artboard)
|
||||||
(= drawing-tool :rect) (utils/get-cursor :create-rectangle)
|
(= drawing-tool :rect) (utils/get-cursor :create-rectangle)
|
||||||
(= drawing-tool :circle) (utils/get-cursor :create-ellipse)
|
(= drawing-tool :circle) (utils/get-cursor :create-ellipse)
|
||||||
|
(and show-zoom? (not @alt?)) (utils/get-cursor :zoom-in)
|
||||||
|
(and show-zoom? @alt?) (utils/get-cursor :zoom-out)
|
||||||
show-pen? (utils/get-cursor :pen)
|
show-pen? (utils/get-cursor :pen)
|
||||||
(= drawing-tool :curve) (utils/get-cursor :pencil)
|
(= drawing-tool :curve) (utils/get-cursor :pencil)
|
||||||
drawing-tool (utils/get-cursor :create-shape)
|
drawing-tool (utils/get-cursor :create-shape)
|
||||||
|
@ -98,10 +105,11 @@
|
||||||
(when (not= @cursor new-cursor)
|
(when (not= @cursor new-cursor)
|
||||||
(reset! cursor new-cursor))))))
|
(reset! cursor new-cursor))))))
|
||||||
|
|
||||||
(defn setup-keyboard [alt? mod? space?]
|
(defn setup-keyboard [alt? mod? space? z?]
|
||||||
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
(hooks/use-stream ms/keyboard-alt #(reset! alt? %))
|
||||||
(hooks/use-stream ms/keyboard-mod #(reset! mod? %))
|
(hooks/use-stream ms/keyboard-mod #(reset! mod? %))
|
||||||
(hooks/use-stream ms/keyboard-space #(reset! space? %)))
|
(hooks/use-stream ms/keyboard-space #(reset! space? %))
|
||||||
|
(hooks/use-stream ms/keyboard-z #(reset! z? %)))
|
||||||
|
|
||||||
(defn group-empty-space?
|
(defn group-empty-space?
|
||||||
"Given a group `group-id` check if `hover-ids` contains any of its children. If it doesn't means
|
"Given a group `group-id` check if `hover-ids` contains any of its children. If it doesn't means
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
:duplicate cur/duplicate
|
:duplicate cur/duplicate
|
||||||
:zoom cur/zoom
|
:zoom cur/zoom
|
||||||
:zoom-in cur/zoom-in
|
:zoom-in cur/zoom-in
|
||||||
:zooom-out cur/zoom-out
|
:zoom-out cur/zoom-out
|
||||||
cur/pointer-inner))
|
cur/pointer-inner))
|
||||||
|
|
||||||
;; Ensure that the label has always the same font
|
;; Ensure that the label has always the same font
|
||||||
|
|
|
@ -6,13 +6,19 @@
|
||||||
|
|
||||||
(ns app.util.keyboard
|
(ns app.util.keyboard
|
||||||
(:require
|
(:require
|
||||||
[app.config :as cfg]))
|
[app.config :as cfg]
|
||||||
|
[cuerdas.core :as str]))
|
||||||
|
|
||||||
(defn is-key?
|
(defn is-key?
|
||||||
[^string key]
|
[^string key]
|
||||||
(fn [^js e]
|
(fn [^js e]
|
||||||
(= (.-key e) key)))
|
(= (.-key e) key)))
|
||||||
|
|
||||||
|
(defn is-key-ignore-case?
|
||||||
|
[^string key]
|
||||||
|
(fn [^js e]
|
||||||
|
(= (str/upper (.-key e)) (str/upper key))))
|
||||||
|
|
||||||
(defn ^boolean alt?
|
(defn ^boolean alt?
|
||||||
[^js event]
|
[^js event]
|
||||||
(.-altKey event))
|
(.-altKey event))
|
||||||
|
@ -38,6 +44,7 @@
|
||||||
(def esc? (is-key? "Escape"))
|
(def esc? (is-key? "Escape"))
|
||||||
(def enter? (is-key? "Enter"))
|
(def enter? (is-key? "Enter"))
|
||||||
(def space? (is-key? " "))
|
(def space? (is-key? " "))
|
||||||
|
(def z? (is-key-ignore-case? "z"))
|
||||||
(def up-arrow? (is-key? "ArrowUp"))
|
(def up-arrow? (is-key? "ArrowUp"))
|
||||||
(def down-arrow? (is-key? "ArrowDown"))
|
(def down-arrow? (is-key? "ArrowDown"))
|
||||||
(def left-arrow? (is-key? "ArrowLeft"))
|
(def left-arrow? (is-key? "ArrowLeft"))
|
||||||
|
|
|
@ -2559,6 +2559,12 @@ msgstr "Distribute vertically"
|
||||||
msgid "shortcuts.zoom-selected"
|
msgid "shortcuts.zoom-selected"
|
||||||
msgstr "Zoom to selected"
|
msgstr "Zoom to selected"
|
||||||
|
|
||||||
|
msgid "shortcuts.zoom-lense-increase"
|
||||||
|
msgstr "Zoom lense increase"
|
||||||
|
|
||||||
|
msgid "shortcuts.zoom-lense-decrease"
|
||||||
|
msgstr "Zoom lense decrease"
|
||||||
|
|
||||||
#: src/app/main/ui/dashboard/files.cljs
|
#: src/app/main/ui/dashboard/files.cljs
|
||||||
msgid "title.dashboard.files"
|
msgid "title.dashboard.files"
|
||||||
msgstr "%s - Penpot"
|
msgstr "%s - Penpot"
|
||||||
|
|
|
@ -3380,6 +3380,12 @@ msgstr "Pantalla completa"
|
||||||
msgid "workspace.header.zoom-selected"
|
msgid "workspace.header.zoom-selected"
|
||||||
msgstr "Zoom a selección"
|
msgstr "Zoom a selección"
|
||||||
|
|
||||||
|
msgid "shortcuts.zoom-lense-increase"
|
||||||
|
msgstr "Incrementar zoom a objetivo"
|
||||||
|
|
||||||
|
msgid "shortcuts.zoom-lense-decrease"
|
||||||
|
msgstr "Decrementar zoom a objetivo"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/libraries.cljs
|
#: src/app/main/ui/workspace/libraries.cljs
|
||||||
msgid "workspace.libraries.add"
|
msgid "workspace.libraries.add"
|
||||||
msgstr "Añadir"
|
msgstr "Añadir"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue