diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index fc578148c8..d029a4143e 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1456,7 +1456,8 @@ "a" #(st/emit! (select-for-drawing :frame)) "b" #(st/emit! (select-for-drawing :rect)) "e" #(st/emit! (select-for-drawing :circle)) - "t" #(st/emit! (select-for-drawing :text)) + "t" #(st/emit! dwtxt/start-edit-if-selected + (select-for-drawing :text)) "ctrl+c" #(st/emit! copy-selected) "ctrl+v" #(st/emit! paste) "escape" #(st/emit! :interrupt deselect-all) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 6054fd7aa4..60d1bf8676 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -186,3 +186,23 @@ (defn update-root-attrs [options] (update-attrs (assoc options :pred is-root-node? :split false))) + +(defn update-overflow-text [id value] + (ptk/reify ::update-overflow-text + ptk/UpdateEvent + (update [_ state] + (let [page-id (:current-page-id state)] + (update-in state [:workspace-data :pages-index page-id :objects id] assoc :overflow-text value))))) + + +(def start-edit-if-selected + (ptk/reify ::start-edit-if-selected + ptk/UpdateEvent + (update [_ state] + (let [page-id (:current-page-id state) + objects (get-in state [:workspace-data :pages-index page-id :objects]) + selected (->> state :workspace-local :selected (map #(get objects %)))] + (cond-> state + (and (= 1 (count selected)) + (= (-> selected first :type) :text)) + (assoc-in [:workspace-local :edition] (-> selected first :id))))))) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 2774c99919..54491833d3 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -18,6 +18,7 @@ [app.common.pages-helpers :as cph] [app.common.spec :as us] [app.main.data.workspace.common :as dwc] + [app.main.data.workspace.texts :as dwt] [app.main.data.workspace.selection :as dws] [app.main.refs :as refs] [app.main.snap :as snap] @@ -139,8 +140,12 @@ layout (:workspace-layout state) page-id (:current-page-id state) objects (dwc/lookup-page-objects state page-id) - resizing-shapes (map #(get objects %) ids)] + resizing-shapes (map #(get objects %) ids) + text-shapes-ids (->> resizing-shapes + (filter #(= :text (:type %))) + (map :id))] (rx/concat + (rx/of (dwc/update-shapes text-shapes-ids #(assoc % :grow-type :fixed))) (->> ms/mouse-position (rx/with-latest vector ms/mouse-position-shift) (rx/map normalize-proportion-lock) diff --git a/frontend/src/app/main/ui/workspace/selection.cljs b/frontend/src/app/main/ui/workspace/selection.cljs index eb73c081da..8e54075e58 100644 --- a/frontend/src/app/main/ui/workspace/selection.cljs +++ b/frontend/src/app/main/ui/workspace/selection.cljs @@ -126,7 +126,7 @@ :on-mouse-down on-rotate}])) (mf/defc resize-point-handler - [{:keys [cx cy zoom position on-resize transform rotation color]}] + [{:keys [cx cy zoom position on-resize transform rotation color overflow-text]}] (let [{cx' :x cy' :y} (gpt/transform (gpt/point cx cy) transform) rot-square (case position :top-left 0 @@ -140,7 +140,7 @@ :vectorEffect "non-scaling-stroke" } :fill "#FFFFFF" - :stroke color + :stroke (if (and (= position :bottom-right) overflow-text) "red" color) :cx cx' :cy cy'}] @@ -172,7 +172,7 @@ (mf/defc controls {::mf/wrap-props false} [props] - (let [shape (obj/get props "shape") + (let [{:keys [overflow-text] :as shape} (obj/get props "shape") zoom (obj/get props "zoom") color (obj/get props "color") on-resize (obj/get props "on-resize") @@ -202,7 +202,8 @@ :on-resize (partial on-resize position) :transform transform :rotation (:rotation shape) - :color color} + :color color + :overflow-text overflow-text} props (map->obj (merge common-props props))] (case type :rotation (when (not= :frame (:type shape)) [:> rotation-handler props]) diff --git a/frontend/src/app/main/ui/workspace/shapes/text.cljs b/frontend/src/app/main/ui/workspace/shapes/text.cljs index d55bc2998a..ff4d978ac2 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text.cljs @@ -61,8 +61,6 @@ selected? (and (contains? selected id) (= (count selected) 1)) - calculate-size (mf/use-state false) - on-mouse-down #(handle-mouse-down % shape) on-context-menu #(common/on-context-menu % shape) @@ -73,18 +71,13 @@ (when selected? (st/emit! (dw/start-edition-mode (:id shape)))))] - (mf/use-effect - (mf/deps grow-type content width height) - (fn [] - (reset! calculate-size true) - (timers/schedule 200 (fn [] (reset! calculate-size false))))) - [:g.shape {:on-double-click on-double-click :on-mouse-down on-mouse-down :on-context-menu on-context-menu} [:* - (when (and (not edition?) @calculate-size) - [:g {:opacity 0} + (when (not edition?) + [:g {:opacity 0 + :style {:pointer-events "none"}} ;; We only render the component for its side-effect [:& text-shape-edit {:shape shape :read-only? true}]]) @@ -125,7 +118,7 @@ lh (obj/set! "lineHeight" lh)))) (defn- generate-text-styles - [data] + [data on-load-font] (let [letter-spacing (obj/get data "letter-spacing") text-decoration (obj/get data "text-decoration") text-transform (obj/get data "text-transform") @@ -157,7 +150,7 @@ (when (and (string? font-id) (pos? (alength font-id))) (let [font (get fontsdb font-id)] - (fonts/ensure-loaded! font-id) + (fonts/ensure-loaded! font-id on-load-font) (let [font-family (or (:family font) (obj/get data "fontFamily")) font-variant (d/seek #(= font-variant-id (:id %)) @@ -219,7 +212,8 @@ (let [attrs (obj/get props "attributes") childs (obj/get props "children") data (obj/get props "leaf") - style (generate-text-styles data) + on-load-font (obj/get props "on-load-font") + style (generate-text-styles data on-load-font) attrs (obj/set! attrs "style" style)] [:> :span attrs childs])) @@ -235,9 +229,10 @@ nil)))) (defn- render-text - [props] - (mf/html - [:> editor-text-node props])) + [on-load-font] + (fn [props] + (mf/html + [:> editor-text-node (obj/merge! props #js {:on-load-font on-load-font})]))) ;; --- Text Shape Edit @@ -271,7 +266,7 @@ (when (not read-only?) (st/emit! dw/clear-edition-mode))) - on-click + on-click-outside (fn [event] (dom/prevent-default event) (dom/stop-propagation event) @@ -304,7 +299,7 @@ on-mount (fn [] (when (not read-only?) - (let [lkey1 (events/listen js/document EventType.CLICK on-click) + (let [lkey1 (events/listen js/document EventType.CLICK on-click-outside) lkey2 (events/listen js/document EventType.KEYUP on-key-up)] (st/emit! (dwt/assign-editor id editor) dwc/start-undo-transaction) @@ -327,22 +322,42 @@ (let [content (js->clj val :keywordize-keys true) content (first content)] (st/emit! (dw/update-shape id {:content content})) - (reset! state val)))))] + (reset! state val))))) + + loaded-fonts (mf/use-var 0) + on-load-font #(swap! loaded-fonts inc)] (mf/use-effect on-mount) (mf/use-effect - (mf/deps @state) + (mf/deps content) + (fn [] + (reset! state (parse-content content)))) + + ;; Checks the size of the wrapper to update if it were necesary + (mf/use-effect + (mf/deps props @loaded-fonts) (fn [] (timers/schedule - #(if (#{:auto-width :auto-height} grow-type) - (let [self-node (mf/ref-val self-ref) - paragraph-node (dom/query self-node ".paragraph-set")] - (when paragraph-node - (let [{:keys [width height]} (dom/get-bounding-rect paragraph-node)] - (st/emit! (dw/update-shape id (if (= grow-type :auto-width) - {:width width :height height} - {:height height})))))))))) + 250 ;; We need to wait to the text to be rendered. Is there a better alternative? + #(let [self-node (mf/ref-val self-ref) + paragraph-node (when self-node (dom/query self-node ".paragraph-set"))] + (when paragraph-node + (let [{:keys [width height]} (dom/get-bounding-rect paragraph-node)] + (cond + (and (:overflow-text shape) (not= :fixed (:grow-type shape))) + (st/emit! (dwt/update-overflow-text id false)) + + (and (= :fixed (:grow-type shape)) (not (:overflow-text shape)) (> height (:height shape))) + (st/emit! (dwt/update-overflow-text id true)) + + (and (= :fixed (:grow-type shape)) (:overflow-text shape) (<= height (:height shape))) + (st/emit! (dwt/update-overflow-text id false))) + + (if (#{:auto-width :auto-height} grow-type) + (st/emit! (dw/update-shape id (if (= grow-type :auto-width) + {:width width :height height} + {:height height})))))))))) [:foreignObject {:ref self-ref :transform (geom/transform-matrix shape) @@ -358,9 +373,10 @@ :spell-check "false" :on-focus on-focus :class "rich-text" - :style {:cursor cur/text} + :style {:cursor cur/text + :width (:width shape)} :render-element #(render-element shape %) - :render-leaf render-text + :render-leaf (render-text on-load-font) :on-mouse-up on-mouse-up :on-mouse-down on-mouse-down :on-blur (fn [event] diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 74957a7e56..0a49936238 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -308,7 +308,7 @@ (st/emit! (ms/->MouseEvent :down ctrl? shift? alt?)) (cond - (and (not edition) (= 1 (.-which event))) + (and (= 1 (.-which event))) (if drawing-tool (st/emit! (dd/start-drawing drawing-tool)) (st/emit! dw/handle-selection))