Merge pull request #6969 from penpot/andy-show-keyboard-distance

 Show distance between layers while moving them with the keyboard
This commit is contained in:
Andrey Antukh 2025-07-29 13:32:53 +02:00 committed by GitHub
commit 6ffbf08826
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 42 additions and 19 deletions

View File

@ -10,6 +10,8 @@
### :sparkles: New features & Enhancements ### :sparkles: New features & Enhancements
- Continuous display of distances between elements when moving a layer with the keyboard [Taiga #1780](https://tree.taiga.io/project/penpot/issue/1780)
### :bug: Bugs fixed ### :bug: Bugs fixed
- Display strokes information in inspect tab [Taiga #11154](https://tree.taiga.io/project/penpot/issue/11154) - Display strokes information in inspect tab [Taiga #11154](https://tree.taiga.io/project/penpot/issue/11154)

View File

@ -142,23 +142,24 @@
[key cb] [key cb]
(fn [event] (fn [event]
(log/debug :msg (str "Shortcut" key)) (log/debug :msg (str "Shortcut" key))
(when (aget event "preventDefault") (when (unchecked-get event "preventDefault")
(.preventDefault event)) (.preventDefault event))
(cb event))) (cb event)))
(defn- bind! (defn- bind!
[shortcuts] [shortcuts]
(let [msbind (fn [command callback type] (let [msbind (fn [command callback type]
(if type (let [command (if (vector? command)
(mousetrap/bind command callback type) (into-array command)
(mousetrap/bind command callback)))] command)]
(if type
(mousetrap/bind command callback type)
(mousetrap/bind command callback))))]
(->> shortcuts (->> shortcuts
(remove #(:disabled (second %))) (remove #(:disabled (second %)))
(run! (fn [[key {:keys [command fn type]}]] (run! (fn [[key {:keys [command fn type]}]]
(let [callback (wrap-cb key fn)] (let [callback (wrap-cb key fn)]
(if (vector? command) (msbind command callback type)))))))
(run! #(msbind % callback type) command)
(msbind command callback type))))))))
(defn- reset! (defn- reset!
([] ([]

View File

@ -213,42 +213,42 @@
:fn #(emit-when-no-readonly (dw/vertical-order-selected :bottom))} :fn #(emit-when-no-readonly (dw/vertical-order-selected :bottom))}
:move-fast-up {:tooltip (ds/shift ds/up-arrow) :move-fast-up {:tooltip (ds/shift ds/up-arrow)
:command "shift+up" :command ["shift+up" "shift+alt+up" "alt+shift+up"]
:subsections [:modify-layers] :subsections [:modify-layers]
:fn #(emit-when-no-readonly (dwt/move-selected :up true))} :fn #(emit-when-no-readonly (dwt/move-selected :up true))}
:move-fast-down {:tooltip (ds/shift ds/down-arrow) :move-fast-down {:tooltip (ds/shift ds/down-arrow)
:command "shift+down" :command ["shift+down" "shift+alt+down" "alt+shift+down"]
:subsections [:modify-layers] :subsections [:modify-layers]
:fn #(emit-when-no-readonly (dwt/move-selected :down true))} :fn #(emit-when-no-readonly (dwt/move-selected :down true))}
:move-fast-right {:tooltip (ds/shift ds/right-arrow) :move-fast-right {:tooltip (ds/shift ds/right-arrow)
:command "shift+right" :command ["shift+right" "shift+alt+right" "alt+shift+right"]
:subsections [:modify-layers] :subsections [:modify-layers]
:fn #(emit-when-no-readonly (dwt/move-selected :right true))} :fn #(emit-when-no-readonly (dwt/move-selected :right true))}
:move-fast-left {:tooltip (ds/shift ds/left-arrow) :move-fast-left {:tooltip (ds/shift ds/left-arrow)
:command "shift+left" :command ["shift+left" "shift+alt+left" "alt+shift+left"]
:subsections [:modify-layers] :subsections [:modify-layers]
:fn #(emit-when-no-readonly (dwt/move-selected :left true))} :fn #(emit-when-no-readonly (dwt/move-selected :left true))}
:move-unit-up {:tooltip ds/up-arrow :move-unit-up {:tooltip ds/up-arrow
:command "up" :command ["up" "alt+up"]
:subsections [:modify-layers] :subsections [:modify-layers]
:fn #(emit-when-no-readonly (dwt/move-selected :up false))} :fn #(emit-when-no-readonly (dwt/move-selected :up false))}
:move-unit-down {:tooltip ds/down-arrow :move-unit-down {:tooltip ds/down-arrow
:command "down" :command ["down" "alt+down"]
:subsections [:modify-layers] :subsections [:modify-layers]
:fn #(emit-when-no-readonly (dwt/move-selected :down false))} :fn #(emit-when-no-readonly (dwt/move-selected :down false))}
:move-unit-left {:tooltip ds/right-arrow :move-unit-left {:tooltip ds/right-arrow
:command "right" :command ["right" "alt+right"]
:subsections [:modify-layers] :subsections [:modify-layers]
:fn #(emit-when-no-readonly (dwt/move-selected :right false))} :fn #(emit-when-no-readonly (dwt/move-selected :right false))}
:move-unit-right {:tooltip ds/left-arrow :move-unit-right {:tooltip ds/left-arrow
:command "left" :command ["left" "alt+left"]
:subsections [:modify-layers] :subsections [:modify-layers]
:fn #(emit-when-no-readonly (dwt/move-selected :left false))} :fn #(emit-when-no-readonly (dwt/move-selected :left false))}

View File

@ -378,7 +378,7 @@
(when (dbg/enabled? :show-export-metadata) (when (dbg/enabled? :show-export-metadata)
[:& use/export-page {:page page}]) [:& use/export-page {:page page}])
;; We need a "real" background shape so layer transforms work properly in firefox ;; We need a "real" background shape so layer transforms work properly in firefox
[:rect {:width (:width vbox 0) [:rect {:width (:width vbox 0)
:height (:height vbox 0) :height (:height vbox 0)
:x (:x vbox 0) :x (:x vbox 0)
@ -387,7 +387,7 @@
[:& (mf/provider ctx/current-vbox) {:value vbox'} [:& (mf/provider ctx/current-vbox) {:value vbox'}
[:& (mf/provider use/include-metadata-ctx) {:value (dbg/enabled? :show-export-metadata)} [:& (mf/provider use/include-metadata-ctx) {:value (dbg/enabled? :show-export-metadata)}
;; Render root shape ;; Render root shape
[:& shapes/root-shape {:key page-id [:& shapes/root-shape {:key page-id
:objects base-objects :objects base-objects
:active-frames @active-frames}]]]] :active-frames @active-frames}]]]]
@ -487,6 +487,26 @@
:hover-shape @measure-hover :hover-shape @measure-hover
:zoom zoom}]) :zoom zoom}])
;; Show distances during movement with ALT
(when (and (= transform :move) @alt? (seq selected-shapes))
[:& msr/measurement
{:bounds vbox
:selected-shapes selected-shapes
:frame selected-frame
:hover-shape @hover
:zoom zoom}])
;; Reactive subscription to duplication relation (safe)
(let [state-var (mf/use-var (resolve 'app.main.store/state))
duplicated-info (get-in @(deref state-var) [:workspace-local :duplicated])]
(when (and (= transform :move) @alt? duplicated-info)
[:g.duplicated-distance
[:& msr/distance-display
{:from (get duplicated-info :selrect-original)
:to (get duplicated-info :selrect-duplicated)
:zoom zoom
:bounds vbox}]]))
(when show-padding? (when show-padding?
[:& mfc/padding-control [:& mfc/padding-control
{:frame first-shape {:frame first-shape

View File

@ -845,8 +845,8 @@ function Mousetrap(targetElement) {
// a callback is added for this key // a callback is added for this key
self._callbacks[info.key] = self._callbacks[info.key] || []; self._callbacks[info.key] = self._callbacks[info.key] || [];
// remove an existing match if there is one // // remove an existing match if there is one
_getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level); // _getMatches(info.key, info.modifiers, {type: info.action}, sequenceName, combination, level);
// add this call back to the array // add this call back to the array
// if it is a sequence put it at the beginning // if it is a sequence put it at the beginning