mirror of
https://github.com/penpot/penpot.git
synced 2026-02-12 14:42:56 +00:00
153 lines
5.4 KiB
Clojure
153 lines
5.4 KiB
Clojure
;; 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) KALEIDOS INC
|
|
|
|
(ns app.main.data.workspace.wasm-text
|
|
"Helpers/events to resize wasm text shapes without depending on workspace.texts.
|
|
|
|
This exists to avoid circular deps:
|
|
workspace.texts -> workspace.libraries -> workspace.texts"
|
|
(:require
|
|
[app.common.data.macros :as dm]
|
|
[app.common.files.helpers :as cfh]
|
|
[app.common.geom.matrix :as gmt]
|
|
[app.common.geom.point :as gpt]
|
|
[app.common.types.modifiers :as ctm]
|
|
[app.main.data.helpers :as dsh]
|
|
[app.main.data.workspace.modifiers :as dwm]
|
|
[app.render-wasm.api :as wasm.api]
|
|
[app.render-wasm.api.fonts :as wasm.fonts]
|
|
[beicon.v2.core :as rx]
|
|
[potok.v2.core :as ptk]))
|
|
|
|
(defn resize-wasm-text-modifiers
|
|
([shape]
|
|
(resize-wasm-text-modifiers shape (:content shape)))
|
|
|
|
([{:keys [id points selrect grow-type] :as shape} content]
|
|
(wasm.api/use-shape id)
|
|
(wasm.api/set-shape-text-content id content)
|
|
(wasm.api/set-shape-text-images id content)
|
|
|
|
(let [dimension (wasm.api/get-text-dimensions)
|
|
width-scale (if (#{:fixed :auto-height} grow-type)
|
|
1.0
|
|
(/ (:width dimension) (:width selrect)))
|
|
height-scale (if (= :fixed grow-type)
|
|
1.0
|
|
(/ (:height dimension) (:height selrect)))
|
|
resize-v (gpt/point width-scale height-scale)
|
|
origin (first points)]
|
|
|
|
{id
|
|
{:modifiers
|
|
(ctm/resize-modifiers
|
|
resize-v
|
|
origin
|
|
(:transform shape (gmt/matrix))
|
|
(:transform-inverse shape (gmt/matrix)))}})))
|
|
|
|
(defn resize-wasm-text
|
|
"Resize a single text shape (auto-width/auto-height) by id.
|
|
No-op if the id is not a text shape or is :fixed."
|
|
[id]
|
|
(ptk/reify ::resize-wasm-text
|
|
ptk/WatchEvent
|
|
(watch [_ state _]
|
|
(let [objects (dsh/lookup-page-objects state)
|
|
shape (get objects id)]
|
|
(if (and (some? shape)
|
|
(cfh/text-shape? shape)
|
|
(not= :fixed (:grow-type shape)))
|
|
(rx/of (dwm/apply-wasm-modifiers (resize-wasm-text-modifiers shape)))
|
|
(rx/empty))))))
|
|
|
|
(defn resize-wasm-text-debounce-commit
|
|
[]
|
|
(ptk/reify ::resize-wasm-text-debounce-commit
|
|
ptk/WatchEvent
|
|
(watch [_ state _]
|
|
(let [ids (get state ::resize-wasm-text-debounce-ids)
|
|
objects (dsh/lookup-page-objects state)
|
|
|
|
modifiers
|
|
(reduce
|
|
(fn [modifiers id]
|
|
(let [shape (get objects id)]
|
|
(cond-> modifiers
|
|
(and (some? shape)
|
|
(cfh/text-shape? shape)
|
|
(not= :fixed (:grow-type shape)))
|
|
(merge (resize-wasm-text-modifiers shape)))))
|
|
{}
|
|
ids)]
|
|
(if (not (empty? modifiers))
|
|
(rx/of (dwm/apply-wasm-modifiers modifiers))
|
|
(rx/empty))))))
|
|
|
|
;; This event will debounce the resize events so, if there are many, they
|
|
;; are processed at the same time and not one-by-one. This will improve
|
|
;; performance because it's better to make only one layout calculation instead
|
|
;; of (potentialy) hundreds.
|
|
(defn resize-wasm-text-debounce-inner
|
|
[id]
|
|
(let [cur-event (js/Symbol)]
|
|
(ptk/reify ::resize-wasm-text-debounce-inner
|
|
ptk/UpdateEvent
|
|
(update [_ state]
|
|
(-> state
|
|
(update ::resize-wasm-text-debounce-ids (fnil conj []) id)
|
|
(cond-> (nil? (::resize-wasm-text-debounce-event state))
|
|
(assoc ::resize-wasm-text-debounce-event cur-event))))
|
|
|
|
ptk/WatchEvent
|
|
(watch [_ state stream]
|
|
(if (= (::resize-wasm-text-debounce-event state) cur-event)
|
|
(let [stopper (->> stream (rx/filter (ptk/type? :app.main.data.workspace/finalize)))]
|
|
(rx/concat
|
|
(rx/merge
|
|
(->> stream
|
|
(rx/filter (ptk/type? ::resize-wasm-text-debounce-inner))
|
|
(rx/debounce 40)
|
|
(rx/take 1)
|
|
(rx/map #(resize-wasm-text-debounce-commit))
|
|
(rx/take-until stopper))
|
|
(rx/of (resize-wasm-text-debounce-inner id)))
|
|
(rx/of #(dissoc %
|
|
::resize-wasm-text-debounce-ids
|
|
::resize-wasm-text-debounce-event))))
|
|
(rx/empty))))))
|
|
|
|
(defn resize-wasm-text-debounce
|
|
[id]
|
|
(ptk/reify ::resize-wasm-text-debounce
|
|
ptk/WatchEvent
|
|
(watch [_ state _]
|
|
(let [page-id (:current-page-id state)
|
|
objects (dsh/lookup-page-objects state page-id)
|
|
content (dm/get-in objects [id :content])
|
|
fonts (wasm.fonts/get-content-fonts content)
|
|
|
|
fonts-loaded?
|
|
(->> fonts
|
|
(every?
|
|
(fn [font]
|
|
(let [font-data (wasm.fonts/make-font-data font)]
|
|
(wasm.fonts/font-stored? font-data (:emoji? font-data))))))]
|
|
|
|
(if (not fonts-loaded?)
|
|
(->> (rx/of (resize-wasm-text-debounce id))
|
|
(rx/delay 20))
|
|
(rx/of (resize-wasm-text-debounce-inner id)))))))
|
|
|
|
(defn resize-wasm-text-all
|
|
"Resize all text shapes (auto-width/auto-height) from a collection of ids."
|
|
[ids]
|
|
(ptk/reify ::resize-wasm-text-all
|
|
ptk/WatchEvent
|
|
(watch [_ _ _]
|
|
(->> (rx/from ids)
|
|
(rx/map resize-wasm-text)))))
|