Merge pull request #276 from uxbox/304/edit-multi-properties

🎉 Display properly multiple text properties
This commit is contained in:
Andrey Antukh 2020-07-03 16:17:00 +02:00 committed by GitHub
commit d1f6e9635c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 83 additions and 65 deletions

View file

@ -855,3 +855,19 @@
:else srect)))) :else srect))))
(defn get-attrs-multi
[shapes attrs]
;; Extract some attributes of a list of shapes.
;; For each attribute, if the value is the same in all shapes,
;; wll take this value. If there is any shape that is different,
;; the value of the attribute will be the keyword :multiple.
(let [combine-value #(if (= %1 %2) %1 :multiple)
combine-values (fn [attrs shape values]
(map #(combine-value (get shape %) (get values %)) attrs))
reducer (fn [result shape]
(zipmap attrs (combine-values attrs shape result)))]
(reduce reducer (select-keys (first shapes) attrs) (rest shapes))))

View file

@ -16,6 +16,7 @@
[clojure.walk :as walk] [clojure.walk :as walk]
[goog.object :as gobj] [goog.object :as gobj]
[potok.core :as ptk] [potok.core :as ptk]
[uxbox.common.geom.shapes :as geom]
[uxbox.main.data.workspace.common :as dwc] [uxbox.main.data.workspace.common :as dwc]
[uxbox.main.fonts :as fonts] [uxbox.main.fonts :as fonts]
[uxbox.util.object :as obj])) [uxbox.util.object :as obj]))
@ -119,10 +120,8 @@
(defn- shape-current-values (defn- shape-current-values
[shape pred attrs] [shape pred attrs]
(let [root (:content shape) (let [root (:content shape)
nodes (nodes-seq pred root) nodes (nodes-seq pred root)]
match (first nodes)] (geom/get-attrs-multi nodes attrs)))
(when match
(select-keys match attrs))))
(defn current-text-values (defn current-text-values
[{:keys [editor default attrs shape]}] [{:keys [editor default attrs shape]}]

View file

@ -124,7 +124,7 @@
(let [selected (get-in state [:workspace-local :selected]) (let [selected (get-in state [:workspace-local :selected])
page-id (get-in state [:workspace-page :id]) page-id (get-in state [:workspace-page :id])
objects (get-in state [:workspace-data page-id :objects])] objects (get-in state [:workspace-data page-id :objects])]
(->> selected (mapv #(get objects %)))))] (mapv #(get objects %) selected)))]
(l/derived selector st/state =))) (l/derived selector st/state =)))
(def selected-shapes-with-children (def selected-shapes-with-children

View file

@ -67,8 +67,6 @@
(fn [] (fn []
(swap! loading? not)))))) (swap! loading? not))))))
_ (prn "exports-menu" exports)
add-export add-export
(mf/use-callback (mf/use-callback
(mf/deps shape) (mf/deps shape)

View file

@ -11,8 +11,8 @@
(ns uxbox.main.ui.workspace.sidebar.options.group (ns uxbox.main.ui.workspace.sidebar.options.group
(:require (:require
[rumext.alpha :as mf] [rumext.alpha :as mf]
[uxbox.common.geom.shapes :as geom]
[uxbox.main.refs :as refs] [uxbox.main.refs :as refs]
[uxbox.main.ui.workspace.sidebar.options.multiple :refer [get-multi]]
[uxbox.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]] [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.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]]))
@ -23,8 +23,8 @@
children (mf/deref (refs/objects-by-id child-ids)) children (mf/deref (refs/objects-by-id child-ids))
type (:type shape) type (:type shape)
measure-values (select-keys shape measure-attrs) measure-values (select-keys shape measure-attrs)
fill-values (get-multi children fill-attrs) fill-values (geom/get-attrs-multi children fill-attrs)
stroke-values (get-multi children stroke-attrs)] stroke-values (geom/get-attrs-multi children stroke-attrs)]
[:* [:*
[:& measures-menu {:ids [(:id shape)] [:& measures-menu {:ids [(:id shape)]
:type type :type type

View file

@ -25,7 +25,7 @@
(def measure-attrs [:proportion-lock :width :height :x :y :rotation :rx :ry :selrect]) (def measure-attrs [:proportion-lock :width :height :x :y :rotation :rx :ry :selrect])
(defn attr->string [attr values] (defn- attr->string [attr values]
(let [value (attr values)] (let [value (attr values)]
(if (= value :multiple) (if (= value :multiple)
"" ""

View file

@ -10,34 +10,19 @@
(ns uxbox.main.ui.workspace.sidebar.options.multiple (ns uxbox.main.ui.workspace.sidebar.options.multiple
(:require (:require
[rumext.alpha :as mf] [rumext.alpha :as mf]
[uxbox.common.geom.shapes :as geom]
[uxbox.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]] [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.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]]))
(defn get-multi
[shapes attrs]
;; Extract some attributes of a list of shapes.
;; For each attribute, if the value is the same in all shapes,
;; wll take this value. If there is any shape that is different,
;; the value of the attribute will be the keyword :multiple.
(let [combine-value #(if (= %1 %2) %1 :multiple)
combine-values (fn [attrs shape values]
(map #(combine-value (get shape %) (get values %)) attrs))
reducer (fn [result shape]
(zipmap attrs (combine-values attrs shape result)))]
(reduce reducer (select-keys (first shapes) attrs) (rest shapes))))
(mf/defc options (mf/defc options
{::mf/wrap [mf/memo]} {::mf/wrap [mf/memo]}
[{:keys [shapes] :as props}] [{:keys [shapes] :as props}]
(let [ids (map :id shapes) (let [ids (map :id shapes)
measure-values (get-multi shapes measure-attrs) measure-values (geom/get-attrs-multi shapes measure-attrs)
fill-values (get-multi shapes fill-attrs) fill-values (geom/get-attrs-multi shapes fill-attrs)
stroke-values (get-multi shapes stroke-attrs)] stroke-values (geom/get-attrs-multi shapes stroke-attrs)]
[:* [:*
[:& measures-menu {:ids ids [:& measures-menu {:ids ids
:type :multiple :type :multiple

View file

@ -44,14 +44,14 @@
(identical? (:stroke-opacity new-values) (identical? (:stroke-opacity new-values)
(:stroke-opacity old-values))))) (:stroke-opacity old-values)))))
(defn width->string [width] (defn- width->string [width]
(if (= width :multiple) (if (= width :multiple)
"" ""
(str (-> width (str (-> width
(d/coalesce 1) (d/coalesce 1)
(math/round))))) (math/round)))))
(defn enum->string [value] (defn- enum->string [value]
(if (= value :multiple) (if (= value :multiple)
"" ""
(pr-str value))) (pr-str value)))

View file

@ -25,6 +25,11 @@
[uxbox.util.i18n :as i18n :refer [tr t]] [uxbox.util.i18n :as i18n :refer [tr t]]
["slate" :refer [Transforms]])) ["slate" :refer [Transforms]]))
(defn- attr->string [value]
(if (= value :multiple)
""
(str value)))
(def ^:private editor-ref (def ^:private editor-ref
(l/derived :editor refs/workspace-local)) (l/derived :editor refs/workspace-local))
@ -44,15 +49,12 @@
(:name font)])]]) (:name font)])]])
(mf/defc font-options (mf/defc font-options
[{:keys [editor shape] :as props}] [{:keys [editor shape locale] :as props}]
(let [selection (mf/use-ref) (let [selection (mf/use-ref)
{:keys [font-id {:keys [font-id
font-size font-size
font-variant-id] font-variant-id]}
:or {font-id "sourcesanspro"
font-size "14"
font-variant-id "regular"}}
(dwt/current-text-values (dwt/current-text-values
{:editor editor {:editor editor
:shape shape :shape shape
@ -60,6 +62,10 @@
:font-size :font-size
:font-variant-id]}) :font-variant-id]})
font-id (or font-id "sourcesanspro")
font-size (or font-size "14")
font-variant-id (or font-variant-id "regular")
fonts (mf/deref fonts/fontsdb) fonts (mf/deref fonts/fontsdb)
font (get fonts font-id) font (get fonts font-id)
@ -77,18 +83,20 @@
on-font-family-change on-font-family-change
(fn [event] (fn [event]
(let [id (-> (dom/get-target event) (let [id (-> (dom/get-target event)
(dom/get-value)) (dom/get-value))]
font (get fonts id)] (when-not (str/empty? id)
(fonts/ensure-loaded! id (partial change-font id)))) (let [font (get fonts id)]
(fonts/ensure-loaded! id (partial change-font id))))))
on-font-size-change on-font-size-change
(fn [event] (fn [event]
(let [val (-> (dom/get-target event) (let [val (-> (dom/get-target event)
(dom/get-value))] (dom/get-value))]
(when-not (str/empty? val)
(st/emit! (dwt/update-text-attrs (st/emit! (dwt/update-text-attrs
{:id (:id shape) {:id (:id shape)
:editor editor :editor editor
:attrs {:font-size val}})))) :attrs {:font-size val}})))))
on-font-variant-change on-font-variant-change
(fn [event] (fn [event]
@ -103,19 +111,22 @@
:font-family (:family font) :font-family (:family font)
:font-variant-id id :font-variant-id id
:font-weight (:weight variant) :font-weight (:weight variant)
:font-style (:style variant)}})))) :font-style (:style variant)}}))))]
]
[:* [:*
[:div.row-flex [:div.row-flex
[:select.input-select {:value font-id [:select.input-select {:value (attr->string font-id)
:on-change on-font-family-change} :on-change on-font-family-change}
(when (= font-id :multiple)
[:option {:value ""} (t locale "settings.multiple")])
[:& font-select-optgroups]]] [:& font-select-optgroups]]]
[:div.row-flex [:div.row-flex
[:div.editable-select [:div.editable-select
[:select.input-select {:value font-size [:select.input-select {:value (attr->string font-size)
:on-change on-font-size-change} :on-change on-font-size-change}
(when (= font-size :multiple)
[:option {:value ""} "--"])
[:option {:value "8"} "8"] [:option {:value "8"} "8"]
[:option {:value "9"} "9"] [:option {:value "9"} "9"]
[:option {:value "10"} "10"] [:option {:value "10"} "10"]
@ -131,11 +142,13 @@
:min "0" :min "0"
:max "200" :max "200"
:value font-size :value font-size
:on-change on-font-size-change :placeholder "--"
}]] :on-change on-font-size-change}]]
[:select.input-select {:value font-variant-id [:select.input-select {:value (attr->string font-variant-id)
:on-change on-font-variant-change} :on-change on-font-variant-change}
(when (= font-size :multiple)
[:option {:value ""} "--"])
(for [variant (:variants font)] (for [variant (:variants font)]
[:option {:value (:id variant) [:option {:value (:id variant)
:key (pr-str variant)} :key (pr-str variant)}
@ -144,13 +157,14 @@
(mf/defc text-align-options (mf/defc text-align-options
[{:keys [editor shape locale] :as props}] [{:keys [editor shape locale] :as props}]
(let [{:keys [text-align] (let [{:keys [text-align]}
:or {text-align "left"}}
(dwt/current-paragraph-values (dwt/current-paragraph-values
{:editor editor {:editor editor
:shape shape :shape shape
:attrs [:text-align]}) :attrs [:text-align]})
text-align (or text-align "left")
on-change on-change
(fn [event type] (fn [event type]
(st/emit! (dwt/update-paragraph-attrs (st/emit! (dwt/update-paragraph-attrs
@ -204,16 +218,17 @@
(mf/defc spacing-options (mf/defc spacing-options
[{:keys [editor shape locale] :as props}] [{:keys [editor shape locale] :as props}]
(let [{:keys [letter-spacing (let [{:keys [line-height
line-height] letter-spacing]}
:or {line-height "1.2"
letter-spacing "0"}}
(dwt/current-text-values (dwt/current-text-values
{:editor editor {:editor editor
:shape shape :shape shape
:attrs [:line-height :attrs [:line-height
:letter-spacing]}) :letter-spacing]})
line-height (or line-height "1.2")
letter-spacing (or letter-spacing "0")
on-change on-change
(fn [event attr] (fn [event attr]
(let [val (-> (dom/get-target event) (let [val (-> (dom/get-target event)
@ -232,7 +247,8 @@
:step "0.1" :step "0.1"
:min "0" :min "0"
:max "200" :max "200"
:value line-height :value (attr->string line-height)
:placeholder (t locale "settings.multiple")
:on-change #(on-change % :line-height)}]] :on-change #(on-change % :line-height)}]]
[:div.input-icon [:div.input-icon
@ -244,7 +260,8 @@
:step "0.1" :step "0.1"
:min "0" :min "0"
:max "200" :max "200"
:value letter-spacing :value (attr->string letter-spacing)
:placeholder (t locale "settings.multiple")
:on-change #(on-change % :letter-spacing)}]]])) :on-change #(on-change % :letter-spacing)}]]]))
;; (mf/defc box-sizing-options ;; (mf/defc box-sizing-options
@ -262,13 +279,14 @@
(mf/defc vertical-align-options (mf/defc vertical-align-options
[{:keys [editor locale shape] :as props}] [{:keys [editor locale shape] :as props}]
(let [{:keys [vertical-align] (let [{:keys [vertical-align]}
:or {vertical-align "top"}}
(dwt/current-root-values (dwt/current-root-values
{:editor editor {:editor editor
:shape shape :shape shape
:attrs [:vertical-align]}) :attrs [:vertical-align]})
vertical-align (or vertical-align "top")
on-change on-change
(fn [event type] (fn [event type]
(st/emit! (dwt/update-root-attrs (st/emit! (dwt/update-root-attrs
@ -297,13 +315,14 @@
(mf/defc text-decoration-options (mf/defc text-decoration-options
[{:keys [editor locale shape] :as props}] [{:keys [editor locale shape] :as props}]
(let [{:keys [text-decoration] (let [{:keys [text-decoration]}
:or {text-decoration "none"}}
(dwt/current-text-values (dwt/current-text-values
{:editor editor {:editor editor
:shape shape :shape shape
:attrs [:text-decoration]}) :attrs [:text-decoration]})
text-decoration (or text-decoration "none")
on-change on-change
(fn [event type] (fn [event type]
(st/emit! (dwt/update-text-attrs (st/emit! (dwt/update-text-attrs
@ -333,13 +352,14 @@
(mf/defc text-transform-options (mf/defc text-transform-options
[{:keys [editor locale shape] :as props}] [{:keys [editor locale shape] :as props}]
(let [{:keys [text-transform] (let [{:keys [text-transform]}
:or {text-transform "none"}}
(dwt/current-text-values (dwt/current-text-values
{:editor editor {:editor editor
:shape shape :shape shape
:attrs [:text-transform]}) :attrs [:text-transform]})
text-transform (or text-transform "none")
on-change on-change
(fn [event type] (fn [event type]
(st/emit! (dwt/update-text-attrs (st/emit! (dwt/update-text-attrs