0
Fork 0
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:
Pablo Alba 2023-01-26 12:49:57 +01:00
parent 21fc9289a6
commit d7d6166232

View file

@ -9,6 +9,7 @@
[app.common.data :as d]
[app.main.data.shortcuts :as ds]
[app.main.data.workspace.texts :as dwt]
[app.main.data.workspace.undo :as dwu]
[app.main.fonts :as fonts]
[app.main.refs :as refs]
[app.main.store :as st]
@ -20,6 +21,12 @@
;; 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
[text-values variant-id]
(let [first-intersection (fn [list1 list2] (first (filter (set list1) list2)))
@ -50,8 +57,6 @@
["700italic" "700cursive" "bolditalic" "blackitalic" "boldcursive" "blackcursive"]
:else
["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)
fonts (deref fonts/fontsdb)
font (get fonts font-id)
@ -62,57 +67,68 @@
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)))
new-variant (let [toggle-bold? (= variant-id "bold")
toggle-italic? (= variant-id "italic")
bold? (is-bold? current-variant)
italic? (is-italic? current-variant)]
new-variant (let [bold? (is-bold? current-variant)
italic? (is-italic? current-variant)
add-bold? (and (not bold?)
(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
(and toggle-bold? bold? italic?) ;; it is bold+italic, set it to 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
(and add-bold? italic?) ;; it is italic, set it to bold+italic
(choose-bold-italic)
(and toggle-bold? (not bold?) (not italic?)) ;; it is regular, set it to bold
(and add-bold? (not italic?)) ;; it is regular, set it to bold
(choose-bold)
(and toggle-italic? bold? italic?) ;; it is bold+italic, set it to bold
(choose-bold)
(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
(and remove-bold? italic?) ;; it is bold+italic, set it to italic
(choose-italic)
(and remove-bold? (not italic?)) ;; it is bold set it to 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
(choose-italic)))
new-weight (when new-variant
(->> (: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))
first
:weight)]
{:font-variant-id new-variant,
:font-weight new-weight}))
(defn calculate-text-values
[shape]
(let [state-map (deref refs/workspace-editor-state)
editor-state (get state-map (:id shape))]
(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]
(let [state-map (deref refs/workspace-editor-state)
editor-state (get state-map (:id 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}))
(let [
text-values (calculate-text-values shape)
font-size (d/parse-double (:font-size text-values))
line-height (d/parse-double (:line-height text-values))
letter-spacing (d/parse-double (:letter-spacing text-values))
@ -129,29 +145,61 @@
{:letter-spacing (str (+ letter-spacing 0.1))}
(:letter-spacing-dec props)
{:letter-spacing (str (- letter-spacing 0.1))}
(= (:text-decoration props) "underline") ;;toggle
(= (:text-decoration props) "toggle-underline") ;;toggle
(if (= (:text-decoration text-values) "underline")
{:text-decoration "none"}
props)
(= (:text-decoration props) "line-through") ;;toggle
{:text-decoration "underline"})
(= (:text-decoration props) "toggle-line-through") ;;toggle
(if (= (:text-decoration text-values) "line-through")
{:text-decoration "none"}
props)
{:text-decoration "line-through"})
(:font-variant-id props)
(generate-variant-props text-values (:font-variant-id props))
:else props)]
(when shape
(when (and 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]
(let [read-only? (deref refs/workspace-read-only?)
shapes (deref refs/selected-objects)
shape (first shapes)]
(when (and (not read-only?)
(= 1 (count shapes))
(= (:type shape) :text))
(update-attrs shape props))))
(let [undo-id (js/Symbol)
read-only? (deref refs/workspace-read-only?)
shapes-with-children (deref refs/selected-shapes-with-children)
text-shapes (filter #(= (:type %) :text) shapes-with-children)
props (if (> (count text-shapes) 1)
(blend-props text-shapes 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
{:align-left {:tooltip (ds/meta (ds/alt "l"))
@ -174,12 +222,12 @@
:underline {:tooltip (ds/meta "u")
:command (ds/c-mod "u")
: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"))
:command "alt+shift+5"
: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)
:command (ds/c-mod "shift+up")
@ -214,12 +262,12 @@
:bold {:tooltip (ds/meta "b")
:command (ds/c-mod "b")
: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")
:command (ds/c-mod "i")
:subsections [:text-editor]
:fn #(update-attrs-when-no-readonly {:font-variant-id "italic"})}})
:fn #(update-attrs-when-no-readonly {:font-variant-id "toggle-italic"})}})