🎉 Allow to edit text properties of multiple shapes

This commit is contained in:
Andrés Moya 2020-07-08 10:21:18 +02:00
parent 0951ba95f0
commit 6020cc797d
6 changed files with 471 additions and 252 deletions

View file

@ -55,9 +55,9 @@
(let [change #(cond-> %
value (assoc :fill-color value)
opacity (assoc :fill-opacity opacity))
new-attrs (cond-> {}
value (assoc :fill value)
opacity (assoc :opacity opacity))]
converted-attrs (cond-> {}
value (assoc :fill value)
opacity (assoc :opacity opacity))]
(when-not (empty? other-ids)
(st/emit! (dwc/update-shapes ids change)))
@ -65,7 +65,7 @@
(run! #(st/emit! (dwt/update-text-attrs
{:id %
:editor editor
:attrs new-attrs}))
:attrs converted-attrs}))
text-ids))))]
[:div.element-set
[:div.element-set-title label]

View file

@ -13,26 +13,123 @@
[rumext.alpha :as mf]
[uxbox.common.geom.shapes :as geom]
[uxbox.main.refs :as refs]
[uxbox.main.data.workspace.texts :as dwt]
[uxbox.main.ui.workspace.sidebar.options.multiple :refer [get-shape-attrs]]
[uxbox.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
[uxbox.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]]
[uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]))
[uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]
[uxbox.main.ui.workspace.sidebar.options.text :refer [text-fill-attrs
text-font-attrs
text-align-attrs
text-spacing-attrs
text-valign-attrs
text-decoration-attrs
text-transform-attrs
text-menu]]))
(mf/defc options
[{:keys [shape] :as props}]
(let [child-ids (:shapes shape)
children (mf/deref (refs/objects-by-id child-ids))
type (:type shape)
measure-values (select-keys shape measure-attrs)
fill-values (geom/get-attrs-multi children fill-attrs)
stroke-values (geom/get-attrs-multi children stroke-attrs)]
[:*
[:& measures-menu {:ids [(:id shape)]
:type type
:values measure-values}]
[:& fill-menu {:ids child-ids
:type type
:values fill-values}]
[:& stroke-menu {:ids child-ids
:type type
:values stroke-values}]]))
text-ids (map :id (filter #(= (:type %) :text) children))
other-ids (map :id (filter #(not= (:type %) :text) children))
type (:type shape)
measure-values
(select-keys shape measure-attrs)
fill-values
(geom/get-attrs-multi children fill-attrs)
stroke-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
stroke-attrs
nil
nil
nil)
children)
stroke-attrs)
font-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-font-attrs
nil
dwt/current-text-values)
children)
text-font-attrs)
align-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-align-attrs
nil
dwt/current-paragraph-values)
children)
text-align-attrs)
spacing-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-spacing-attrs
nil
dwt/current-text-values)
children)
text-spacing-attrs)
valign-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-valign-attrs
nil
dwt/current-root-values)
children)
text-valign-attrs)
decoration-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-decoration-attrs
nil
dwt/current-text-values)
children)
text-decoration-attrs)
transform-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-transform-attrs
nil
dwt/current-text-values)
children)
text-transform-attrs)]
[:*
[:& measures-menu {:ids [(:id shape)]
:type type
:values measure-values}]
[:& fill-menu {:ids child-ids
:type type
:values fill-values}]
(when-not (empty? other-ids)
[:& stroke-menu {:ids child-ids
:type type
:values stroke-values}])
(when-not (empty? text-ids)
[:& text-menu {:ids text-ids
:type type
:editor nil
:font-values font-values
:align-values align-values
:spacing-values spacing-values
:valign-values valign-values
:decoration-values decoration-values
:transform-values transform-values}])]))

View file

@ -13,28 +13,122 @@
[uxbox.common.geom.shapes :as geom]
[uxbox.main.data.workspace.texts :as dwt]
[uxbox.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
[uxbox.main.ui.workspace.sidebar.options.text :refer [text-fill-attrs]]
[uxbox.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]]
[uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]))
[uxbox.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]
[uxbox.main.ui.workspace.sidebar.options.text :refer [text-fill-attrs
text-font-attrs
text-align-attrs
text-spacing-attrs
text-valign-attrs
text-decoration-attrs
text-transform-attrs
text-menu]]))
(defn- get-attrs
[shape attrs text-attrs]
(defn get-shape-attrs
[shape attrs text-attrs convert-attrs extract-fn]
(if (not= (:type shape) :text)
(select-keys shape attrs)
(let [text-values (dwt/current-text-values {:editor nil
:shape shape
:attrs text-attrs})
converted-values (zipmap fill-attrs
(map #(% text-values) text-attrs))]
converted-values)))
(when attrs
(select-keys shape attrs))
(when text-attrs
(let [text-values (extract-fn {:editor nil
:shape shape
:attrs text-attrs})
converted-values (if convert-attrs
(zipmap convert-attrs
(map #(% text-values) text-attrs))
text-values)]
converted-values))))
(mf/defc options
{::mf/wrap [mf/memo]}
[{:keys [shapes] :as props}]
(let [ids (map :id shapes)
measure-values (geom/get-attrs-multi shapes measure-attrs)
fill-values (geom/get-attrs-multi (map #(get-attrs % fill-attrs text-fill-attrs) shapes) fill-attrs)
stroke-values (geom/get-attrs-multi shapes stroke-attrs)]
text-ids (map :id (filter #(= (:type %) :text) shapes))
other-ids (map :id (filter #(not= (:type %) :text) shapes))
measure-values
(geom/get-attrs-multi shapes measure-attrs)
fill-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
fill-attrs
text-fill-attrs
fill-attrs
dwt/current-text-values)
shapes)
fill-attrs)
stroke-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
stroke-attrs
nil
nil
nil)
shapes)
stroke-attrs)
font-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-font-attrs
nil
dwt/current-text-values)
shapes)
text-font-attrs)
align-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-align-attrs
nil
dwt/current-paragraph-values)
shapes)
text-align-attrs)
spacing-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-spacing-attrs
nil
dwt/current-text-values)
shapes)
text-spacing-attrs)
valign-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-valign-attrs
nil
dwt/current-root-values)
shapes)
text-valign-attrs)
decoration-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-decoration-attrs
nil
dwt/current-text-values)
shapes)
text-decoration-attrs)
transform-values
(geom/get-attrs-multi (map #(get-shape-attrs
%
nil
text-transform-attrs
nil
dwt/current-text-values)
shapes)
text-transform-attrs)]
[:*
[:& measures-menu {:ids ids
:type :multiple
@ -42,7 +136,18 @@
[:& fill-menu {:ids ids
:type :multiple
:values fill-values}]
[:& stroke-menu {:ids ids
(when-not (empty? other-ids)
[:& stroke-menu {:ids other-ids
:type :multiple
:values stroke-values}])
(when-not (empty? text-ids)
[:& text-menu {:ids text-ids
:type :multiple
:values stroke-values}]]))
:editor nil
:font-values font-values
:align-values align-values
:spacing-values spacing-values
:valign-values valign-values
:decoration-values decoration-values
:transform-values transform-values}])]))

View file

