mirror of
https://github.com/penpot/penpot.git
synced 2025-05-30 05:16:10 +02:00
✨ Shortcuts for paths
This commit is contained in:
parent
6331dff484
commit
65ad46ab38
15 changed files with 320 additions and 116 deletions
|
@ -305,10 +305,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&.is-disabled {
|
&.is-disabled {
|
||||||
opacity: 0.3;
|
cursor: initial;
|
||||||
|
svg {
|
||||||
&:hover svg {
|
fill: $color-gray-20;
|
||||||
fill: initial;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,13 @@
|
||||||
|
|
||||||
(ns app.main.data.shortcuts
|
(ns app.main.data.shortcuts
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.workspace.colors :as mdc]
|
["mousetrap" :as mousetrap]
|
||||||
[app.main.data.workspace.transforms :as dwt]
|
[app.config :as cfg]
|
||||||
[app.main.store :as st]
|
[app.util.logging :as log])
|
||||||
[app.util.dom :as dom]
|
|
||||||
[potok.core :as ptk]
|
|
||||||
[beicon.core :as rx]
|
|
||||||
[app.config :as cfg])
|
|
||||||
(:refer-clojure :exclude [meta]))
|
(:refer-clojure :exclude [meta]))
|
||||||
|
|
||||||
|
(log/set-level! :warn)
|
||||||
|
|
||||||
(def mac-command "\u2318")
|
(def mac-command "\u2318")
|
||||||
(def mac-option "\u2325")
|
(def mac-option "\u2325")
|
||||||
(def mac-delete "\u232B")
|
(def mac-delete "\u232B")
|
||||||
|
@ -46,20 +44,41 @@
|
||||||
[shortcut]
|
[shortcut]
|
||||||
(c-mod (a-mod shortcut)))
|
(c-mod (a-mod shortcut)))
|
||||||
|
|
||||||
(defn bind-shortcuts [shortcuts bind-fn cb-fn]
|
(defn bind-shortcuts
|
||||||
(doseq [[key {:keys [command disabled fn type]}] shortcuts]
|
([shortcuts-config]
|
||||||
(when-not disabled
|
(bind-shortcuts
|
||||||
(if (vector? command)
|
shortcuts-config
|
||||||
(doseq [cmd (seq command)]
|
mousetrap/bind
|
||||||
(bind-fn cmd (cb-fn key fn) type))
|
(fn [key cb]
|
||||||
(bind-fn command (cb-fn key fn) type)))))
|
(fn [event]
|
||||||
|
(log/debug :msg (str "Shortcut" key))
|
||||||
|
(.preventDefault event)
|
||||||
|
(cb event)))))
|
||||||
|
|
||||||
|
([shortcuts-config bind-fn cb-fn]
|
||||||
|
(doseq [[key {:keys [command disabled fn type]}] shortcuts-config]
|
||||||
|
(when-not disabled
|
||||||
|
(if (vector? command)
|
||||||
|
(doseq [cmd (seq command)]
|
||||||
|
(bind-fn cmd (cb-fn key fn) type))
|
||||||
|
(bind-fn command (cb-fn key fn) type))))))
|
||||||
|
|
||||||
|
(defn remove-shortcuts
|
||||||
|
[]
|
||||||
|
(mousetrap/reset))
|
||||||
|
|
||||||
(defn meta [key]
|
(defn meta [key]
|
||||||
(str
|
;; If the key is "+" we need to surround with quotes
|
||||||
(if (cfg/check-platform? :macos)
|
;; otherwise will not be very readable
|
||||||
mac-command
|
(let [key (if (and (not (cfg/check-platform? :macos))
|
||||||
"Ctrl+")
|
(= key "+"))
|
||||||
key))
|
"\"+\""
|
||||||
|
key)]
|
||||||
|
(str
|
||||||
|
(if (cfg/check-platform? :macos)
|
||||||
|
mac-command
|
||||||
|
"Ctrl+")
|
||||||
|
key)))
|
||||||
|
|
||||||
(defn shift [key]
|
(defn shift [key]
|
||||||
(str
|
(str
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
[app.main.data.workspace.path.drawing :as drawing]
|
[app.main.data.workspace.path.drawing :as drawing]
|
||||||
[app.main.data.workspace.path.edition :as edition]
|
[app.main.data.workspace.path.edition :as edition]
|
||||||
[app.main.data.workspace.path.selection :as selection]
|
[app.main.data.workspace.path.selection :as selection]
|
||||||
[app.main.data.workspace.path.tools :as tools]))
|
[app.main.data.workspace.path.tools :as tools]
|
||||||
|
[app.main.data.workspace.path.undo :as undo]))
|
||||||
|
|
||||||
;; Drawing
|
;; Drawing
|
||||||
(d/export drawing/handle-new-shape)
|
(d/export drawing/handle-new-shape)
|
||||||
|
@ -42,3 +43,7 @@
|
||||||
(d/export tools/separate-nodes)
|
(d/export tools/separate-nodes)
|
||||||
(d/export tools/toggle-snap)
|
(d/export tools/toggle-snap)
|
||||||
|
|
||||||
|
;; Undo/redo
|
||||||
|
(d/export undo/undo-path)
|
||||||
|
(d/export undo/redo-path)
|
||||||
|
(d/export undo/merge-head)
|
||||||
|
|
|
@ -113,7 +113,8 @@
|
||||||
(let [id (st/get-path-id state)
|
(let [id (st/get-path-id state)
|
||||||
handler (get-in state [:workspace-local :edit-path id :prev-handler])]
|
handler (get-in state [:workspace-local :edit-path id :prev-handler])]
|
||||||
;; Update the preview because can be outdated after the dragging
|
;; Update the preview because can be outdated after the dragging
|
||||||
(rx/of (preview-next-point handler))))))
|
(rx/of (preview-next-point handler)
|
||||||
|
(undo/merge-head))))))
|
||||||
|
|
||||||
(declare close-path-drag-end)
|
(declare close-path-drag-end)
|
||||||
|
|
||||||
|
|
94
frontend/src/app/main/data/workspace/path/shortcuts.cljs
Normal file
94
frontend/src/app/main/data/workspace/path/shortcuts.cljs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns app.main.data.workspace.path.shortcuts
|
||||||
|
(:require
|
||||||
|
[app.main.data.shortcuts :as ds]
|
||||||
|
[app.main.data.workspace :as dw]
|
||||||
|
[app.main.data.workspace.path :as drp]
|
||||||
|
[app.main.store :as st]
|
||||||
|
[beicon.core :as rx]
|
||||||
|
[potok.core :as ptk]))
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Shortcuts
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;; Shortcuts format https://github.com/ccampbell/mousetrap
|
||||||
|
|
||||||
|
(defn esc-pressed []
|
||||||
|
(ptk/reify :esc-pressed
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state stream]
|
||||||
|
;; Not interrupt when we're editing a path
|
||||||
|
(let [edition-id (or (get-in state [:workspace-drawing :object :id])
|
||||||
|
(get-in state [:workspace-local :edition]))
|
||||||
|
path-edit-mode (get-in state [:workspace-local :edit-path edition-id :edit-mode])]
|
||||||
|
(if-not (= :draw path-edit-mode)
|
||||||
|
(rx/of :interrupt (dw/deselect-all true))
|
||||||
|
(rx/empty))))))
|
||||||
|
|
||||||
|
(def shortcuts
|
||||||
|
{:move-nodes {:tooltip "V"
|
||||||
|
:command "v"
|
||||||
|
:fn #(st/emit! (drp/change-edit-mode :move))}
|
||||||
|
|
||||||
|
:draw-nodes {:tooltip "P"
|
||||||
|
:command "p"
|
||||||
|
:fn #(st/emit! (drp/change-edit-mode :draw))}
|
||||||
|
|
||||||
|
:add-node {:tooltip (ds/meta "+")
|
||||||
|
:command (ds/c-mod "+")
|
||||||
|
:fn #(st/emit! (drp/add-node))}
|
||||||
|
|
||||||
|
:delete-node {:tooltip (ds/supr)
|
||||||
|
:command ["del" "backspace"]
|
||||||
|
:fn #(st/emit! (drp/remove-node))}
|
||||||
|
|
||||||
|
:merge-nodes {:tooltip (ds/meta "J")
|
||||||
|
:command (ds/c-mod "j")
|
||||||
|
:fn #(st/emit! (drp/merge-nodes))}
|
||||||
|
|
||||||
|
:join-nodes {:tooltip (ds/meta-shift "J")
|
||||||
|
:command (ds/c-mod "shift+j")
|
||||||
|
:fn #(st/emit! (drp/join-nodes))}
|
||||||
|
|
||||||
|
:separate-nodes {:tooltip (ds/meta "K")
|
||||||
|
:command (ds/c-mod "k")
|
||||||
|
:fn #(st/emit! (drp/separate-nodes))}
|
||||||
|
|
||||||
|
:make-corner {:tooltip (ds/meta "B")
|
||||||
|
:command (ds/c-mod "b")
|
||||||
|
:fn #(st/emit! (drp/make-corner))}
|
||||||
|
|
||||||
|
:make-curve {:tooltip (ds/meta-shift "B")
|
||||||
|
:command (ds/c-mod "shift+b")
|
||||||
|
:fn #(st/emit! (drp/make-curve))}
|
||||||
|
|
||||||
|
:snap-nodes {:tooltip (ds/meta "'")
|
||||||
|
:command (ds/c-mod "'")
|
||||||
|
:fn #(st/emit! (drp/toggle-snap))}
|
||||||
|
|
||||||
|
:escape {:tooltip (ds/esc)
|
||||||
|
:command "escape"
|
||||||
|
:fn #(st/emit! (esc-pressed))}
|
||||||
|
|
||||||
|
:start-editing {:tooltip (ds/enter)
|
||||||
|
:command "enter"
|
||||||
|
:fn #(st/emit! (dw/start-editing-selected))}
|
||||||
|
|
||||||
|
:undo {:tooltip (ds/meta "Z")
|
||||||
|
:command (ds/c-mod "z")
|
||||||
|
:fn #(st/emit! (drp/undo-path))}
|
||||||
|
|
||||||
|
:redo {:tooltip (ds/meta "Y")
|
||||||
|
:command [(ds/c-mod "shift+z") (ds/c-mod "y")]
|
||||||
|
:fn #(st/emit! (drp/redo-path))}
|
||||||
|
})
|
||||||
|
|
||||||
|
(defn get-tooltip [shortcut]
|
||||||
|
(assert (contains? shortcuts shortcut) (str shortcut))
|
||||||
|
(get-in shortcuts [shortcut :tooltip]))
|
|
@ -72,6 +72,14 @@
|
||||||
(->> ms/mouse-position
|
(->> ms/mouse-position
|
||||||
(rx/map check-path-snap))))
|
(rx/map check-path-snap))))
|
||||||
|
|
||||||
|
(defn get-angle [node handler opposite]
|
||||||
|
(when (and (some? node) (some? handler) (some? opposite))
|
||||||
|
(let [v1 (gpt/to-vec node opposite)
|
||||||
|
v2 (gpt/to-vec node handler)
|
||||||
|
rot-angle (gpt/angle-with-other v1 v2)
|
||||||
|
rot-sign (gpt/angle-sign v1 v2)]
|
||||||
|
[rot-angle rot-sign])))
|
||||||
|
|
||||||
(defn move-handler-stream
|
(defn move-handler-stream
|
||||||
[snap-toggled start-point node handler opposite points]
|
[snap-toggled start-point node handler opposite points]
|
||||||
|
|
||||||
|
@ -79,8 +87,7 @@
|
||||||
ranges (snap/create-ranges points)
|
ranges (snap/create-ranges points)
|
||||||
d-pos (/ snap/snap-path-accuracy zoom)
|
d-pos (/ snap/snap-path-accuracy zoom)
|
||||||
|
|
||||||
initial-angle (gpt/angle-with-other (gpt/to-vec node handler)
|
[initial-angle] (get-angle node handler opposite)
|
||||||
(gpt/to-vec node opposite))
|
|
||||||
|
|
||||||
check-path-snap
|
check-path-snap
|
||||||
(fn [position]
|
(fn [position]
|
||||||
|
@ -88,14 +95,11 @@
|
||||||
(let [delta (gpt/subtract position start-point)
|
(let [delta (gpt/subtract position start-point)
|
||||||
handler (gpt/add handler delta)
|
handler (gpt/add handler delta)
|
||||||
|
|
||||||
v1 (gpt/to-vec node opposite)
|
[rot-angle rot-sign] (get-angle node handler opposite)
|
||||||
v2 (gpt/to-vec node handler)
|
|
||||||
|
|
||||||
rot-angle (gpt/angle-with-other v1 v2)
|
|
||||||
rot-sign (gpt/angle-sign v1 v2)
|
|
||||||
|
|
||||||
snap-opposite-angle?
|
snap-opposite-angle?
|
||||||
(and (or (:alt? position) (> (- 180 initial-angle) 0.1))
|
(and (some? rot-angle)
|
||||||
|
(or (:alt? position) (> (- 180 initial-angle) 0.1))
|
||||||
(<= (- 180 rot-angle) 5))]
|
(<= (- 180 rot-angle) 5))]
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
|
|
|
@ -48,8 +48,8 @@
|
||||||
:prev-handler prev-handler
|
:prev-handler prev-handler
|
||||||
:old-content old-content))))
|
:old-content old-content))))
|
||||||
|
|
||||||
(defn undo []
|
(defn undo-path []
|
||||||
(ptk/reify ::undo
|
(ptk/reify ::undo-path
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [id (st/get-path-id state)
|
(let [id (st/get-path-id state)
|
||||||
|
@ -65,10 +65,10 @@
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(rx/of (changes/save-path-content)))))
|
(rx/of (changes/save-path-content {:preserve-move-to true})))))
|
||||||
|
|
||||||
(defn redo []
|
(defn redo-path []
|
||||||
(ptk/reify ::redo
|
(ptk/reify ::redo-path
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [id (st/get-path-id state)
|
(let [id (st/get-path-id state)
|
||||||
|
@ -85,6 +85,23 @@
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(rx/of (changes/save-path-content)))))
|
(rx/of (changes/save-path-content)))))
|
||||||
|
|
||||||
|
(defn merge-head
|
||||||
|
"Joins the head with the previous undo in one. This is done so when the user changes a
|
||||||
|
node handlers after adding it the undo merges both in one operation only"
|
||||||
|
[]
|
||||||
|
(ptk/reify ::add-undo-entry
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [id (st/get-path-id state)
|
||||||
|
entry (make-entry state)
|
||||||
|
stack (get-in state [:workspace-local :edit-path id :undo-stack])
|
||||||
|
head (u/peek stack)
|
||||||
|
stack (-> stack (u/undo) (u/fixup head))]
|
||||||
|
(-> state
|
||||||
|
(d/assoc-in-when
|
||||||
|
[:workspace-local :edit-path id :undo-stack]
|
||||||
|
stack))))))
|
||||||
|
|
||||||
(defn add-undo-entry []
|
(defn add-undo-entry []
|
||||||
(ptk/reify ::add-undo-entry
|
(ptk/reify ::add-undo-entry
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
|
@ -136,20 +153,10 @@
|
||||||
(rx/filter stop-undo?)
|
(rx/filter stop-undo?)
|
||||||
(rx/take 1))]
|
(rx/take 1))]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(->> (rx/merge
|
(->> (rx/from-atom path-content-ref {:emit-current-value? true})
|
||||||
(->> (rx/from-atom path-content-ref {:emit-current-value? true})
|
(rx/take-until stop-undo-stream)
|
||||||
(rx/filter (comp not nil?))
|
(rx/filter (comp not nil?))
|
||||||
(rx/map #(add-undo-entry)))
|
(rx/map #(add-undo-entry)))
|
||||||
|
|
||||||
(->> stream
|
|
||||||
(rx/filter undo-event?)
|
|
||||||
(rx/map #(undo)))
|
|
||||||
|
|
||||||
(->> stream
|
|
||||||
(rx/filter redo-event?)
|
|
||||||
(rx/map #(redo))))
|
|
||||||
|
|
||||||
(rx/take-until stop-undo-stream))
|
|
||||||
|
|
||||||
(rx/of (end-path-undo))))))))))
|
(rx/of (end-path-undo))))))))))
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,9 @@
|
||||||
|
|
||||||
(ns app.main.data.workspace.shortcuts
|
(ns app.main.data.workspace.shortcuts
|
||||||
(:require
|
(:require
|
||||||
[app.config :as cfg]
|
|
||||||
[app.main.data.workspace.colors :as mdc]
|
|
||||||
[app.main.data.shortcuts :as ds]
|
[app.main.data.shortcuts :as ds]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
[app.main.data.workspace.colors :as mdc]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.drawing :as dwd]
|
[app.main.data.workspace.drawing :as dwd]
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
|
@ -17,28 +16,13 @@
|
||||||
[app.main.data.workspace.transforms :as dwt]
|
[app.main.data.workspace.transforms :as dwt]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[beicon.core :as rx]
|
|
||||||
[potok.core :as ptk]))
|
[potok.core :as ptk]))
|
||||||
|
|
||||||
;; \u2318P
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Shortcuts
|
;; Shortcuts
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
;; Shortcuts impl https://github.com/ccampbell/mousetrap
|
;; Shortcuts format https://github.com/ccampbell/mousetrap
|
||||||
|
|
||||||
(defn esc-pressed []
|
|
||||||
(ptk/reify :esc-pressed
|
|
||||||
ptk/WatchEvent
|
|
||||||
(watch [_ state stream]
|
|
||||||
;; Not interrupt when we're editing a path
|
|
||||||
(let [edition-id (or (get-in state [:workspace-drawing :object :id])
|
|
||||||
(get-in state [:workspace-local :edition]))
|
|
||||||
path-edit-mode (get-in state [:workspace-local :edit-path edition-id :edit-mode])]
|
|
||||||
(if-not (= :draw path-edit-mode)
|
|
||||||
(rx/of :interrupt (dw/deselect-all true))
|
|
||||||
(rx/empty))))))
|
|
||||||
|
|
||||||
(def shortcuts
|
(def shortcuts
|
||||||
{:toggle-layers {:tooltip (ds/alt "L")
|
{:toggle-layers {:tooltip (ds/alt "L")
|
||||||
|
@ -252,7 +236,7 @@
|
||||||
|
|
||||||
:escape {:tooltip (ds/esc)
|
:escape {:tooltip (ds/esc)
|
||||||
:command "escape"
|
:command "escape"
|
||||||
:fn #(st/emit! (esc-pressed))}
|
:fn #(st/emit! :interrupt (dw/deselect-all true))}
|
||||||
|
|
||||||
:start-editing {:tooltip (ds/enter)
|
:start-editing {:tooltip (ds/enter)
|
||||||
:command "enter"
|
:command "enter"
|
||||||
|
|
|
@ -7,9 +7,8 @@
|
||||||
(ns app.main.ui.hooks
|
(ns app.main.ui.hooks
|
||||||
"A collection of general purpose react hooks."
|
"A collection of general purpose react hooks."
|
||||||
(:require
|
(:require
|
||||||
["mousetrap" :as mousetrap]
|
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.main.data.shortcuts :refer [bind-shortcuts]]
|
[app.main.data.shortcuts :as dsc]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[app.util.dom.dnd :as dnd]
|
[app.util.dom.dnd :as dnd]
|
||||||
|
@ -39,16 +38,8 @@
|
||||||
[shortcuts]
|
[shortcuts]
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(fn []
|
(fn []
|
||||||
(bind-shortcuts
|
(dsc/bind-shortcuts shortcuts)
|
||||||
shortcuts
|
(fn [] (dsc/remove-shortcuts)))))
|
||||||
mousetrap/bind
|
|
||||||
(fn [key cb]
|
|
||||||
(fn [event]
|
|
||||||
(log/debug :msg (str "Shortcut" key))
|
|
||||||
(.preventDefault event)
|
|
||||||
(cb event))))
|
|
||||||
(fn [] (mousetrap/reset))))
|
|
||||||
nil)
|
|
||||||
|
|
||||||
(defn invisible-image
|
(defn invisible-image
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
[app.main.data.history :as udh]
|
[app.main.data.history :as udh]
|
||||||
[app.main.data.messages :as dm]
|
[app.main.data.messages :as dm]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.shortcuts :as sc]
|
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.streams :as ms]
|
[app.main.streams :as ms]
|
||||||
|
@ -21,13 +20,13 @@
|
||||||
[app.main.ui.workspace.colorpalette :refer [colorpalette]]
|
[app.main.ui.workspace.colorpalette :refer [colorpalette]]
|
||||||
[app.main.ui.workspace.colorpicker]
|
[app.main.ui.workspace.colorpicker]
|
||||||
[app.main.ui.workspace.context-menu :refer [context-menu]]
|
[app.main.ui.workspace.context-menu :refer [context-menu]]
|
||||||
|
[app.main.ui.workspace.coordinates :as coordinates]
|
||||||
[app.main.ui.workspace.header :refer [header]]
|
[app.main.ui.workspace.header :refer [header]]
|
||||||
[app.main.ui.workspace.left-toolbar :refer [left-toolbar]]
|
[app.main.ui.workspace.left-toolbar :refer [left-toolbar]]
|
||||||
[app.main.ui.workspace.libraries]
|
[app.main.ui.workspace.libraries]
|
||||||
[app.main.ui.workspace.rules :refer [horizontal-rule vertical-rule]]
|
[app.main.ui.workspace.rules :refer [horizontal-rule vertical-rule]]
|
||||||
[app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]]
|
[app.main.ui.workspace.sidebar :refer [left-sidebar right-sidebar]]
|
||||||
[app.main.ui.workspace.viewport :refer [viewport]]
|
[app.main.ui.workspace.viewport :refer [viewport]]
|
||||||
[app.main.ui.workspace.coordinates :as coordinates]
|
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.keyboard :as kbd]
|
[app.util.keyboard :as kbd]
|
||||||
|
@ -114,30 +113,29 @@
|
||||||
(mf/defc workspace
|
(mf/defc workspace
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [project-id file-id page-id layout-name] :as props}]
|
[{:keys [project-id file-id page-id layout-name] :as props}]
|
||||||
(mf/use-effect
|
|
||||||
(mf/deps layout-name)
|
|
||||||
#(st/emit! (dw/initialize-layout layout-name)))
|
|
||||||
|
|
||||||
(mf/use-effect
|
|
||||||
(mf/deps project-id file-id)
|
|
||||||
(fn []
|
|
||||||
(st/emit! (dw/initialize-file project-id file-id))
|
|
||||||
(st/emitf (dw/finalize-file project-id file-id))))
|
|
||||||
|
|
||||||
(mf/use-effect
|
|
||||||
(fn []
|
|
||||||
;; Close any non-modal dialog that may be still open
|
|
||||||
(st/emitf dm/hide)))
|
|
||||||
|
|
||||||
(hooks/use-shortcuts sc/shortcuts)
|
|
||||||
|
|
||||||
(let [file (mf/deref refs/workspace-file)
|
(let [file (mf/deref refs/workspace-file)
|
||||||
project (mf/deref refs/workspace-project)
|
project (mf/deref refs/workspace-project)
|
||||||
layout (mf/deref refs/workspace-layout)]
|
layout (mf/deref refs/workspace-layout)]
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/use-effect
|
||||||
(mf/deps file)
|
(mf/deps layout-name)
|
||||||
#(dom/set-html-title (tr "title.workspace" (:name file))))
|
#(st/emit! (dw/initialize-layout layout-name)))
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps project-id file-id)
|
||||||
|
(fn []
|
||||||
|
(st/emit! (dw/initialize-file project-id file-id))
|
||||||
|
(st/emitf (dw/finalize-file project-id file-id))))
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(fn []
|
||||||
|
;; Close any non-modal dialog that may be still open
|
||||||
|
(st/emitf dm/hide)))
|
||||||
|
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps file)
|
||||||
|
#(dom/set-html-title (tr "title.workspace" (:name file))))
|
||||||
|
|
||||||
[:& (mf/provider ctx/current-file-id) {:value (:id file)}
|
[:& (mf/provider ctx/current-file-id) {:value (:id file)}
|
||||||
[:& (mf/provider ctx/current-team-id) {:value (:team-id project)}
|
[:& (mf/provider ctx/current-team-id) {:value (:team-id project)}
|
||||||
|
|
|
@ -143,6 +143,7 @@
|
||||||
(hooks/setup-keyboard alt? ctrl?)
|
(hooks/setup-keyboard alt? ctrl?)
|
||||||
(hooks/setup-hover-shapes page-id move-stream selected objects transform selected ctrl? hover hover-ids)
|
(hooks/setup-hover-shapes page-id move-stream selected objects transform selected ctrl? hover hover-ids)
|
||||||
(hooks/setup-viewport-modifiers modifiers selected objects render-ref)
|
(hooks/setup-viewport-modifiers modifiers selected objects render-ref)
|
||||||
|
(hooks/setup-shortcuts path-editing? drawing-path?)
|
||||||
|
|
||||||
[:div.viewport
|
[:div.viewport
|
||||||
[:div.viewport-overlays
|
[:div.viewport-overlays
|
||||||
|
|
|
@ -9,7 +9,10 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
|
[app.main.data.shortcuts :as dsc]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
|
[app.main.data.workspace.path.shortcuts :as psc]
|
||||||
|
[app.main.data.workspace.shortcuts :as wsc]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.streams :as ms]
|
[app.main.streams :as ms]
|
||||||
[app.main.ui.hooks :as hooks]
|
[app.main.ui.hooks :as hooks]
|
||||||
|
@ -148,3 +151,15 @@
|
||||||
(if modifiers
|
(if modifiers
|
||||||
(utils/update-transform render-node roots modifiers)
|
(utils/update-transform render-node roots modifiers)
|
||||||
(utils/remove-transform render-node roots))))))
|
(utils/remove-transform render-node roots))))))
|
||||||
|
|
||||||
|
(defn setup-shortcuts [path-editing? drawing-path?]
|
||||||
|
(mf/use-effect
|
||||||
|
(mf/deps path-editing? drawing-path?)
|
||||||
|
(fn []
|
||||||
|
(cond
|
||||||
|
(or drawing-path? path-editing?)
|
||||||
|
(dsc/bind-shortcuts psc/shortcuts)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(dsc/bind-shortcuts wsc/shortcuts))
|
||||||
|
dsc/remove-shortcuts)))
|
||||||
|
|
|
@ -8,10 +8,12 @@
|
||||||
(:require
|
(:require
|
||||||
[app.main.data.workspace.path :as drp]
|
[app.main.data.workspace.path :as drp]
|
||||||
[app.main.data.workspace.path.helpers :as wph]
|
[app.main.data.workspace.path.helpers :as wph]
|
||||||
|
[app.main.data.workspace.path.shortcuts :as sc]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.icons :as i]
|
[app.main.ui.icons :as i]
|
||||||
[app.main.ui.workspace.shapes.path.common :as pc]
|
[app.main.ui.workspace.shapes.path.common :as pc]
|
||||||
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
[app.util.path.tools :as upt]
|
[app.util.path.tools :as upt]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
|
@ -106,65 +108,75 @@
|
||||||
[:div.viewport-actions-group
|
[:div.viewport-actions-group
|
||||||
|
|
||||||
;; Draw Mode
|
;; Draw Mode
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when (= edit-mode :draw) "is-toggled")
|
{:class (when (= edit-mode :draw) "is-toggled")
|
||||||
|
:alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes))
|
||||||
:on-click on-select-draw-mode}
|
:on-click on-select-draw-mode}
|
||||||
i/pen]
|
i/pen]
|
||||||
|
|
||||||
;; Edit mode
|
;; Edit mode
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when (= edit-mode :move) "is-toggled")
|
{:class (when (= edit-mode :move) "is-toggled")
|
||||||
|
:alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes))
|
||||||
:on-click on-select-edit-mode}
|
:on-click on-select-edit-mode}
|
||||||
i/pointer-inner]]
|
i/pointer-inner]]
|
||||||
|
|
||||||
[:div.viewport-actions-group
|
[:div.viewport-actions-group
|
||||||
;; Add Node
|
;; Add Node
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when-not (:add-node enabled-buttons) "is-disabled")
|
{:class (when-not (:add-node enabled-buttons) "is-disabled")
|
||||||
|
:alt (tr "workspace.path.actions.add-node" (sc/get-tooltip :add-node))
|
||||||
:on-click on-add-node}
|
:on-click on-add-node}
|
||||||
i/nodes-add]
|
i/nodes-add]
|
||||||
|
|
||||||
;; Remove node
|
;; Remove node
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when-not (:remove-node enabled-buttons) "is-disabled")
|
{:class (when-not (:remove-node enabled-buttons) "is-disabled")
|
||||||
|
:alt (tr "workspace.path.actions.delete-node" (sc/get-tooltip :delete-node))
|
||||||
:on-click on-remove-node}
|
:on-click on-remove-node}
|
||||||
i/nodes-remove]]
|
i/nodes-remove]]
|
||||||
|
|
||||||
[:div.viewport-actions-group
|
[:div.viewport-actions-group
|
||||||
;; Merge Nodes
|
;; Merge Nodes
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when-not (:merge-nodes enabled-buttons) "is-disabled")
|
{:class (when-not (:merge-nodes enabled-buttons) "is-disabled")
|
||||||
|
:alt (tr "workspace.path.actions.merge-nodes" (sc/get-tooltip :merge-nodes))
|
||||||
:on-click on-merge-nodes}
|
:on-click on-merge-nodes}
|
||||||
i/nodes-merge]
|
i/nodes-merge]
|
||||||
|
|
||||||
;; Join Nodes
|
;; Join Nodes
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when-not (:join-nodes enabled-buttons) "is-disabled")
|
{:class (when-not (:join-nodes enabled-buttons) "is-disabled")
|
||||||
|
:alt (tr "workspace.path.actions.join-nodes" (sc/get-tooltip :join-nodes))
|
||||||
:on-click on-join-nodes}
|
:on-click on-join-nodes}
|
||||||
i/nodes-join]
|
i/nodes-join]
|
||||||
|
|
||||||
;; Separate Nodes
|
;; Separate Nodes
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when-not (:separate-nodes enabled-buttons) "is-disabled")
|
{:class (when-not (:separate-nodes enabled-buttons) "is-disabled")
|
||||||
|
:alt (tr "workspace.path.actions.separate-nodes" (sc/get-tooltip :separate-nodes))
|
||||||
:on-click on-separate-nodes}
|
:on-click on-separate-nodes}
|
||||||
i/nodes-separate]]
|
i/nodes-separate]]
|
||||||
|
|
||||||
;; Make Corner
|
;; Make Corner
|
||||||
[:div.viewport-actions-group
|
[:div.viewport-actions-group
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when-not (:make-corner enabled-buttons) "is-disabled")
|
{:class (when-not (:make-corner enabled-buttons) "is-disabled")
|
||||||
|
:alt (tr "workspace.path.actions.make-corner" (sc/get-tooltip :make-corner))
|
||||||
:on-click on-make-corner}
|
:on-click on-make-corner}
|
||||||
i/nodes-corner]
|
i/nodes-corner]
|
||||||
|
|
||||||
;; Make Curve
|
;; Make Curve
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when-not (:make-curve enabled-buttons) "is-disabled")
|
{:class (when-not (:make-curve enabled-buttons) "is-disabled")
|
||||||
|
:alt (tr "workspace.path.actions.make-curve" (sc/get-tooltip :make-curve))
|
||||||
:on-click on-make-curve}
|
:on-click on-make-curve}
|
||||||
i/nodes-curve]]
|
i/nodes-curve]]
|
||||||
|
|
||||||
;; Toggle snap
|
;; Toggle snap
|
||||||
[:div.viewport-actions-group
|
[:div.viewport-actions-group
|
||||||
[:div.viewport-actions-entry
|
[:div.viewport-actions-entry.tooltip.tooltip-bottom
|
||||||
{:class (when snap-toggled "is-toggled")
|
{:class (when snap-toggled "is-toggled")
|
||||||
|
:alt (tr "workspace.path.actions.snap-nodes" (sc/get-tooltip :snap-nodes))
|
||||||
:on-click on-toggle-snap}
|
:on-click on-toggle-snap}
|
||||||
i/nodes-snap]]]))
|
i/nodes-snap]]]))
|
||||||
|
|
|
@ -1,11 +1,25 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR Free Software Foundation, Inc.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Language: en\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"PO-Revision-Date: 2021-04-22 13:43+0200\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=iso-8859-1\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
||||||
|
|
||||||
|
# ~ msgid ""
|
||||||
|
# ~ msgstr ""
|
||||||
|
# ~ "Language: en\n"
|
||||||
|
# ~ "MIME-Version: 1.0\n"
|
||||||
|
# ~ "Content-Type: text/plain; charset=utf-8\n"
|
||||||
|
# ~ "Content-Transfer-Encoding: 8bit\n"
|
||||||
|
# ~ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
#: src/app/main/ui/auth/register.cljs
|
#: src/app/main/ui/auth/register.cljs
|
||||||
msgid "auth.already-have-account"
|
msgid "auth.already-have-account"
|
||||||
msgstr "Already have an account?"
|
msgstr "Already have an account?"
|
||||||
|
@ -2169,6 +2183,36 @@ msgstr "Vertical align"
|
||||||
msgid "workspace.options.use-play-button"
|
msgid "workspace.options.use-play-button"
|
||||||
msgstr "Use the play button at the header to run the prototype view."
|
msgstr "Use the play button at the header to run the prototype view."
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.add-node"
|
||||||
|
msgstr "Add node (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.delete-node"
|
||||||
|
msgstr "Delete node (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.draw-nodes"
|
||||||
|
msgstr "Draw nodes (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.join-nodes"
|
||||||
|
msgstr "Join nodes (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.make-corner"
|
||||||
|
msgstr "To corner (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.make-curve"
|
||||||
|
msgstr "To curve (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.merge-nodes"
|
||||||
|
msgstr "Merge nodes (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.move-nodes"
|
||||||
|
msgstr "Move nodes (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.separate-nodes"
|
||||||
|
msgstr "Separate nodes (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.snap-nodes"
|
||||||
|
msgstr "Snap nodes (%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/context_menu.cljs
|
#: src/app/main/ui/workspace/context_menu.cljs
|
||||||
msgid "workspace.shape.menu.back"
|
msgid "workspace.shape.menu.back"
|
||||||
msgstr "Send to back"
|
msgstr "Send to back"
|
||||||
|
|
|
@ -2153,6 +2153,36 @@ msgstr "Alineación vertical"
|
||||||
msgid "workspace.options.use-play-button"
|
msgid "workspace.options.use-play-button"
|
||||||
msgstr "Usa el botón de play de la cabecera para arrancar la vista de prototipo."
|
msgstr "Usa el botón de play de la cabecera para arrancar la vista de prototipo."
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.add-node"
|
||||||
|
msgstr "Añadir nodo (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.delete-node"
|
||||||
|
msgstr "Borrar nodos (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.draw-nodes"
|
||||||
|
msgstr "Dibujar nodos (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.join-nodes"
|
||||||
|
msgstr "Unir nodos (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.make-corner"
|
||||||
|
msgstr "Convertir en esquina (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.make-curve"
|
||||||
|
msgstr "Convertir en curva (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.merge-nodes"
|
||||||
|
msgstr "Fusionar nodos (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.move-nodes"
|
||||||
|
msgstr "Mover nodes (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.separate-nodes"
|
||||||
|
msgstr "Separar nodos (%s)"
|
||||||
|
|
||||||
|
msgid "workspace.path.actions.snap-nodes"
|
||||||
|
msgstr "Alinear nodos (%s)"
|
||||||
|
|
||||||
#: src/app/main/ui/workspace/context_menu.cljs
|
#: src/app/main/ui/workspace/context_menu.cljs
|
||||||
msgid "workspace.shape.menu.back"
|
msgid "workspace.shape.menu.back"
|
||||||
msgstr "Enviar al fondo"
|
msgstr "Enviar al fondo"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue