mirror of
https://github.com/penpot/penpot.git
synced 2025-01-10 17:00:36 -05:00
Improve text shape rendering and fix broken behavior.
This commit is contained in:
parent
82f1da06f8
commit
57c53ba6a1
1 changed files with 85 additions and 118 deletions
|
@ -11,11 +11,9 @@
|
|||
[lentes.core :as l]
|
||||
[goog.events :as events]
|
||||
[uxbox.rstore :as rs]
|
||||
[uxbox.state :as st]
|
||||
[uxbox.data.shapes :as uds]
|
||||
[uxbox.ui.core :as ui]
|
||||
[uxbox.ui.mixins :as mx]
|
||||
[uxbox.ui.keyboard :as kbd]
|
||||
[uxbox.ui.shapes.common :as common]
|
||||
[uxbox.ui.shapes.attrs :as attrs]
|
||||
[uxbox.util.geom :as geom]
|
||||
|
@ -25,124 +23,52 @@
|
|||
|
||||
;; --- Events
|
||||
|
||||
;; FIXME: try to reuse the common.
|
||||
|
||||
(defn on-mouse-down
|
||||
[event own {:keys [id group] :as shape} selected]
|
||||
(let [selected? (contains? selected id)
|
||||
local (:rum/local own)
|
||||
drawing? @common/drawing-state-l]
|
||||
(when-not (:blocked shape)
|
||||
(cond
|
||||
(or drawing?
|
||||
(:edition @local)
|
||||
(and group (:locked (geom/resolve-parent shape))))
|
||||
nil
|
||||
|
||||
(and (not selected?) (empty? selected))
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(ui/acquire-action! "ui.shape.move")
|
||||
(rs/emit! (uds/select-shape id)))
|
||||
|
||||
(and (not selected?) (not (empty? selected)))
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(if (kbd/shift? event)
|
||||
(rs/emit! (uds/select-shape id))
|
||||
(rs/emit! (uds/deselect-all)
|
||||
(uds/select-shape id))))
|
||||
|
||||
:else
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(ui/acquire-action! "ui.shape.move"))))))
|
||||
|
||||
(defn on-mouse-up
|
||||
[event {:keys [id group] :as shape}]
|
||||
(cond
|
||||
(and group (:locked (geom/resolve-parent shape)))
|
||||
(defn handle-mouse-down
|
||||
[event local {:keys [id group] :as shape} selected]
|
||||
(if (and (not (:blocked shape))
|
||||
(or @common/drawing-state-l
|
||||
(:edition @local)
|
||||
(and group (:locked (geom/resolve-parent shape)))))
|
||||
nil
|
||||
|
||||
:else
|
||||
(do
|
||||
(dom/stop-propagation event)
|
||||
(ui/release-action! "ui.shape"))))
|
||||
(common/on-mouse-down event shape selected)))
|
||||
|
||||
;; --- Text Component
|
||||
|
||||
(defn- text-component-did-mount
|
||||
[own]
|
||||
(letfn [(on-double-click [ev]
|
||||
(let [container (mx/get-ref-dom own "container")
|
||||
local (:rum/local own)]
|
||||
(swap! local assoc :edition true)
|
||||
(ui/acquire-action! "ui.text.edit")
|
||||
(set! (.-contentEditable container) true)
|
||||
(.setAttribute container "contenteditable" "true")
|
||||
(.focus container)))
|
||||
(on-blur [ev]
|
||||
(let [container (mx/get-ref-dom own "container")
|
||||
local (:rum/local own)]
|
||||
(ui/release-action! "ui.text.edit")
|
||||
(swap! local assoc :edition false)
|
||||
(set! (.-contentEditable container) false)
|
||||
(.removeAttribute container "contenteditable")))
|
||||
(on-input [ev]
|
||||
(let [content (dom/event->inner-text ev)
|
||||
sid (:id (first (:rum/props own)))]
|
||||
(rs/emit! (uds/update-text sid {:content content}))))]
|
||||
(let [main-dom (mx/get-ref-dom own "main")
|
||||
cntr-dom (mx/get-ref-dom own "container")
|
||||
key1 (events/listen main-dom EventType.DBLCLICK on-double-click)
|
||||
key2 (events/listen cntr-dom EventType.BLUR on-blur)
|
||||
key3 (events/listen cntr-dom EventType.INPUT on-input)]
|
||||
(assoc own ::key1 key1 ::key2 key2 ::key3 key3))))
|
||||
|
||||
(defn- text-component-will-unmount
|
||||
[own]
|
||||
(let [key1 (::key1 own)
|
||||
key2 (::key2 own)
|
||||
key3 (::key3 own)]
|
||||
(events/unlistenByKey key1)
|
||||
(events/unlistenByKey key2)
|
||||
(events/unlistenByKey key3)
|
||||
(dissoc own ::key1 ::key2 ::key3)))
|
||||
|
||||
(defn- text-component-transfer-state
|
||||
[old-own own]
|
||||
(let [data (select-keys old-own [::key1 ::key2 ::key3])]
|
||||
(merge own data)))
|
||||
|
||||
(declare text-shape)
|
||||
(declare text-shape-render)
|
||||
(declare text-shape-edit)
|
||||
|
||||
(defn- text-component-render
|
||||
[own shape]
|
||||
(let [{:keys [id x1 y1 content group]} shape
|
||||
selected (rum/react common/selected-shapes-l)
|
||||
selected? (and (contains? selected id) (= (count selected) 1))
|
||||
on-mouse-down #(on-mouse-down % own shape selected)
|
||||
on-mouse-up #(on-mouse-up % shape)
|
||||
local (:rum/local own)
|
||||
shape (assoc shape :editing? (:edition @local false))]
|
||||
(html
|
||||
[:g.shape {:class (when selected? "selected")
|
||||
:ref "main"
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-mouse-up on-mouse-up}
|
||||
(text-shape-render own shape)])))
|
||||
[own {:keys [id x1 y1 content group] :as shape}]
|
||||
(let [selected (rum/react common/selected-shapes-l)
|
||||
selected? (and (contains? selected id)
|
||||
(= (count selected) 1))
|
||||
local (:rum/local own)]
|
||||
(letfn [(on-mouse-down [event]
|
||||
(handle-mouse-down event local shape selected))
|
||||
(on-mouse-up [event]
|
||||
(common/on-mouse-up event shape))
|
||||
(on-done [_]
|
||||
(swap! local assoc :edition false))
|
||||
(on-double-click [event]
|
||||
(swap! local assoc :edition true)
|
||||
(ui/acquire-action! "ui.text.edit"))]
|
||||
(html
|
||||
[:g.shape {:class (when selected? "selected")
|
||||
:ref "main"
|
||||
:on-double-click on-double-click
|
||||
:on-mouse-down on-mouse-down
|
||||
:on-mouse-up on-mouse-up}
|
||||
(if (:edition @local false)
|
||||
(text-shape-edit shape on-done)
|
||||
(text-shape shape))]))))
|
||||
|
||||
(def text-component
|
||||
(mx/component
|
||||
{:render text-component-render
|
||||
:name "text-componet"
|
||||
:did-mount text-component-did-mount
|
||||
:will-unmount text-component-will-unmount
|
||||
:transfer-state text-component-transfer-state
|
||||
:mixins [mx/static rum/reactive (mx/local)]}))
|
||||
|
||||
;; --- Test Shape
|
||||
;; --- Text Styles Helpers
|
||||
|
||||
(def ^:const +style-attrs+ [:font-size])
|
||||
(def ^:const +select-rect-attrs+
|
||||
|
@ -168,6 +94,7 @@
|
|||
(merge
|
||||
{:fontSize (str size "px")
|
||||
:color color
|
||||
:whiteSpace "pre"
|
||||
:textAlign align
|
||||
:fontFamily family
|
||||
:fontWeight weight
|
||||
|
@ -175,8 +102,52 @@
|
|||
(when line-height {:lineHeight line-height})
|
||||
(when letter-spacing {:letterSpacing letter-spacing}))))
|
||||
|
||||
;; --- Text Shape Edit
|
||||
|
||||
(defn- text-shape-edit-did-mount
|
||||
[own]
|
||||
(let [[shape] (:rum/props own)
|
||||
dom (mx/get-ref-dom own "container")]
|
||||
(set! (.-textContent dom) (:content shape ""))
|
||||
(.focus dom)
|
||||
own))
|
||||
|
||||
(defn- text-shape-edit-render
|
||||
[own {:keys [id x1 y1 content] :as shape} on-done]
|
||||
(let [size (geom/size shape)
|
||||
style (make-style shape)
|
||||
rfm (geom/transformation-matrix shape)
|
||||
props {:x x1 :y y1
|
||||
:transform (str rfm)}
|
||||
props (merge props size)]
|
||||
(letfn [(on-blur [ev]
|
||||
(ui/release-action! "ui.text.edit")
|
||||
(on-done))
|
||||
(on-input [ev]
|
||||
(let [content (dom/event->inner-text ev)
|
||||
sid (:id (first (:rum/props own)))]
|
||||
(rs/emit! (uds/update-text sid {:content content}))))]
|
||||
(html
|
||||
[:g
|
||||
[:rect (merge props +select-rect-attrs+)]
|
||||
[:foreignObject props
|
||||
[:p {:ref "container"
|
||||
:on-blur on-blur
|
||||
:on-input on-input
|
||||
:contentEditable true
|
||||
:style style}]]]))))
|
||||
|
||||
(def text-shape-edit
|
||||
(mx/component
|
||||
{:render text-shape-edit-render
|
||||
:did-mount text-shape-edit-did-mount
|
||||
:name "text-shape-edit"
|
||||
:mixins [mx/static]}))
|
||||
|
||||
;; --- Text Shape
|
||||
|
||||
(defn- text-shape-render
|
||||
[own {:keys [id x1 y1 x2 y2 content drawing? editing?] :as shape}]
|
||||
[own {:keys [id x1 y1 content] :as shape}]
|
||||
(let [key (str id)
|
||||
rfm (geom/transformation-matrix shape)
|
||||
size (geom/size shape)
|
||||
|
@ -185,15 +156,11 @@
|
|||
attrs (merge props size)
|
||||
style (make-style shape)]
|
||||
(html
|
||||
[:g
|
||||
(if (or drawing? editing?)
|
||||
[:g
|
||||
[:rect (merge attrs +select-rect-attrs+)]])
|
||||
[:foreignObject attrs
|
||||
[:p {:ref "container" :style style} content]]])))
|
||||
[:foreignObject attrs
|
||||
[:p {:style style} content]])))
|
||||
|
||||
;; (def text-shape
|
||||
;; (mx/component
|
||||
;; {:render text-shape-render
|
||||
;; :name "text-shape"
|
||||
;; :mixins [mx/static]}))
|
||||
(def text-shape
|
||||
(mx/component
|
||||
{:render text-shape-render
|
||||
:name "text-shape"
|
||||
:mixins [mx/static]}))
|
||||
|
|
Loading…
Reference in a new issue