@ -26,8 +26,12 @@
["slate" :refer [Transforms]]))
(def text-fill-attrs [:fill :opacity])
(def text-font-attrs [:font-id :font-family :font-variant-id :font-size :font-weight :font-style])
(def text-align-attrs [:text-align])
(def text-spacing-attrs [:line-height :letter-spacing])
(def text-valign-attrs [:vertical-align])
(def text-decoration-attrs [:text-decoration])
(def text-transform-attrs [:text-transform])
(defn- attr->string [value]
(if (= value :multiple)
@ -171,22 +175,22 @@
;; --- Align
[:div.row-flex.align-icons
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-left")
{:alt (t locale "workspace.options.text-options.align-left")
:class (dom/classnames :current (= "left" text-align))
:on-click #(on-change % "left")}
i/text-align-left]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-center")
{:alt (t locale "workspace.options.text-options.align-center")
:class (dom/classnames :current (= "center" text-align))
:on-click #(on-change % "center")}
i/text-align-center]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-right")
{:alt (t locale "workspace.options.text-options.align-right")
:class (dom/classnames :current (= "right" text-align))
:on-click #(on-change % "right")}
i/text-align-right]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-justify")
{:alt (t locale "workspace.options.text-options.align-justify")
:class (dom/classnames :current (= "justify" text-align))
:on-click #(on-change % "justify")}
i/text-align-justify]]))
@ -212,7 +216,7 @@
[:div.row-flex
[:div.input-icon
[:span.icon-before.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.line-height")}
{:alt (t locale "workspace.options.text-options.line-height")}
i/line-height]
[:input.input-text
{:type "number"
@ -225,7 +229,7 @@
[:div.input-icon
[:span.icon-before.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.letter-spacing")}
{:alt (t locale "workspace.options.text-options.letter-spacing")}
i/letter-spacing]
[:input.input-text
{:type "number"
@ -264,20 +268,20 @@
ids))]
[:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.font-options.vertical-align")]
[:span.element-set-subtitle (t locale "workspace.options.text-options.vertical-align")]
[:div.align-icons
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-top")
{:alt (t locale "workspace.options.text-options.align-top")
:class (dom/classnames :current (= "top" vertical-align))
:on-click #(on-change % "top")}
i/align-top]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-middle")
{:alt (t locale "workspace.options.text-options.align-middle")
:class (dom/classnames :current (= "center" vertical-align))
:on-click #(on-change % "center")}
i/align-middle]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.align-bottom")
{:alt (t locale "workspace.options.text-options.align-bottom")
:class (dom/classnames :current (= "bottom" vertical-align))
:on-click #(on-change % "bottom")}
i/align-bottom]]]))
@ -296,22 +300,22 @@
:attrs {:text-decoration type}}))
ids))]
[:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.font-options.decoration")]
[:span.element-set-subtitle (t locale "workspace.options.text-options.decoration")]
[:div.align-icons
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.none")
{:alt (t locale "workspace.options.text-options.none")
:class (dom/classnames :current (= "none" text-decoration))
:on-click #(on-change % "none")}
i/minus]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.underline")
{:alt (t locale "workspace.options.text-options.underline")
:class (dom/classnames :current (= "underline" text-decoration))
:on-click #(on-change % "underline")}
i/underline]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.strikethrough")
{:alt (t locale "workspace.options.text-options.strikethrough")
:class (dom/classnames :current (= "line-through" text-decoration))
:on-click #(on-change % "line-through")}
i/strikethrough]]]))
@ -330,25 +334,25 @@
:attrs {:text-transform type}}))
ids))]
[:div.row-flex
[:span.element-set-subtitle (t locale "workspace.options.font-options.text-case")]
[:span.element-set-subtitle (t locale "workspace.options.text-options.text-case")]
[:div.align-icons
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.none")
{:alt (t locale "workspace.options.text-options.none")
:class (dom/classnames :current (= "none" text-transform))
:on-click #(on-change % "none")}
i/minus]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.uppercase")
{:alt (t locale "workspace.options.text-options.uppercase")
:class (dom/classnames :current (= "uppercase" text-transform))
:on-click #(on-change % "uppercase")}
i/uppercase]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.lowercase")
{:alt (t locale "workspace.options.text-options.lowercase")
:class (dom/classnames :current (= "lowercase" text-transform))
:on-click #(on-change % "lowercase")}
i/lowercase]
[:span.tooltip.tooltip-bottom
{:alt (t locale "workspace.options.font-options.titlecase")
{:alt (t locale "workspace.options.text-options.titlecase")
:class (dom/classnames :current (= "capitalize" text-transform))
:on-click #(on-change % "capitalize")}
i/titlecase]]]))
@ -358,26 +362,26 @@
[{:keys [ids
type
editor
fill-values
font-values
align-values
spacing-values
valign-values
decoration-values
transform-values] :as props}]
(let [locale (mf/deref i18n/locale)]
[:*
[:& fill-menu {:ids ids :type type :values fill-values :editor editor}]
[:div.element-set
[:div.element-set-title (t locale "workspace.options.font-options")]
[:div.element-set-content
[:& font-options {:editor editor :ids ids :values font-values :locale locale}]
[:& text-align-options {:editor editor :ids ids :values align-values :locale locale}]
[:& spacing-options {:editor editor :ids ids :values spacing-values :locale locale}]
[:& vertical-align-options {:editor editor :ids ids :values valign-values :locale locale}]
[:& text-decoration-options {:editor editor :ids ids :values decoration-values :locale locale}]
[:& text-transform-options {:editor editor :ids ids :values transform-values :locale locale}]]]]))
(let [locale (mf/deref i18n/locale)
label (case type
:multiple (t locale "workspace.options.text-options.title-selection")
:group (t locale "workspace.options.text-options.title-group")
(t locale "workspace.options.text-options.title"))]
[:div.element-set
[:div.element-set-title label]
[:div.element-set-content
[:& font-options {:editor editor :ids ids :values font-values :locale locale}]
[:& text-align-options {:editor editor :ids ids :values align-values :locale locale}]
[:& spacing-options {:editor editor :ids ids :values spacing-values :locale locale}]
[:& vertical-align-options {:editor editor :ids ids :values valign-values :locale locale}]
[:& text-decoration-options {:editor editor :ids ids :values decoration-values :locale locale}]
[:& text-transform-options {:editor editor :ids ids :values transform-values :locale locale}]]]))
(mf/defc options
[{:keys [shape] :as props}]
@ -387,15 +391,12 @@
local (deref refs/workspace-local)
editor (get-in local [:editors (:id shape)])
_ (println "hay editor" (clj->js (not (nil? editor))))
measure-values (select-keys shape measure-attrs)
fill-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:fill
:opacity]})
:attrs text-fill-attrs})
converted-fill-values {:fill-color (:fill fill-values)
:fill-opacity (:opacity fill-values)}
@ -403,43 +404,43 @@
font-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:font-id
:font-size
:font-variant-id]})
:attrs text-font-attrs})
align-values (dwt/current-paragraph-values
{:editor editor
:shape shape
:attrs [:text-align]})
:attrs text-align-attrs})
spacing-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:line-height
:letter-spacing]})
:attrs text-spacing-attrs})
valign-values (dwt/current-root-values
{:editor editor
:shape shape
:attrs [:vertical-align]})
:attrs text-valign-attrs})
decoration-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:text-decoration]})
:attrs text-decoration-attrs})
transform-values (dwt/current-text-values
{:editor editor
:shape shape
:attrs [:text-transform]})]
[:div
:attrs text-transform-attrs})]
[:*
[:& measures-menu {:ids ids
:type type
:values measure-values}]
[:& fill-menu {:ids ids
:type type
:values converted-fill-values
:editor editor}]
[:& text-menu {:ids ids
:type type
:editor editor
:fill-values converted-fill-values
:font-values font-values
:align-values align-values
:spacing-values spacing-values