diff --git a/frontend/src/app/main/data/workspace/text/shortcuts.cljs b/frontend/src/app/main/data/workspace/text/shortcuts.cljs index 000401b3d..5ef7850ee 100644 --- a/frontend/src/app/main/data/workspace/text/shortcuts.cljs +++ b/frontend/src/app/main/data/workspace/text/shortcuts.cljs @@ -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"})}})