mirror of
https://github.com/penpot/penpot.git
synced 2025-01-10 08:50:57 -05:00
✨ Apply text format shortcuts to several layers (even inside groups)
This commit is contained in:
parent
21fc9289a6
commit
d7d6166232
1 changed files with 109 additions and 61 deletions
|
@ -9,6 +9,7 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.main.data.shortcuts :as ds]
|
[app.main.data.shortcuts :as ds]
|
||||||
[app.main.data.workspace.texts :as dwt]
|
[app.main.data.workspace.texts :as dwt]
|
||||||
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.fonts :as fonts]
|
[app.main.fonts :as fonts]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
@ -20,6 +21,12 @@
|
||||||
|
|
||||||
;; Shortcuts format https://github.com/ccampbell/mousetrap
|
;; Shortcuts format https://github.com/ccampbell/mousetrap
|
||||||
|
|
||||||
|
(defn- is-bold? [variant-id]
|
||||||
|
(some #(str/includes? variant-id %) ["bold" "black" "700"]))
|
||||||
|
|
||||||
|
(defn- is-italic? [variant-id]
|
||||||
|
(some #(str/includes? variant-id %) ["italic" "cursive"]))
|
||||||
|
|
||||||
(defn- generate-variant-props
|
(defn- generate-variant-props
|
||||||
[text-values variant-id]
|
[text-values variant-id]
|
||||||
(let [first-intersection (fn [list1 list2] (first (filter (set list1) list2)))
|
(let [first-intersection (fn [list1 list2] (first (filter (set list1) list2)))
|
||||||
|
@ -50,8 +57,6 @@
|
||||||
["700italic" "700cursive" "bolditalic" "blackitalic" "boldcursive" "blackcursive"]
|
["700italic" "700cursive" "bolditalic" "blackitalic" "boldcursive" "blackcursive"]
|
||||||
:else
|
:else
|
||||||
["bolditalic" "700italic" "blackitalic" "boldcursive" "700cursive" "blackcursive"])
|
["bolditalic" "700italic" "blackitalic" "boldcursive" "700cursive" "blackcursive"])
|
||||||
is-bold? (fn [variant-id] (some #(str/includes? variant-id %) bold-options))
|
|
||||||
is-italic? (fn [variant-id] (some #(str/includes? variant-id %) italic-options))
|
|
||||||
font-id (:font-id text-values)
|
font-id (:font-id text-values)
|
||||||
fonts (deref fonts/fontsdb)
|
fonts (deref fonts/fontsdb)
|
||||||
font (get fonts font-id)
|
font (get fonts font-id)
|
||||||
|
@ -62,57 +67,68 @@
|
||||||
choose-bold-italic (fn [] (or (first-intersection variants bold-italic-options) (choose-bold)))
|
choose-bold-italic (fn [] (or (first-intersection variants bold-italic-options) (choose-bold)))
|
||||||
choose-italic-bold (fn [] (or (first-intersection variants bold-italic-options) (choose-italic)))
|
choose-italic-bold (fn [] (or (first-intersection variants bold-italic-options) (choose-italic)))
|
||||||
|
|
||||||
new-variant (let [toggle-bold? (= variant-id "bold")
|
new-variant (let [bold? (is-bold? current-variant)
|
||||||
toggle-italic? (= variant-id "italic")
|
italic? (is-italic? current-variant)
|
||||||
bold? (is-bold? current-variant)
|
add-bold? (and (not bold?)
|
||||||
italic? (is-italic? current-variant)]
|
(or (= variant-id "add-bold")
|
||||||
|
(= variant-id "toggle-bold")))
|
||||||
|
remove-bold? (and bold?
|
||||||
|
(or (= variant-id "remove-bold")
|
||||||
|
(= variant-id "toggle-bold")))
|
||||||
|
add-italic? (and (not italic?)
|
||||||
|
(or (= variant-id "add-italic")
|
||||||
|
(= variant-id "toggle-italic")))
|
||||||
|
remove-italic? (and italic?
|
||||||
|
(or (= variant-id "remove-italic")
|
||||||
|
(= variant-id "toggle-italic")))]
|
||||||
(cond
|
(cond
|
||||||
(and toggle-bold? bold? italic?) ;; it is bold+italic, set it to italic
|
(and add-bold? italic?) ;; it is italic, set it to bold+italic
|
||||||
(choose-italic)
|
|
||||||
|
|
||||||
(and toggle-bold? bold? (not italic?)) ;; it is bold, set it to regular
|
|
||||||
(choose-regular)
|
|
||||||
|
|
||||||
(and toggle-bold? (not bold?) italic?) ;; it is italic, set it to bold+italic
|
|
||||||
(choose-bold-italic)
|
(choose-bold-italic)
|
||||||
|
(and add-bold? (not italic?)) ;; it is regular, set it to bold
|
||||||
(and toggle-bold? (not bold?) (not italic?)) ;; it is regular, set it to bold
|
|
||||||
(choose-bold)
|
(choose-bold)
|
||||||
|
(and remove-bold? italic?) ;; it is bold+italic, set it to italic
|
||||||
(and toggle-italic? bold? italic?) ;; it is bold+italic, set it to bold
|
(choose-italic)
|
||||||
(choose-bold)
|
(and remove-bold? (not italic?)) ;; it is bold set it to regular
|
||||||
|
|
||||||
(and toggle-italic? bold? (not italic?)) ;; it is bold, set it to italic+bold
|
|
||||||
(choose-italic-bold)
|
|
||||||
|
|
||||||
(and toggle-italic? (not bold?) italic?) ;; it is italic, set it to regular
|
|
||||||
(choose-regular)
|
(choose-regular)
|
||||||
|
(and add-italic? bold?) ;; it is bold, set it to italic+bold
|
||||||
|
(choose-italic-bold)
|
||||||
|
(and add-italic? (not bold?)) ;; it is regular, set it to italic
|
||||||
|
(choose-italic)
|
||||||
|
(and remove-italic? bold?) ;; it is bold+italic, set it to bold
|
||||||
|
(choose-bold)
|
||||||
|
(and remove-italic? (not bold?)) ;; it is italic, set it to regular
|
||||||
|
(choose-regular)))
|
||||||
|
|
||||||
(and toggle-italic? (not bold?) (not italic?)) ;; it is regular, set it to italic
|
new-weight (when new-variant
|
||||||
(choose-italic)))
|
(->> (:variants font)
|
||||||
|
(filter #(= (:id %) new-variant))
|
||||||
|
first
|
||||||
|
:weight))]
|
||||||
|
(when new-variant
|
||||||
|
{:font-variant-id new-variant,
|
||||||
|
:font-weight new-weight})))
|
||||||
|
|
||||||
new-weight (->> (:variants font)
|
|
||||||
(filter #(= (:id %) new-variant))
|
(defn calculate-text-values
|
||||||
first
|
[shape]
|
||||||
:weight)]
|
(let [state-map (deref refs/workspace-editor-state)
|
||||||
{:font-variant-id new-variant,
|
editor-state (get state-map (:id shape))]
|
||||||
:font-weight new-weight}))
|
(d/merge
|
||||||
|
(dwt/current-root-values
|
||||||
|
{:shape shape
|
||||||
|
:attrs dwt/root-attrs})
|
||||||
|
(dwt/current-paragraph-values
|
||||||
|
{:editor-state editor-state
|
||||||
|
:shape shape
|
||||||
|
:attrs dwt/paragraph-attrs})
|
||||||
|
(dwt/current-text-values
|
||||||
|
{:editor-state editor-state
|
||||||
|
:shape shape
|
||||||
|
:attrs dwt/text-attrs}))))
|
||||||
|
|
||||||
(defn- update-attrs [shape props]
|
(defn- update-attrs [shape props]
|
||||||
(let [state-map (deref refs/workspace-editor-state)
|
(let [
|
||||||
editor-state (get state-map (:id shape))
|
text-values (calculate-text-values shape)
|
||||||
text-values (d/merge
|
|
||||||
(dwt/current-root-values
|
|
||||||
{:shape shape
|
|
||||||
:attrs dwt/root-attrs})
|
|
||||||
(dwt/current-paragraph-values
|
|
||||||
{:editor-state editor-state
|
|
||||||
:shape shape
|
|
||||||
:attrs dwt/paragraph-attrs})
|
|
||||||
(dwt/current-text-values
|
|
||||||
{:editor-state editor-state
|
|
||||||
:shape shape
|
|
||||||
:attrs dwt/text-attrs}))
|
|
||||||
font-size (d/parse-double (:font-size text-values))
|
font-size (d/parse-double (:font-size text-values))
|
||||||
line-height (d/parse-double (:line-height text-values))
|
line-height (d/parse-double (:line-height text-values))
|
||||||
letter-spacing (d/parse-double (:letter-spacing text-values))
|
letter-spacing (d/parse-double (:letter-spacing text-values))
|
||||||
|
@ -129,29 +145,61 @@
|
||||||
{:letter-spacing (str (+ letter-spacing 0.1))}
|
{:letter-spacing (str (+ letter-spacing 0.1))}
|
||||||
(:letter-spacing-dec props)
|
(:letter-spacing-dec props)
|
||||||
{:letter-spacing (str (- letter-spacing 0.1))}
|
{:letter-spacing (str (- letter-spacing 0.1))}
|
||||||
(= (:text-decoration props) "underline") ;;toggle
|
(= (:text-decoration props) "toggle-underline") ;;toggle
|
||||||
(if (= (:text-decoration text-values) "underline")
|
(if (= (:text-decoration text-values) "underline")
|
||||||
{:text-decoration "none"}
|
{:text-decoration "none"}
|
||||||
props)
|
{:text-decoration "underline"})
|
||||||
(= (:text-decoration props) "line-through") ;;toggle
|
(= (:text-decoration props) "toggle-line-through") ;;toggle
|
||||||
(if (= (:text-decoration text-values) "line-through")
|
(if (= (:text-decoration text-values) "line-through")
|
||||||
{:text-decoration "none"}
|
{:text-decoration "none"}
|
||||||
props)
|
{:text-decoration "line-through"})
|
||||||
(:font-variant-id props)
|
(:font-variant-id props)
|
||||||
(generate-variant-props text-values (:font-variant-id props))
|
(generate-variant-props text-values (:font-variant-id props))
|
||||||
:else props)]
|
:else props)]
|
||||||
|
|
||||||
(when shape
|
(when (and shape props)
|
||||||
(st/emit! (dwt/update-attrs (:id shape) props)))))
|
(st/emit! (dwt/update-attrs (:id shape) props)))))
|
||||||
|
|
||||||
|
(defn blend-props
|
||||||
|
[shapes props]
|
||||||
|
(let [text-values (map calculate-text-values shapes)
|
||||||
|
all-underline? (every? #(= (:text-decoration %) "underline") text-values)
|
||||||
|
all-line-through? (every? #(= (:text-decoration %) "line-through") text-values)
|
||||||
|
all-bold? (every? #(is-bold? (:font-variant-id %)) text-values)
|
||||||
|
all-italic? (every? #(is-italic? (:font-variant-id %)) text-values)
|
||||||
|
]
|
||||||
|
(cond
|
||||||
|
(= (:text-decoration props) "toggle-underline")
|
||||||
|
(if all-underline?
|
||||||
|
{:text-decoration "none"}
|
||||||
|
{:text-decoration "underline"})
|
||||||
|
(= (:text-decoration props) "toggle-line-through")
|
||||||
|
(if all-line-through?
|
||||||
|
{:text-decoration "none"}
|
||||||
|
{:text-decoration "line-through"})
|
||||||
|
(= (:font-variant-id props) "toggle-bold")
|
||||||
|
(if all-bold?
|
||||||
|
{:font-variant-id "remove-bold"}
|
||||||
|
{:font-variant-id "add-bold"})
|
||||||
|
(= (:font-variant-id props) "toggle-italic")
|
||||||
|
(if all-italic?
|
||||||
|
{:font-variant-id "remove-italic"}
|
||||||
|
{:font-variant-id "add-italic"})
|
||||||
|
:else
|
||||||
|
props)))
|
||||||
|
|
||||||
(defn- update-attrs-when-no-readonly [props]
|
(defn- update-attrs-when-no-readonly [props]
|
||||||
(let [read-only? (deref refs/workspace-read-only?)
|
(let [undo-id (js/Symbol)
|
||||||
shapes (deref refs/selected-objects)
|
read-only? (deref refs/workspace-read-only?)
|
||||||
shape (first shapes)]
|
shapes-with-children (deref refs/selected-shapes-with-children)
|
||||||
(when (and (not read-only?)
|
text-shapes (filter #(= (:type %) :text) shapes-with-children)
|
||||||
(= 1 (count shapes))
|
props (if (> (count text-shapes) 1)
|
||||||
(= (:type shape) :text))
|
(blend-props text-shapes props)
|
||||||
(update-attrs shape props))))
|
props)]
|
||||||
|
(when (and (not read-only?) text-shapes)
|
||||||
|
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||||
|
(run! #(update-attrs % props) text-shapes)
|
||||||
|
(st/emit! (dwu/commit-undo-transaction undo-id)))))
|
||||||
|
|
||||||
(def shortcuts
|
(def shortcuts
|
||||||
{:align-left {:tooltip (ds/meta (ds/alt "l"))
|
{:align-left {:tooltip (ds/meta (ds/alt "l"))
|
||||||
|
@ -174,12 +222,12 @@
|
||||||
:underline {:tooltip (ds/meta "u")
|
:underline {:tooltip (ds/meta "u")
|
||||||
:command (ds/c-mod "u")
|
:command (ds/c-mod "u")
|
||||||
:subsections [:text-editor]
|
:subsections [:text-editor]
|
||||||
:fn #(update-attrs-when-no-readonly {:text-decoration "underline"})}
|
:fn #(update-attrs-when-no-readonly {:text-decoration "toggle-underline"})}
|
||||||
|
|
||||||
:line-through {:tooltip (ds/alt (ds/meta-shift "5"))
|
:line-through {:tooltip (ds/alt (ds/meta-shift "5"))
|
||||||
:command "alt+shift+5"
|
:command "alt+shift+5"
|
||||||
:subsections [:text-editor]
|
:subsections [:text-editor]
|
||||||
:fn #(update-attrs-when-no-readonly {:text-decoration "line-through"})}
|
:fn #(update-attrs-when-no-readonly {:text-decoration "toggle-line-through"})}
|
||||||
|
|
||||||
:font-size-inc {:tooltip (ds/meta-shift ds/up-arrow)
|
:font-size-inc {:tooltip (ds/meta-shift ds/up-arrow)
|
||||||
:command (ds/c-mod "shift+up")
|
:command (ds/c-mod "shift+up")
|
||||||
|
@ -214,12 +262,12 @@
|
||||||
:bold {:tooltip (ds/meta "b")
|
:bold {:tooltip (ds/meta "b")
|
||||||
:command (ds/c-mod "b")
|
:command (ds/c-mod "b")
|
||||||
:subsections [:text-editor]
|
:subsections [:text-editor]
|
||||||
:fn #(update-attrs-when-no-readonly {:font-variant-id "bold"})}
|
:fn #(update-attrs-when-no-readonly {:font-variant-id "toggle-bold"})}
|
||||||
|
|
||||||
:italic {:tooltip (ds/meta "i")
|
:italic {:tooltip (ds/meta "i")
|
||||||
:command (ds/c-mod "i")
|
:command (ds/c-mod "i")
|
||||||
:subsections [:text-editor]
|
:subsections [:text-editor]
|
||||||
:fn #(update-attrs-when-no-readonly {:font-variant-id "italic"})}})
|
:fn #(update-attrs-when-no-readonly {:font-variant-id "toggle-italic"})}})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue