0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-23 06:58:58 -05:00

🐛 Fix edit attrs of groups

This commit is contained in:
Andrés Moya 2020-07-09 13:36:38 +02:00
parent cf108e110f
commit 8de55ce054
5 changed files with 127 additions and 60 deletions

View file

@ -856,34 +856,63 @@
:else srect))))
(defn get-attrs-multi
[values attrs]
;; Extract some attributes of a list of shape values.
[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.
;;
;; If some shape has the value nil in any attribute, it's
;; considered a different value. If the shape does not contain
;; the attribute, it's ignored in the final result.
;;
;; Example:
;; (def values [{:stroke-color "#ff0000'
;; (def shapes [{:stroke-color "#ff0000"
;; :stroke-width 3
;; :x 1000 :y 2000}
;; {:stroke-width "#ff0000'
;; :fill-color "#0000ff"
;; :x 1000 :y 2000 :rx nil}
;; {:stroke-width "#ff0000"
;; :stroke-width 5
;; :x 1500 :y 2000}])
;;
;; (get-attrs-multi values [:stroke-color :stroke-width :fill-color])
;; >>> {:stroke-color "#ff0000'
;; (get-attrs-multi shapes [:stroke-color
;; :stroke-width
;; :fill-color
;; :rx
;; :ry])
;; >>> {:stroke-color "#ff0000"
;; :stroke-width :multiple
;; :fill-color nil}
;; :fill-color "#0000ff"
;; :rx nil
;; :ry nil}
;;
(let [defined-values (filter some? values)
(let [defined-shapes (filter some? shapes)
combine-value #(if (= %1 %2) %1 :multiple)
combine-value (fn [v1 v2] (cond
(= v1 v2) v1
(= v1 :undefined) v2
(= v2 :undefined) v1
:else :multiple))
combine-values (fn [attrs shape values]
(map #(combine-value (get shape %) (get values %)) attrs))
(map #(combine-value (get shape % :undefined)
(get values % :undefined)) attrs))
select-attrs (fn [shape attrs]
(zipmap attrs (map #(get shape % :undefined) attrs)))
reducer (fn [result shape]
(zipmap attrs (combine-values attrs shape result)))]
(zipmap attrs (combine-values attrs shape result)))
(reduce reducer (select-keys (first defined-values) attrs) (rest defined-values))))
combined (reduce reducer
(select-attrs (first defined-shapes) attrs)
(rest defined-shapes))
cleanup-value (fn [value]
(if (= value :undefined) nil value))
cleanup (fn [result]
(zipmap attrs (map #(cleanup-value (get result %)) attrs)))]
(cleanup combined)))

View file

@ -233,36 +233,61 @@
[{:type :rect
:name "Rect"
:fill-color default-color
:stroke-alignment :center
:rx 0
:ry 0}
{:type :image}
{:type :icon}
{:type :circle
:name "Circle"
:fill-color default-color}
{:type :path
:name "Path"
:stroke-style :solid
:stroke-color "#000000"
:stroke-width 2
:stroke-alignment :center
:fill-color "#000000"
:fill-opacity 0
:segments []}
{:type :frame
:fill-opacity 1
:stroke-style :none
:stroke-alignment :center
:name "Artboard"}
{:type :curve
:name "Path"
:stroke-style :solid
:stroke-width 0
:stroke-color "#000000"
:stroke-width 2
:stroke-opacity 0
:rx 0
:ry 0}
{:type :image}
{:type :icon}
{:type :circle
:name "Circle"
:fill-color default-color
:fill-opacity 1
:stroke-style :none
:stroke-alignment :center
:stroke-width 0
:stroke-color "#000000"
:stroke-opacity 0}
{:type :path
:name "Path"
:fill-color "#000000"
:fill-opacity 0
:stroke-style :solid
:stroke-alignment :center
:stroke-width 2
:stroke-color "#000000"
:stroke-opacity 1
:segments []}
{:type :frame
:name "Artboard"
:fill-color "#ffffff"
:fill-opacity 1
:stroke-style :none
:stroke-alignment :center
:stroke-width 0
:stroke-color "#000000"
:stroke-opacity 0}
{:type :curve
:name "Path"
:fill-color "#000000"
:fill-opacity 0
:stroke-style :solid
:stroke-alignment :center
:stroke-width 2
:stroke-color "#000000"
:stroke-opacity 1
:segments []}
{:type :text
:name "Text"
:content nil}])

View file

@ -136,6 +136,16 @@
(into selected children)))]
(l/derived selector st/state)))
(def selected-objects-with-children
(letfn [(selector [state]
(let [selected (get-in state [:workspace-local :selected])
page-id (get-in state [:workspace-page :id])
objects (get-in state [:workspace-data page-id :objects])
children (mapcat #(cph/get-children % objects) selected)
accumulated (into selected children)]
(mapv #(get objects %) accumulated)))]
(l/derived selector st/state)))
(defn make-selected
[id]
(l/derived #(contains? % id) selected-shapes))

View file

@ -37,11 +37,11 @@
(mf/defc shape-options
{::mf/wrap [#(mf/throttle % 60)]}
[{:keys [shape page] :as props}]
[{:keys [shape shapes-with-children page] :as props}]
[:*
(case (:type shape)
:frame [:& frame/options {:shape shape}]
:group [:& group/options {:shape shape}]
:group [:& group/options {:shape shape :shape-with-children shapes-with-children}]
:text [:& text/options {:shape shape}]
:rect [:& rect/options {:shape shape}]
:icon [:& icon/options {:shape shape}]
@ -55,7 +55,7 @@
(mf/defc options-content
{::mf/wrap [mf/memo]}
[{:keys [section shapes page] :as props}]
[{:keys [section shapes shapes-with-children page] :as props}]
(let [locale (mf/deref i18n/locale)]
[:div.tool-window
[:div.tool-window-content
@ -67,8 +67,8 @@
[:& align-options]
(case (count shapes)
0 [:& page/options {:page page}]
1 [:& shape-options {:shape (first shapes)}]
[:& multiple/options {:shapes shapes}])]]
1 [:& shape-options {:shape (first shapes) :shapes-with-children shapes-with-children}]
[:& multiple/options {:shapes shapes-with-children}])]]
[:& tab-element {:id :prototype
:title (t locale "workspace.options.prototype")}
@ -79,9 +79,11 @@
(mf/defc options-toolbox
{::mf/wrap [mf/memo]}
[{:keys [page local] :as props}]
(let [section (:options-mode local)
shapes (mf/deref refs/selected-objects)]
(let [section (:options-mode local)
shapes (mf/deref refs/selected-objects)
shapes-with-children (mf/deref refs/selected-objects-with-children)]
[:& options-content {:shapes shapes
:shapes-with-children shapes-with-children
:page page
:section section}]))

View file

@ -12,6 +12,7 @@
(:require
[rumext.alpha :as mf]
[uxbox.common.geom.shapes :as geom]
[uxbox.common.pages-helpers :as cph]
[uxbox.main.refs :as refs]
[uxbox.main.data.workspace.texts :as dwt]
[uxbox.main.ui.workspace.sidebar.options.multiple :refer [get-shape-attrs]]
@ -28,19 +29,19 @@
text-menu]]))
(mf/defc options
[{:keys [shape] :as props}]
(let [child-ids (:shapes shape)
children (mf/deref (refs/objects-by-id child-ids))
text-ids (map :id (filter #(= (:type %) :text) children))
other-ids (map :id (filter #(not= (:type %) :text) children))
[{:keys [shape shape-with-children] :as props}]
(let [id (:id shape)
ids-with-children (map :id shape-with-children)
text-ids (map :id (filter #(= (:type %) :text) shape-with-children))
other-ids (map :id (filter #(not= (:type %) :text) shape-with-children))
type (:type shape)
type (:type shape) ; always be :group
measure-values
(select-keys shape measure-attrs)
fill-values
(geom/get-attrs-multi children fill-attrs)
(geom/get-attrs-multi shape-with-children fill-attrs)
stroke-values
(geom/get-attrs-multi (map #(get-shape-attrs
@ -49,7 +50,7 @@
nil
nil
nil)
children)
shape-with-children)
stroke-attrs)
font-values
@ -59,7 +60,7 @@
text-font-attrs
nil
dwt/current-text-values)
children)
shape-with-children)
text-font-attrs)
align-values
@ -69,7 +70,7 @@
text-align-attrs
nil
dwt/current-paragraph-values)
children)
shape-with-children)
text-align-attrs)
spacing-values
@ -79,7 +80,7 @@
text-spacing-attrs
nil
dwt/current-text-values)
children)
shape-with-children)
text-spacing-attrs)
valign-values
@ -89,7 +90,7 @@
text-valign-attrs
nil
dwt/current-root-values)
children)
shape-with-children)
text-valign-attrs)
decoration-values
@ -99,7 +100,7 @@
text-decoration-attrs
nil
dwt/current-text-values)
children)
shape-with-children)
text-decoration-attrs)
transform-values
@ -109,17 +110,17 @@
text-transform-attrs
nil
dwt/current-text-values)
children)
shape-with-children)
text-transform-attrs)]
[:*
[:& measures-menu {:ids [(:id shape)]
[:& measures-menu {:ids [id]
:type type
:values measure-values}]
[:& fill-menu {:ids child-ids
[:& fill-menu {:ids ids-with-children
:type type
:values fill-values}]
(when-not (empty? other-ids)
[:& stroke-menu {:ids child-ids
[:& stroke-menu {:ids other-ids
:type type
:values stroke-values}])
(when-not (empty? text-ids)