mirror of
https://github.com/penpot/penpot.git
synced 2025-02-04 05:18:56 -05:00
🐛 Fixed several issues with groups and multiple selection
This commit is contained in:
parent
9822c52573
commit
e26ece57d1
11 changed files with 467 additions and 394 deletions
|
@ -10,62 +10,66 @@
|
||||||
(ns app.common.attrs)
|
(ns app.common.attrs)
|
||||||
|
|
||||||
(defn get-attrs-multi
|
(defn get-attrs-multi
|
||||||
[shapes attrs]
|
([shapes attrs] (get-attrs-multi shapes attrs = identity))
|
||||||
;; Extract some attributes of a list of shapes.
|
([shapes attrs eq-fn sel-fn]
|
||||||
;; For each attribute, if the value is the same in all shapes,
|
;; Extract some attributes of a list of shapes.
|
||||||
;; wll take this value. If there is any shape that is different,
|
;; For each attribute, if the value is the same in all shapes,
|
||||||
;; the value of the attribute will be the keyword :multiple.
|
;; wll take this value. If there is any shape that is different,
|
||||||
;;
|
;; the value of the attribute will be the keyword :multiple.
|
||||||
;; If some shape has the value nil in any attribute, it's
|
;;
|
||||||
;; considered a different value. If the shape does not contain
|
;; If some shape has the value nil in any attribute, it's
|
||||||
;; the attribute, it's ignored in the final result.
|
;; considered a different value. If the shape does not contain
|
||||||
;;
|
;; the attribute, it's ignored in the final result.
|
||||||
;; Example:
|
;;
|
||||||
;; (def shapes [{:stroke-color "#ff0000"
|
;; Example:
|
||||||
;; :stroke-width 3
|
;; (def shapes [{:stroke-color "#ff0000"
|
||||||
;; :fill-color "#0000ff"
|
;; :stroke-width 3
|
||||||
;; :x 1000 :y 2000 :rx nil}
|
;; :fill-color "#0000ff"
|
||||||
;; {:stroke-width "#ff0000"
|
;; :x 1000 :y 2000 :rx nil}
|
||||||
;; :stroke-width 5
|
;; {:stroke-width "#ff0000"
|
||||||
;; :x 1500 :y 2000}])
|
;; :stroke-width 5
|
||||||
;;
|
;; :x 1500 :y 2000}])
|
||||||
;; (get-attrs-multi shapes [:stroke-color
|
;;
|
||||||
;; :stroke-width
|
;; (get-attrs-multi shapes [:stroke-color
|
||||||
;; :fill-color
|
;; :stroke-width
|
||||||
;; :rx
|
;; :fill-color
|
||||||
;; :ry])
|
;; :rx
|
||||||
;; >>> {:stroke-color "#ff0000"
|
;; :ry])
|
||||||
;; :stroke-width :multiple
|
;; >>> {:stroke-color "#ff0000"
|
||||||
;; :fill-color "#0000ff"
|
;; :stroke-width :multiple
|
||||||
;; :rx nil
|
;; :fill-color "#0000ff"
|
||||||
;; :ry nil}
|
;; :rx nil
|
||||||
;;
|
;; :ry nil}
|
||||||
(let [defined-shapes (filter some? shapes)
|
;;
|
||||||
|
(let [defined-shapes (filter some? shapes)
|
||||||
|
|
||||||
combine-value (fn [v1 v2] (cond
|
combine-value (fn [v1 v2]
|
||||||
(= v1 v2) v1
|
(cond
|
||||||
(= v1 :undefined) v2
|
(and (= v1 :undefined) (= v2 :undefined)) :undefined
|
||||||
(= v2 :undefined) v1
|
(= v1 :undefined) (if (= v2 :multiple) :multiple (sel-fn v2))
|
||||||
:else :multiple))
|
(= v2 :undefined) (if (= v1 :multiple) :multiple (sel-fn v1))
|
||||||
|
(or (= v1 :multiple) (= v2 :multiple)) :multiple
|
||||||
|
(eq-fn v1 v2) (sel-fn v1)
|
||||||
|
:else :multiple))
|
||||||
|
|
||||||
combine-values (fn [attrs shape values]
|
combine-values (fn [attrs shape values]
|
||||||
(map #(combine-value (get shape % :undefined)
|
(map #(combine-value (get shape % :undefined)
|
||||||
(get values % :undefined)) attrs))
|
(get values % :undefined)) attrs))
|
||||||
|
|
||||||
select-attrs (fn [shape attrs]
|
select-attrs (fn [shape attrs]
|
||||||
(zipmap attrs (map #(get shape % :undefined) attrs)))
|
(zipmap attrs (map #(get shape % :undefined) attrs)))
|
||||||
|
|
||||||
reducer (fn [result shape]
|
reducer (fn [result shape]
|
||||||
(zipmap attrs (combine-values attrs shape result)))
|
(zipmap attrs (combine-values attrs shape result)))
|
||||||
|
|
||||||
combined (reduce reducer
|
combined (reduce reducer
|
||||||
(select-attrs (first defined-shapes) attrs)
|
(select-attrs (first defined-shapes) attrs)
|
||||||
(rest defined-shapes))
|
(rest defined-shapes))
|
||||||
|
|
||||||
cleanup-value (fn [value]
|
cleanup-value (fn [value]
|
||||||
(if (= value :undefined) nil value))
|
(if (= value :undefined) nil value))
|
||||||
|
|
||||||
cleanup (fn [result]
|
cleanup (fn [result]
|
||||||
(zipmap attrs (map #(cleanup-value (get result %)) attrs)))]
|
(zipmap attrs (map #(cleanup-value (get result %)) attrs)))]
|
||||||
|
|
||||||
(cleanup combined)))
|
(cleanup combined))))
|
||||||
|
|
|
@ -42,31 +42,7 @@
|
||||||
(move shape (gpt/point dx dy))))
|
(move shape (gpt/point dx dy))))
|
||||||
|
|
||||||
;; --- Resize (Dimensions)
|
;; --- Resize (Dimensions)
|
||||||
(defn resize
|
(defn resize-modifiers
|
||||||
[shape width height]
|
|
||||||
(us/assert map? shape)
|
|
||||||
(us/assert number? width)
|
|
||||||
(us/assert number? height)
|
|
||||||
|
|
||||||
(let [shape-transform (:transform shape (gmt/matrix))
|
|
||||||
shape-transform-inv (:transform-inverse shape (gmt/matrix))
|
|
||||||
shape-center (gco/center-shape shape)
|
|
||||||
{sr-width :width sr-height :height} (:selrect shape)
|
|
||||||
origin (-> (gpt/point (:selrect shape))
|
|
||||||
(gtr/transform-point-center shape-center shape-transform))
|
|
||||||
|
|
||||||
scalev (gpt/divide (gpt/point width height)
|
|
||||||
(gpt/point sr-width sr-height))]
|
|
||||||
|
|
||||||
(-> shape
|
|
||||||
(update :modifiers assoc
|
|
||||||
:resize-vector scalev
|
|
||||||
:resize-origin origin
|
|
||||||
:resize-transform shape-transform
|
|
||||||
:resize-transform-inverse shape-transform-inv)
|
|
||||||
(gtr/transform-shape))))
|
|
||||||
|
|
||||||
(defn resize-rect
|
|
||||||
[shape attr value]
|
[shape attr value]
|
||||||
(us/assert map? shape)
|
(us/assert map? shape)
|
||||||
(us/assert #{:width :height} attr)
|
(us/assert #{:width :height} attr)
|
||||||
|
@ -81,8 +57,24 @@
|
||||||
(assoc :height (/ value proportion)))
|
(assoc :height (/ value proportion)))
|
||||||
(-> size
|
(-> size
|
||||||
(assoc :height value)
|
(assoc :height value)
|
||||||
(assoc :width (* value proportion)))))]
|
(assoc :width (* value proportion)))))
|
||||||
(resize shape (:width new-size) (:height new-size))))
|
width (:width new-size)
|
||||||
|
height (:height new-size)
|
||||||
|
|
||||||
|
shape-transform (:transform shape (gmt/matrix))
|
||||||
|
shape-transform-inv (:transform-inverse shape (gmt/matrix))
|
||||||
|
shape-center (gco/center-shape shape)
|
||||||
|
{sr-width :width sr-height :height} (:selrect shape)
|
||||||
|
|
||||||
|
origin (-> (gpt/point (:selrect shape))
|
||||||
|
(gtr/transform-point-center shape-center shape-transform))
|
||||||
|
|
||||||
|
scalev (gpt/divide (gpt/point width height)
|
||||||
|
(gpt/point sr-width sr-height))]
|
||||||
|
{:resize-vector scalev
|
||||||
|
:resize-origin origin
|
||||||
|
:resize-transform shape-transform
|
||||||
|
:resize-transform-inverse shape-transform-inv}))
|
||||||
|
|
||||||
;; --- Setup (Initialize)
|
;; --- Setup (Initialize)
|
||||||
;; FIXME: Is this the correct place for these functions?
|
;; FIXME: Is this the correct place for these functions?
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -868,6 +868,13 @@
|
||||||
fill: $color-primary;
|
fill: $color-primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.element-set-label {
|
||||||
|
font-size: $fs11;
|
||||||
|
padding: 0.5rem;
|
||||||
|
color: $color-gray-10;
|
||||||
|
}
|
||||||
|
|
||||||
.element-set-actions {
|
.element-set-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
|
|
@ -1441,8 +1441,6 @@
|
||||||
|
|
||||||
(defn change-canvas-color
|
(defn change-canvas-color
|
||||||
[color]
|
[color]
|
||||||
;; TODO: Create a color spec
|
|
||||||
#_(s/assert string? color)
|
|
||||||
(ptk/reify ::change-canvas-color
|
(ptk/reify ::change-canvas-color
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
|
|
|
@ -477,6 +477,34 @@
|
||||||
(us/verify #{:width :height} attr)
|
(us/verify #{:width :height} attr)
|
||||||
(us/verify ::us/number value)
|
(us/verify ::us/number value)
|
||||||
(ptk/reify ::update-dimensions
|
(ptk/reify ::update-dimensions
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
|
||||||
|
(let [page-id (:current-page-id state)
|
||||||
|
objects (dwc/lookup-page-objects state page-id)
|
||||||
|
|
||||||
|
update-children
|
||||||
|
(fn [objects ids modifiers]
|
||||||
|
(reduce #(assoc-in %1 [%2 :modifiers] modifiers) objects ids))
|
||||||
|
|
||||||
|
;; For each shape updates the modifiers given as arguments
|
||||||
|
update-shape
|
||||||
|
(fn [objects shape-id]
|
||||||
|
(let [shape (get objects shape-id)
|
||||||
|
modifier (gsh/resize-modifiers shape attr value)]
|
||||||
|
(-> objects
|
||||||
|
(assoc-in [shape-id :modifiers] modifier)
|
||||||
|
(cond-> (not (= :frame (:type shape)))
|
||||||
|
(update-children (cp/get-children shape-id objects) modifier)))))]
|
||||||
|
|
||||||
|
(d/update-in-when
|
||||||
|
state
|
||||||
|
[:workspace-data :pages-index page-id :objects]
|
||||||
|
#(reduce update-shape % ids))))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(rx/of (dwc/update-shapes ids #(gsh/resize-rect % attr value) {:reg-objects? true})))))
|
(let [page-id (:current-page-id state)
|
||||||
|
objects (dwc/lookup-page-objects state page-id)
|
||||||
|
ids (d/concat [] ids (mapcat #(cp/get-children % objects) ids))]
|
||||||
|
(rx/of (apply-modifiers ids))))))
|
||||||
|
|
|
@ -74,7 +74,8 @@
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:file-id file-id
|
:file-id file-id
|
||||||
:shapes-with-children shapes-with-children}]
|
:shapes-with-children shapes-with-children}]
|
||||||
[:& multiple/options {:shapes shapes-with-children}])]]
|
[:& multiple/options {:shapes-with-children shapes-with-children
|
||||||
|
:shapes shapes}])]]
|
||||||
|
|
||||||
[:& tab-element {:id :prototype
|
[:& tab-element {:id :prototype
|
||||||
:title (t locale "workspace.options.prototype")}
|
:title (t locale "workspace.options.prototype")}
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [t]]))
|
[app.util.i18n :as i18n :refer [t]]))
|
||||||
|
|
||||||
|
(def blur-attrs [:blur])
|
||||||
|
|
||||||
(defn create-blur []
|
(defn create-blur []
|
||||||
(let [id (uuid/next)]
|
(let [id (uuid/next)]
|
||||||
{:id id
|
{:id id
|
||||||
|
@ -28,10 +30,11 @@
|
||||||
:value 4
|
:value 4
|
||||||
:hidden false}))
|
:hidden false}))
|
||||||
|
|
||||||
(mf/defc blur-menu [{:keys [ids values]}]
|
(mf/defc blur-menu [{:keys [ids type values]}]
|
||||||
(let [locale (i18n/use-locale)
|
(let [locale (i18n/use-locale)
|
||||||
blur (:blur values)
|
blur (:blur values)
|
||||||
has-value? (not (nil? blur))
|
has-value? (not (nil? blur))
|
||||||
|
multiple? (= blur :multiple)
|
||||||
|
|
||||||
change! (fn [update-fn] (st/emit! (dwc/update-shapes ids update-fn)))
|
change! (fn [update-fn] (st/emit! (dwc/update-shapes ids update-fn)))
|
||||||
|
|
||||||
|
@ -53,18 +56,26 @@
|
||||||
|
|
||||||
[:div.element-set
|
[:div.element-set
|
||||||
[:div.element-set-title
|
[:div.element-set-title
|
||||||
[:span (t locale "workspace.options.blur-options.title")]
|
[:span
|
||||||
|
(case type
|
||||||
|
:multiple (t locale "workspace.options.blur-options.title.multiple")
|
||||||
|
:group (t locale "workspace.options.blur-options.title.group")
|
||||||
|
(t locale "workspace.options.blur-options.title"))]
|
||||||
|
|
||||||
[:div.element-set-title-actions
|
[:div.element-set-title-actions
|
||||||
(if has-value?
|
(when (and has-value? (not multiple?))
|
||||||
[:div.add-page {:on-click handle-toggle-visibility} (if (:hidden blur) i/eye-closed i/eye)])
|
[:div.add-page {:on-click handle-toggle-visibility} (if (:hidden blur) i/eye-closed i/eye)])
|
||||||
|
|
||||||
(if has-value?
|
(if has-value?
|
||||||
[:div.add-page {:on-click handle-delete} i/minus]
|
[:div.add-page {:on-click handle-delete} i/minus]
|
||||||
[:div.add-page {:on-click handle-add} i/close])]]
|
[:div.add-page {:on-click handle-add} i/close])]]
|
||||||
|
|
||||||
(when has-value?
|
(cond
|
||||||
|
has-value?
|
||||||
[:div.element-set-content
|
[:div.element-set-content
|
||||||
[:& input-row {:label "Value"
|
[:& input-row {:label "Value"
|
||||||
:class "pixels"
|
:class "pixels"
|
||||||
:min 0
|
:min 0
|
||||||
:value (:value blur)
|
:value (:value blur)
|
||||||
|
:placeholder (t locale "settings.multiple")
|
||||||
:on-change handle-change}]])]))
|
:on-change handle-change}]])]))
|
||||||
|
|
|
@ -15,20 +15,14 @@
|
||||||
[app.common.geom.shapes :as geom]
|
[app.common.geom.shapes :as geom]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.data.workspace.texts :as dwt]
|
[app.main.data.workspace.texts :as dwt]
|
||||||
[app.main.ui.workspace.sidebar.options.multiple :refer [get-shape-attrs]]
|
[app.main.ui.workspace.sidebar.options.multiple :refer [get-shape-attrs extract]]
|
||||||
[app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
|
[app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.component :refer [component-attrs component-menu]]
|
[app.main.ui.workspace.sidebar.options.component :refer [component-attrs component-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]]
|
[app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]]
|
[app.main.ui.workspace.sidebar.options.blur :refer [blur-menu]]
|
||||||
|
[app.main.ui.workspace.sidebar.options.shadow :refer [shadow-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]
|
[app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.text :refer [text-fill-attrs
|
[app.main.ui.workspace.sidebar.options.text :as ot]))
|
||||||
text-font-attrs
|
|
||||||
text-align-attrs
|
|
||||||
text-spacing-attrs
|
|
||||||
text-valign-attrs
|
|
||||||
text-decoration-attrs
|
|
||||||
text-transform-attrs
|
|
||||||
text-menu]]))
|
|
||||||
|
|
||||||
(mf/defc options
|
(mf/defc options
|
||||||
[{:keys [shape shape-with-children] :as props}]
|
[{:keys [shape shape-with-children] :as props}]
|
||||||
|
@ -76,65 +70,17 @@
|
||||||
shape-with-children)
|
shape-with-children)
|
||||||
stroke-attrs)
|
stroke-attrs)
|
||||||
|
|
||||||
font-values
|
root-values (extract {:shapes shape-with-children
|
||||||
(attrs/get-attrs-multi (map #(get-shape-attrs
|
:text-attrs ot/root-attrs
|
||||||
%
|
:extract-fn dwt/current-root-values})
|
||||||
nil
|
|
||||||
text-font-attrs
|
|
||||||
nil
|
|
||||||
dwt/current-text-values)
|
|
||||||
shape-with-children)
|
|
||||||
text-font-attrs)
|
|
||||||
|
|
||||||
align-values
|
paragraph-values (extract {:shapes shape-with-children
|
||||||
(attrs/get-attrs-multi (map #(get-shape-attrs
|
:text-attrs ot/paragraph-attrs
|
||||||
%
|
:extract-fn dwt/current-paragraph-values})
|
||||||
nil
|
|
||||||
text-align-attrs
|
|
||||||
nil
|
|
||||||
dwt/current-paragraph-values)
|
|
||||||
shape-with-children)
|
|
||||||
text-align-attrs)
|
|
||||||
|
|
||||||
spacing-values
|
text-values (extract {:shapes shape-with-children
|
||||||
(attrs/get-attrs-multi (map #(get-shape-attrs
|
:text-attrs ot/text-attrs
|
||||||
%
|
:extract-fn dwt/current-text-values})]
|
||||||
nil
|
|
||||||
text-spacing-attrs
|
|
||||||
nil
|
|
||||||
dwt/current-text-values)
|
|
||||||
shape-with-children)
|
|
||||||
text-spacing-attrs)
|
|
||||||
|
|
||||||
valign-values
|
|
||||||
(attrs/get-attrs-multi (map #(get-shape-attrs
|
|
||||||
%
|
|
||||||
nil
|
|
||||||
text-valign-attrs
|
|
||||||
nil
|
|
||||||
dwt/current-root-values)
|
|
||||||
shape-with-children)
|
|
||||||
text-valign-attrs)
|
|
||||||
|
|
||||||
decoration-values
|
|
||||||
(attrs/get-attrs-multi (map #(get-shape-attrs
|
|
||||||
%
|
|
||||||
nil
|
|
||||||
text-decoration-attrs
|
|
||||||
nil
|
|
||||||
dwt/current-text-values)
|
|
||||||
shape-with-children)
|
|
||||||
text-decoration-attrs)
|
|
||||||
|
|
||||||
transform-values
|
|
||||||
(attrs/get-attrs-multi (map #(get-shape-attrs
|
|
||||||
%
|
|
||||||
nil
|
|
||||||
text-transform-attrs
|
|
||||||
nil
|
|
||||||
dwt/current-text-values)
|
|
||||||
shape-with-children)
|
|
||||||
text-transform-attrs)]
|
|
||||||
[:*
|
[:*
|
||||||
[:& measures-menu {:ids [id]
|
[:& measures-menu {:ids [id]
|
||||||
:ids-with-children ids-with-children
|
:ids-with-children ids-with-children
|
||||||
|
@ -146,7 +92,12 @@
|
||||||
:type type
|
:type type
|
||||||
:values fill-values}]
|
:values fill-values}]
|
||||||
|
|
||||||
|
[:& shadow-menu {:ids [id]
|
||||||
|
:type type
|
||||||
|
:values (select-keys shape [:shadow])}]
|
||||||
|
|
||||||
[:& blur-menu {:ids [id]
|
[:& blur-menu {:ids [id]
|
||||||
|
:type type
|
||||||
:values (select-keys shape [:blur])}]
|
:values (select-keys shape [:blur])}]
|
||||||
|
|
||||||
(when-not (empty? other-ids)
|
(when-not (empty? other-ids)
|
||||||
|
@ -154,13 +105,11 @@
|
||||||
:type type
|
:type type
|
||||||
:values stroke-values}])
|
:values stroke-values}])
|
||||||
(when-not (empty? text-ids)
|
(when-not (empty? text-ids)
|
||||||
[:& text-menu {:ids text-ids
|
[:& ot/text-menu {:ids text-ids
|
||||||
:type type
|
:type type
|
||||||
:editor nil
|
:editor nil
|
||||||
:font-values font-values
|
:shapes shape-with-children
|
||||||
:align-values align-values
|
:values (merge root-values
|
||||||
:spacing-values spacing-values
|
paragraph-values
|
||||||
:valign-values valign-values
|
text-values)}])]))
|
||||||
:decoration-values decoration-values
|
|
||||||
:transform-values transform-values}])]))
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
[app.main.data.workspace.texts :as dwt]
|
[app.main.data.workspace.texts :as dwt]
|
||||||
[app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
|
[app.main.ui.workspace.sidebar.options.measures :refer [measure-attrs measures-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]]
|
[app.main.ui.workspace.sidebar.options.fill :refer [fill-attrs fill-menu]]
|
||||||
|
[app.main.ui.workspace.sidebar.options.shadow :refer [shadow-attrs shadow-menu]]
|
||||||
|
[app.main.ui.workspace.sidebar.options.blur :refer [blur-attrs blur-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]
|
[app.main.ui.workspace.sidebar.options.stroke :refer [stroke-attrs stroke-menu]]
|
||||||
[app.main.ui.workspace.sidebar.options.text :as ot]))
|
[app.main.ui.workspace.sidebar.options.text :as ot]))
|
||||||
|
|
||||||
|
@ -34,47 +36,81 @@
|
||||||
text-values)]
|
text-values)]
|
||||||
converted-values))))
|
converted-values))))
|
||||||
|
|
||||||
|
(defn extract [{:keys [shapes attrs text-attrs convert-attrs extract-fn]}]
|
||||||
|
(let [mapfn
|
||||||
|
(fn [shape]
|
||||||
|
(get-shape-attrs shape
|
||||||
|
attrs
|
||||||
|
text-attrs
|
||||||
|
convert-attrs
|
||||||
|
extract-fn))]
|
||||||
|
(attrs/get-attrs-multi (map mapfn shapes) (or attrs text-attrs))))
|
||||||
|
|
||||||
(mf/defc options
|
(mf/defc options
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [shapes] :as props}]
|
[{:keys [shapes shapes-with-children] :as props}]
|
||||||
(let [ids (map :id shapes)
|
(let [ids (map :id shapes)
|
||||||
text-ids (map :id (filter #(= (:type %) :text) shapes))
|
ids-with-children (map :id shapes-with-children)
|
||||||
other-ids (map :id (filter #(not= (:type %) :text) shapes))
|
text-ids (map :id (filter #(= (:type %) :text) shapes-with-children))
|
||||||
|
other-ids (map :id (filter #(not= (:type %) :text) shapes-with-children))
|
||||||
|
|
||||||
extract (fn [{:keys [attrs text-attrs convert-attrs extract-fn]}]
|
|
||||||
(let [mapfn
|
|
||||||
(fn [shape]
|
|
||||||
(get-shape-attrs shape
|
|
||||||
attrs
|
|
||||||
text-attrs
|
|
||||||
convert-attrs
|
|
||||||
extract-fn))]
|
|
||||||
(attrs/get-attrs-multi (map mapfn shapes) (or attrs text-attrs))))
|
|
||||||
|
|
||||||
measure-values (attrs/get-attrs-multi shapes measure-attrs)
|
measure-values (attrs/get-attrs-multi shapes measure-attrs)
|
||||||
|
|
||||||
fill-values (extract {:attrs fill-attrs
|
shadow-values (let [keys [:style :color :offset-x :offset-y :blur :spread]]
|
||||||
|
(attrs/get-attrs-multi
|
||||||
|
shapes shadow-attrs
|
||||||
|
(fn [s1 s2]
|
||||||
|
(and (= (count s1) (count s2))
|
||||||
|
(->> (map vector s1 s2)
|
||||||
|
(every? (fn [[v1 v2]]
|
||||||
|
(= (select-keys v1 keys) (select-keys v2 keys)))))))
|
||||||
|
(fn [v]
|
||||||
|
(mapv #(select-keys % keys) v))))
|
||||||
|
|
||||||
|
blur-values (let [keys [:type :value]]
|
||||||
|
(attrs/get-attrs-multi
|
||||||
|
shapes blur-attrs
|
||||||
|
(fn [v1 v2]
|
||||||
|
(= (select-keys v1 keys) (select-keys v2 keys)))
|
||||||
|
(fn [v] (select-keys v keys))))
|
||||||
|
|
||||||
|
fill-values (extract {:shapes shapes-with-children
|
||||||
|
:attrs fill-attrs
|
||||||
:text-attrs ot/text-fill-attrs
|
:text-attrs ot/text-fill-attrs
|
||||||
:convert-attrs fill-attrs
|
:convert-attrs fill-attrs
|
||||||
:extract-fn dwt/current-text-values})
|
:extract-fn dwt/current-text-values})
|
||||||
|
|
||||||
stroke-values (extract {:attrs stroke-attrs})
|
stroke-values (extract {:shapes shapes-with-children
|
||||||
|
:attrs stroke-attrs})
|
||||||
|
|
||||||
root-values (extract {:text-attrs ot/root-attrs
|
root-values (extract {:shapes shapes-with-children
|
||||||
|
:text-attrs ot/root-attrs
|
||||||
:extract-fn dwt/current-root-values})
|
:extract-fn dwt/current-root-values})
|
||||||
|
|
||||||
paragraph-values (extract {:text-attrs ot/paragraph-attrs
|
paragraph-values (extract {:shapes shapes-with-children
|
||||||
|
:text-attrs ot/paragraph-attrs
|
||||||
:extract-fn dwt/current-paragraph-values})
|
:extract-fn dwt/current-paragraph-values})
|
||||||
|
|
||||||
text-values (extract {:text-attrs ot/text-attrs
|
text-values (extract {:shapes shapes-with-children
|
||||||
|
:text-attrs ot/text-attrs
|
||||||
:extract-fn dwt/current-text-values})]
|
:extract-fn dwt/current-text-values})]
|
||||||
[:*
|
[:*
|
||||||
[:& measures-menu {:ids ids
|
[:& measures-menu {:ids ids
|
||||||
:type :multiple
|
:type :multiple
|
||||||
:values measure-values}]
|
:values measure-values}]
|
||||||
[:& fill-menu {:ids ids
|
[:& fill-menu {:ids ids-with-children
|
||||||
:type :multiple
|
:type :multiple
|
||||||
:values fill-values}]
|
:values fill-values}]
|
||||||
|
|
||||||
|
[:& shadow-menu {:ids ids
|
||||||
|
:type :multiple
|
||||||
|
:values shadow-values}]
|
||||||
|
|
||||||
|
[:& blur-menu {:ids ids
|
||||||
|
:type :multiple
|
||||||
|
:values blur-values}]
|
||||||
|
|
||||||
(when-not (empty? other-ids)
|
(when-not (empty? other-ids)
|
||||||
[:& stroke-menu {:ids other-ids
|
[:& stroke-menu {:ids other-ids
|
||||||
:type :multiple
|
:type :multiple
|
||||||
|
@ -83,8 +119,8 @@
|
||||||
[:& ot/text-menu {:ids text-ids
|
[:& ot/text-menu {:ids text-ids
|
||||||
:type :multiple
|
:type :multiple
|
||||||
:editor nil
|
:editor nil
|
||||||
|
:shapes shapes-with-children
|
||||||
:values (merge root-values
|
:values (merge root-values
|
||||||
paragraph-values
|
paragraph-values
|
||||||
text-values)
|
text-values)}])]))
|
||||||
:shapes shapes}])]))
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
[app.util.i18n :as i18n :refer [t]]))
|
[app.util.i18n :as i18n :refer [t]]))
|
||||||
|
|
||||||
|
(def shadow-attrs [:shadow])
|
||||||
|
|
||||||
(defn create-shadow []
|
(defn create-shadow []
|
||||||
(let [id (uuid/next)]
|
(let [id (uuid/next)]
|
||||||
{:id id
|
{:id id
|
||||||
|
@ -49,13 +51,15 @@
|
||||||
adv-blur-ref (mf/use-ref nil)
|
adv-blur-ref (mf/use-ref nil)
|
||||||
adv-spread-ref (mf/use-ref nil)
|
adv-spread-ref (mf/use-ref nil)
|
||||||
|
|
||||||
remove-shadow-by-id
|
remove-shadow-by-index
|
||||||
(fn [values id] (->> values (filterv (fn [s] (not= (:id s) id)))))
|
(fn [values index] (->> (d/enumerate values)
|
||||||
|
(filterv (fn [[idx s]] (not= idx index)))
|
||||||
|
(mapv second)))
|
||||||
|
|
||||||
on-remove-shadow
|
on-remove-shadow
|
||||||
(fn [id]
|
(fn [index]
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dwc/update-shapes ids #(update % :shadow remove-shadow-by-id id) ))))
|
(st/emit! (dwc/update-shapes ids #(update % :shadow remove-shadow-by-index index) ))))
|
||||||
|
|
||||||
select-text
|
select-text
|
||||||
(fn [ref] (fn [event] (dom/select-text! (mf/ref-val ref))))
|
(fn [ref] (fn [event] (dom/select-text! (mf/ref-val ref))))
|
||||||
|
@ -111,7 +115,7 @@
|
||||||
[:div.element-set-actions
|
[:div.element-set-actions
|
||||||
[:div.element-set-actions-button {:on-click (toggle-visibility index)}
|
[:div.element-set-actions-button {:on-click (toggle-visibility index)}
|
||||||
(if (:hidden value) i/eye-closed i/eye)]
|
(if (:hidden value) i/eye-closed i/eye)]
|
||||||
[:div.element-set-actions-button {:on-click (on-remove-shadow (:id value))}
|
[:div.element-set-actions-button {:on-click (on-remove-shadow index)}
|
||||||
i/minus]]]
|
i/minus]]]
|
||||||
|
|
||||||
[:& advanced-options {:visible? @open-shadow
|
[:& advanced-options {:visible? @open-shadow
|
||||||
|
@ -175,21 +179,39 @@
|
||||||
:on-open #(st/emit! (dwc/start-undo-transaction))
|
:on-open #(st/emit! (dwc/start-undo-transaction))
|
||||||
:on-close #(st/emit! (dwc/commit-undo-transaction))}]]]]))
|
:on-close #(st/emit! (dwc/commit-undo-transaction))}]]]]))
|
||||||
(mf/defc shadow-menu
|
(mf/defc shadow-menu
|
||||||
[{:keys [ids values] :as props}]
|
[{:keys [ids type values] :as props}]
|
||||||
|
|
||||||
(let [locale (i18n/use-locale)
|
(let [locale (i18n/use-locale)
|
||||||
|
on-remove-all-shadows
|
||||||
|
(fn [event]
|
||||||
|
(st/emit! (dwc/update-shapes ids #(dissoc % :shadow) )))
|
||||||
|
|
||||||
on-add-shadow
|
on-add-shadow
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dwc/update-shapes ids #(update % :shadow (fnil conj []) (create-shadow)) )))]
|
(st/emit! (dwc/update-shapes ids #(update % :shadow (fnil conj []) (create-shadow)) )))]
|
||||||
[:div.element-set.shadow-options
|
[:div.element-set.shadow-options
|
||||||
[:div.element-set-title
|
[:div.element-set-title
|
||||||
[:span (t locale "workspace.options.shadow-options.title")]
|
[:span
|
||||||
[:div.add-page {:on-click on-add-shadow} i/close]]
|
(case type
|
||||||
|
:multiple (t locale "workspace.options.shadow-options.title.multiple")
|
||||||
|
:group (t locale "workspace.options.shadow-options.title.group")
|
||||||
|
(t locale "workspace.options.shadow-options.title"))]
|
||||||
|
|
||||||
(when (seq (:shadow values))
|
(when-not (= :multiple (:shadow values))
|
||||||
|
[:div.add-page {:on-click on-add-shadow} i/close])]
|
||||||
|
|
||||||
|
(cond
|
||||||
|
(= :multiple (:shadow values))
|
||||||
|
[:div.element-set-content
|
||||||
|
[:div.element-set-options-group
|
||||||
|
[:div.element-set-label (t locale "settings.multiple")]
|
||||||
|
[:div.element-set-actions
|
||||||
|
[:div.element-set-actions-button {:on-click on-remove-all-shadows}
|
||||||
|
i/minus]]]]
|
||||||
|
|
||||||
|
(not (empty? (:shadow values)))
|
||||||
[:div.element-set-content
|
[:div.element-set-content
|
||||||
(for [[index {:keys [id] :as value}] (d/enumerate (:shadow values []))]
|
(for [[index {:keys [id] :as value}] (d/enumerate (:shadow values []))]
|
||||||
[:& shadow-entry {:key (str "shadow-" id)
|
[:& shadow-entry {:key (str "shadow-" index)
|
||||||
:ids ids
|
:ids ids
|
||||||
:value value
|
:value value
|
||||||
:index index}])])]))
|
:index index}])])]))
|
||||||
|
|
Loading…
Add table
Reference in a new issue