mirror of
https://github.com/penpot/penpot.git
synced 2025-02-02 04:19:08 -05:00
Merge pull request #1834 from penpot/hirunatan-update-color-library
Synchronize library colors in all parts of a shape
This commit is contained in:
commit
c83bb70074
4 changed files with 298 additions and 180 deletions
|
@ -286,37 +286,38 @@
|
||||||
update-shape
|
update-shape
|
||||||
(fn [changes id]
|
(fn [changes id]
|
||||||
(let [old-obj (get objects id)
|
(let [old-obj (get objects id)
|
||||||
new-obj (update-fn old-obj)
|
new-obj (update-fn old-obj)]
|
||||||
|
(if (= old-obj new-obj)
|
||||||
|
changes
|
||||||
|
(let [attrs (or attrs (d/concat-set (keys old-obj) (keys new-obj)))
|
||||||
|
|
||||||
attrs (or attrs (d/concat-set (keys old-obj) (keys new-obj)))
|
{rops :rops uops :uops}
|
||||||
|
(reduce #(generate-operation %1 %2 old-obj new-obj ignore-geometry?)
|
||||||
|
{:rops [] :uops []}
|
||||||
|
attrs)
|
||||||
|
|
||||||
{rops :rops uops :uops}
|
uops (cond-> uops
|
||||||
(reduce #(generate-operation %1 %2 old-obj new-obj ignore-geometry?)
|
(seq uops)
|
||||||
{:rops [] :uops []}
|
(d/preconj {:type :set-touched :touched (:touched old-obj)}))
|
||||||
attrs)
|
|
||||||
|
|
||||||
uops (cond-> uops
|
change (cond-> {:type :mod-obj
|
||||||
(seq uops)
|
:id id}
|
||||||
(d/preconj {:type :set-touched :touched (:touched old-obj)}))
|
|
||||||
|
|
||||||
change (cond-> {:type :mod-obj
|
(some? page-id)
|
||||||
:id id}
|
(assoc :page-id page-id)
|
||||||
|
|
||||||
(some? page-id)
|
(some? component-id)
|
||||||
(assoc :page-id page-id)
|
(assoc :component-id component-id))]
|
||||||
|
|
||||||
(some? component-id)
|
(cond-> changes
|
||||||
(assoc :component-id component-id))]
|
(seq rops)
|
||||||
|
(update :redo-changes conj (assoc change :operations rops))
|
||||||
|
|
||||||
(cond-> changes
|
(seq uops)
|
||||||
(seq rops)
|
(update :undo-changes d/preconj (assoc change :operations uops)))))))]
|
||||||
(update :redo-changes conj (assoc change :operations rops))
|
|
||||||
|
|
||||||
(seq uops)
|
(-> (reduce update-shape changes ids)
|
||||||
(update :undo-changes d/preconj (assoc change :operations uops)))))]
|
(apply-changes-local)))))
|
||||||
|
|
||||||
(-> (reduce update-shape changes ids)
|
|
||||||
(apply-changes-local)))))
|
|
||||||
|
|
||||||
(defn remove-objects
|
(defn remove-objects
|
||||||
[changes ids]
|
[changes ids]
|
||||||
|
|
|
@ -6,8 +6,10 @@
|
||||||
|
|
||||||
(ns app.common.spec.color
|
(ns app.common.spec.color
|
||||||
(:require
|
(:require
|
||||||
[app.common.spec :as us]
|
[app.common.data :as d]
|
||||||
[clojure.spec.alpha :as s]))
|
[app.common.spec :as us]
|
||||||
|
[app.common.text :as txt]
|
||||||
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
;; TODO: waiting clojure 1.11 to rename this all :internal.stuff to a
|
;; TODO: waiting clojure 1.11 to rename this all :internal.stuff to a
|
||||||
;; more consistent name.
|
;; more consistent name.
|
||||||
|
@ -46,7 +48,7 @@
|
||||||
:internal.gradient/width
|
:internal.gradient/width
|
||||||
:internal.gradient/stops]))
|
:internal.gradient/stops]))
|
||||||
|
|
||||||
;;; --- COLORS
|
;; --- COLORS
|
||||||
|
|
||||||
(s/def :internal.color/name string?)
|
(s/def :internal.color/name string?)
|
||||||
(s/def :internal.color/path (s/nilable string?))
|
(s/def :internal.color/path (s/nilable string?))
|
||||||
|
@ -54,6 +56,15 @@
|
||||||
(s/def :internal.color/color (s/nilable string?))
|
(s/def :internal.color/color (s/nilable string?))
|
||||||
(s/def :internal.color/opacity (s/nilable ::us/safe-number))
|
(s/def :internal.color/opacity (s/nilable ::us/safe-number))
|
||||||
(s/def :internal.color/gradient (s/nilable ::gradient))
|
(s/def :internal.color/gradient (s/nilable ::gradient))
|
||||||
|
(s/def :internal.color/ref-id uuid?)
|
||||||
|
(s/def :internal.color/ref-file uuid?)
|
||||||
|
|
||||||
|
(s/def ::shape-color
|
||||||
|
(s/keys :req-un [:us/color
|
||||||
|
:internal.color/opacity]
|
||||||
|
:opt-un [:internal.color/gradient
|
||||||
|
:internal.color/ref-id
|
||||||
|
:internal.color/ref-file]))
|
||||||
|
|
||||||
(s/def ::color
|
(s/def ::color
|
||||||
(s/keys :opt-un [::id
|
(s/keys :opt-un [::id
|
||||||
|
@ -70,6 +81,197 @@
|
||||||
:internal.color/opacity
|
:internal.color/opacity
|
||||||
:internal.color/gradient]))
|
:internal.color/gradient]))
|
||||||
|
|
||||||
|
;; --- Helpers for color in different parts of a shape
|
||||||
|
|
||||||
|
;; fill
|
||||||
|
|
||||||
|
(defn fill->shape-color
|
||||||
|
[fill]
|
||||||
|
(d/without-nils {:color (:fill-color fill)
|
||||||
|
:opacity (:fill-opacity fill)
|
||||||
|
:gradient (:fill-color-gradient fill)
|
||||||
|
:ref-id (:fill-color-ref-id fill)
|
||||||
|
:ref-file (:fill-color-ref-file fill)}))
|
||||||
|
|
||||||
|
(defn set-fill-color
|
||||||
|
[shape position color opacity gradient]
|
||||||
|
(update-in shape [:fills position]
|
||||||
|
(fn [fill]
|
||||||
|
(d/without-nils (assoc fill
|
||||||
|
:fill-color color
|
||||||
|
:fill-opacity opacity
|
||||||
|
:fill-color-gradient gradient)))))
|
||||||
|
|
||||||
|
(defn detach-fill-color
|
||||||
|
[shape position]
|
||||||
|
(-> shape
|
||||||
|
(d/dissoc-in [:fills position :fill-color-ref-id])
|
||||||
|
(d/dissoc-in [:fills position :fill-color-ref-file])))
|
||||||
|
|
||||||
|
;; stroke
|
||||||
|
|
||||||
|
(defn stroke->shape-color
|
||||||
|
[stroke]
|
||||||
|
(d/without-nils {:color (:stroke-color stroke)
|
||||||
|
:opacity (:stroke-opacity stroke)
|
||||||
|
:gradient (:stroke-color-gradient stroke)
|
||||||
|
:ref-id (:stroke-color-ref-id stroke)
|
||||||
|
:ref-file (:stroke-color-ref-file stroke)}))
|
||||||
|
|
||||||
|
(defn set-stroke-color
|
||||||
|
[shape position color opacity gradient]
|
||||||
|
(update-in shape [:strokes position]
|
||||||
|
(fn [stroke]
|
||||||
|
(d/without-nils (assoc stroke
|
||||||
|
:stroke-color color
|
||||||
|
:stroke-opacity opacity
|
||||||
|
:stroke-color-gradient gradient)))))
|
||||||
|
|
||||||
|
(defn detach-stroke-color
|
||||||
|
[shape position]
|
||||||
|
(-> shape
|
||||||
|
(d/dissoc-in [:strokes position :stroke-color-ref-id])
|
||||||
|
(d/dissoc-in [:strokes position :stroke-color-ref-file])))
|
||||||
|
|
||||||
|
;; shadow
|
||||||
|
|
||||||
|
(defn shadow->shape-color
|
||||||
|
[shadow]
|
||||||
|
(d/without-nils {:color (-> shadow :color :color)
|
||||||
|
:opacity (-> shadow :color :opacity)
|
||||||
|
:gradient (-> shadow :color :gradient)
|
||||||
|
:ref-id (-> shadow :color :id)
|
||||||
|
:ref-file (-> shadow :color :file-id)}))
|
||||||
|
|
||||||
|
(defn set-shadow-color
|
||||||
|
[shape position color opacity gradient]
|
||||||
|
(update-in shape [:shadow position :color]
|
||||||
|
(fn [shadow-color]
|
||||||
|
(d/without-nils (assoc shadow-color
|
||||||
|
:color color
|
||||||
|
:opacity opacity
|
||||||
|
:gradient gradient)))))
|
||||||
|
|
||||||
|
(defn detach-shadow-color
|
||||||
|
[shape position]
|
||||||
|
(-> shape
|
||||||
|
(d/dissoc-in [:shadow position :color :id])
|
||||||
|
(d/dissoc-in [:shadow position :color :file-id])))
|
||||||
|
|
||||||
|
;; grid
|
||||||
|
|
||||||
|
(defn grid->shape-color
|
||||||
|
[grid]
|
||||||
|
(d/without-nils {:color (-> grid :params :color :color)
|
||||||
|
:opacity (-> grid :params :color :opacity)
|
||||||
|
:gradient (-> grid :params :color :gradient)
|
||||||
|
:ref-id (-> grid :params :color :id)
|
||||||
|
:ref-file (-> grid :params :color :file-id)}))
|
||||||
|
|
||||||
|
(defn set-grid-color
|
||||||
|
[shape position color opacity gradient]
|
||||||
|
(update-in shape [:grids position :params :color]
|
||||||
|
(fn [grid-color]
|
||||||
|
(d/without-nils (assoc grid-color
|
||||||
|
:color color
|
||||||
|
:opacity opacity
|
||||||
|
:gradient gradient)))))
|
||||||
|
|
||||||
|
(defn detach-grid-color
|
||||||
|
[shape position]
|
||||||
|
(-> shape
|
||||||
|
(d/dissoc-in [:grids position :params :color :id])
|
||||||
|
(d/dissoc-in [:grids position :params :color :file-id])))
|
||||||
|
|
||||||
|
;; --- Helpers for all colors in a shape
|
||||||
|
|
||||||
|
(defn get-text-node-colors
|
||||||
|
"Get all colors used by a node of a text shape"
|
||||||
|
[node]
|
||||||
|
(concat (map fill->shape-color (:fills node))
|
||||||
|
(map stroke->shape-color (:strokes node))))
|
||||||
|
|
||||||
|
(defn get-all-colors
|
||||||
|
"Get all colors used by a shape, in any section."
|
||||||
|
[shape]
|
||||||
|
(concat (map fill->shape-color (:fills shape))
|
||||||
|
(map stroke->shape-color (:strokes shape))
|
||||||
|
(map shadow->shape-color (:shadow shape))
|
||||||
|
(when (= (:type shape) :frame)
|
||||||
|
(map grid->shape-color (:grids shape)))
|
||||||
|
(when (= (:type shape) :text)
|
||||||
|
(reduce (fn [colors node]
|
||||||
|
(concat colors (get-text-node-colors node)))
|
||||||
|
()
|
||||||
|
(txt/node-seq (:content shape))))))
|
||||||
|
|
||||||
|
(defn uses-library-colors?
|
||||||
|
"Check if the shape uses any color in the given library."
|
||||||
|
[shape library-id]
|
||||||
|
(let [all-colors (get-all-colors shape)]
|
||||||
|
(some #(and (some? (:ref-id %))
|
||||||
|
(= (:ref-file %) library-id))
|
||||||
|
all-colors)))
|
||||||
|
|
||||||
|
(defn sync-shape-colors
|
||||||
|
"Look for usage of any color of the given library inside the shape,
|
||||||
|
and, in this case, copy the library color into the shape."
|
||||||
|
[shape library-id library-colors]
|
||||||
|
(let [sync-color (fn [shape position shape-color set-fn detach-fn]
|
||||||
|
(if (= (:ref-file shape-color) library-id)
|
||||||
|
(let [library-color (get library-colors (:ref-id shape-color))]
|
||||||
|
(if (some? library-color)
|
||||||
|
(set-fn shape
|
||||||
|
position
|
||||||
|
(:color library-color)
|
||||||
|
(:opacity library-color)
|
||||||
|
(:gradient library-color))
|
||||||
|
(detach-fn shape position)))
|
||||||
|
shape))
|
||||||
|
|
||||||
|
sync-fill (fn [shape [position fill]]
|
||||||
|
(sync-color shape
|
||||||
|
position
|
||||||
|
(fill->shape-color fill)
|
||||||
|
set-fill-color
|
||||||
|
detach-fill-color))
|
||||||
|
|
||||||
|
sync-stroke (fn [shape [position stroke]]
|
||||||
|
(sync-color shape
|
||||||
|
position
|
||||||
|
(stroke->shape-color stroke)
|
||||||
|
set-stroke-color
|
||||||
|
detach-stroke-color))
|
||||||
|
|
||||||
|
sync-shadow (fn [shape [position shadow]]
|
||||||
|
(sync-color shape
|
||||||
|
position
|
||||||
|
(shadow->shape-color shadow)
|
||||||
|
set-shadow-color
|
||||||
|
detach-shadow-color))
|
||||||
|
|
||||||
|
sync-grid (fn [shape [position grid]]
|
||||||
|
(sync-color shape
|
||||||
|
position
|
||||||
|
(grid->shape-color grid)
|
||||||
|
set-grid-color
|
||||||
|
detach-grid-color))
|
||||||
|
|
||||||
|
sync-text-node (fn [node]
|
||||||
|
(as-> node $
|
||||||
|
(reduce sync-fill $ (d/enumerate (:fills $)))
|
||||||
|
(reduce sync-stroke $ (d/enumerate (:strokes $)))))
|
||||||
|
|
||||||
|
sync-text (fn [shape]
|
||||||
|
(let [content (:content shape)
|
||||||
|
new-content (txt/transform-nodes sync-text-node content)]
|
||||||
|
(if (not= content new-content)
|
||||||
|
(assoc shape :content new-content)
|
||||||
|
shape)))]
|
||||||
|
|
||||||
|
(as-> shape $
|
||||||
|
(reduce sync-fill $ (d/enumerate (:fills $)))
|
||||||
|
(reduce sync-stroke $ (d/enumerate (:strokes $)))
|
||||||
|
(reduce sync-shadow $ (d/enumerate (:shadow $)))
|
||||||
|
(reduce sync-grid $ (d/enumerate (:grids $)))
|
||||||
|
(sync-text $))))
|
||||||
|
|
|
@ -166,11 +166,11 @@
|
||||||
::blocked
|
::blocked
|
||||||
::collapsed
|
::collapsed
|
||||||
::fills
|
::fills
|
||||||
::fill-color
|
::fill-color ;; TODO: remove these attributes
|
||||||
::fill-opacity
|
::fill-opacity ;; when backward compatibility
|
||||||
::fill-color-gradient
|
::fill-color-gradient ;; is no longer needed
|
||||||
::fill-color-ref-file
|
::fill-color-ref-file ;;
|
||||||
::fill-color-ref-id
|
::fill-color-ref-id ;;
|
||||||
::hide-fill-on-export
|
::hide-fill-on-export
|
||||||
::font-family
|
::font-family
|
||||||
::font-size
|
::font-size
|
||||||
|
@ -196,10 +196,10 @@
|
||||||
::exports
|
::exports
|
||||||
::shapes
|
::shapes
|
||||||
::strokes
|
::strokes
|
||||||
::stroke-color
|
::stroke-color ;; TODO: same thing
|
||||||
::stroke-color-ref-file
|
::stroke-color-ref-file ;;
|
||||||
::stroke-color-ref-id
|
::stroke-color-ref-i ;;
|
||||||
::stroke-opacity
|
::stroke-opacity ;;
|
||||||
::stroke-style
|
::stroke-style
|
||||||
::stroke-width
|
::stroke-width
|
||||||
::stroke-alignment
|
::stroke-alignment
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
[app.common.pages.changes-builder :as pcb]
|
[app.common.pages.changes-builder :as pcb]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
|
[app.common.spec.color :as color]
|
||||||
[app.common.text :as txt]
|
[app.common.text :as txt]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.groups :as dwg]
|
[app.main.data.workspace.groups :as dwg]
|
||||||
|
@ -24,18 +25,10 @@
|
||||||
;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default
|
;; Change this to :info :debug or :trace to debug this module, or :warn to reset to default
|
||||||
(log/set-level! :warn)
|
(log/set-level! :warn)
|
||||||
|
|
||||||
(defonce color-sync-attrs
|
|
||||||
[[:fill-color-ref-id :fill-color-ref-file :color :fill-color]
|
|
||||||
[:fill-color-ref-id :fill-color-ref-file :gradient :fill-color-gradient]
|
|
||||||
[:fill-color-ref-id :fill-color-ref-file :opacity :fill-opacity]
|
|
||||||
|
|
||||||
[:stroke-color-ref-id :stroke-color-ref-file :color :stroke-color]
|
|
||||||
[:stroke-color-ref-id :stroke-color-ref-file :gradient :stroke-color-gradient]
|
|
||||||
[:stroke-color-ref-id :stroke-color-ref-file :opacity :stroke-opacity]])
|
|
||||||
|
|
||||||
(declare generate-sync-container)
|
(declare generate-sync-container)
|
||||||
(declare generate-sync-shape)
|
(declare generate-sync-shape)
|
||||||
(declare has-asset-reference-fn)
|
(declare generate-sync-text-shape)
|
||||||
|
(declare uses-assets?)
|
||||||
|
|
||||||
(declare get-assets)
|
(declare get-assets)
|
||||||
(declare generate-sync-shape-direct)
|
(declare generate-sync-shape-direct)
|
||||||
|
@ -60,7 +53,7 @@
|
||||||
"<local>"
|
"<local>"
|
||||||
(str "<" (get-in state [:workspace-libraries file-id :name]) ">")))
|
(str "<" (get-in state [:workspace-libraries file-id :name]) ">")))
|
||||||
|
|
||||||
;; ---- Create a new component ----
|
;; ---- Components and instances creation ----
|
||||||
|
|
||||||
(defn make-component-shape
|
(defn make-component-shape
|
||||||
"Clone the shape and all children. Generate new ids and detach
|
"Clone the shape and all children. Generate new ids and detach
|
||||||
|
@ -278,9 +271,8 @@
|
||||||
(log/debug :msg "Sync page in local file" :page-id (:id container))
|
(log/debug :msg "Sync page in local file" :page-id (:id container))
|
||||||
(log/debug :msg "Sync component in local library" :component-id (:id container)))
|
(log/debug :msg "Sync component in local library" :component-id (:id container)))
|
||||||
|
|
||||||
(let [has-asset-reference? (has-asset-reference-fn asset-type library-id (cph/page? container))
|
(let [linked-shapes (->> (vals (:objects container))
|
||||||
linked-shapes (->> (vals (:objects container))
|
(filter #(uses-assets? asset-type % library-id (cph/page? container))))]
|
||||||
(filter has-asset-reference?))]
|
|
||||||
(loop [shapes (seq linked-shapes)
|
(loop [shapes (seq linked-shapes)
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
(pcb/with-container container)
|
(pcb/with-container container)
|
||||||
|
@ -295,49 +287,34 @@
|
||||||
shape))
|
shape))
|
||||||
changes))))
|
changes))))
|
||||||
|
|
||||||
(defn- has-asset-reference-fn
|
(defmulti uses-assets?
|
||||||
"Gets a function that checks if a shape uses some asset of the given type
|
"Checks if a shape uses some asset of the given type in the given library."
|
||||||
in the given library."
|
(fn [asset-type _ _ _] asset-type))
|
||||||
[asset-type library-id page?]
|
|
||||||
(case asset-type
|
|
||||||
:components
|
|
||||||
(fn [shape] (and (:component-id shape)
|
|
||||||
(or (:component-root? shape) (not page?))
|
|
||||||
(= (:component-file shape) library-id)))
|
|
||||||
|
|
||||||
:colors
|
(defmethod uses-assets? :components
|
||||||
(fn [shape]
|
[_ shape library-id page?]
|
||||||
(if (= (:type shape) :text)
|
(and (some? (:component-id shape))
|
||||||
(->> shape
|
(= (:component-file shape) library-id)
|
||||||
:content
|
(or (:component-root? shape) (not page?)))) ; avoid nested components inside pages
|
||||||
;; Check if any node in the content has a reference for the library
|
|
||||||
(txt/node-seq
|
|
||||||
#(or (and (some? (:stroke-color-ref-id %))
|
|
||||||
(= library-id (:stroke-color-ref-file %)))
|
|
||||||
(and (some? (:fill-color-ref-id %))
|
|
||||||
(= library-id (:fill-color-ref-file %))))))
|
|
||||||
(some
|
|
||||||
#(let [attr (name %)
|
|
||||||
attr-ref-id (keyword (str attr "-ref-id"))
|
|
||||||
attr-ref-file (keyword (str attr "-ref-file"))]
|
|
||||||
(and (get shape attr-ref-id)
|
|
||||||
(= library-id (get shape attr-ref-file))))
|
|
||||||
(map #(nth % 3) color-sync-attrs))))
|
|
||||||
|
|
||||||
:typographies
|
(defmethod uses-assets? :colors
|
||||||
(fn [shape]
|
[_ shape library-id _]
|
||||||
(and (= (:type shape) :text)
|
(color/uses-library-colors? shape library-id))
|
||||||
(->> shape
|
|
||||||
:content
|
(defmethod uses-assets? :typographies
|
||||||
;; Check if any node in the content has a reference for the library
|
[_ shape library-id _]
|
||||||
(txt/node-seq
|
(and (= (:type shape) :text)
|
||||||
#(and (some? (:typography-ref-id %))
|
(->> shape
|
||||||
(= library-id (:typography-ref-file %)))))))))
|
:content
|
||||||
|
;; Check if any node in the content has a reference for the library
|
||||||
|
(txt/node-seq
|
||||||
|
#(and (some? (:typography-ref-id %))
|
||||||
|
(= (:typography-ref-file %) library-id))))))
|
||||||
|
|
||||||
(defmulti generate-sync-shape
|
(defmulti generate-sync-shape
|
||||||
"Generate changes to synchronize one shape with all assets of the given type
|
"Generate changes to synchronize one shape from all assets of the given type
|
||||||
that is using, in the given library."
|
that is using, in the given library."
|
||||||
(fn [type _changes _library-id _state _container _shape] type))
|
(fn [asset-type _changes _library-id _state _container _shape] asset-type))
|
||||||
|
|
||||||
(defmethod generate-sync-shape :components
|
(defmethod generate-sync-shape :components
|
||||||
[_ changes _library-id state container shape]
|
[_ changes _library-id state container shape]
|
||||||
|
@ -345,6 +322,37 @@
|
||||||
libraries (wsh/get-libraries state)]
|
libraries (wsh/get-libraries state)]
|
||||||
(generate-sync-shape-direct changes libraries container shape-id false)))
|
(generate-sync-shape-direct changes libraries container shape-id false)))
|
||||||
|
|
||||||
|
(defmethod generate-sync-shape :colors
|
||||||
|
[_ changes library-id state _ shape]
|
||||||
|
(log/debug :msg "Sync colors of shape" :shape (:name shape))
|
||||||
|
|
||||||
|
;; Synchronize a shape that uses some colors of the library. The value of the
|
||||||
|
;; color in the library is copied to the shape.
|
||||||
|
(let [library-colors (get-assets library-id :colors state)]
|
||||||
|
(pcb/update-shapes changes
|
||||||
|
[(:id shape)]
|
||||||
|
#(color/sync-shape-colors % library-id library-colors))))
|
||||||
|
|
||||||
|
(defmethod generate-sync-shape :typographies
|
||||||
|
[_ changes library-id state container shape]
|
||||||
|
(log/debug :msg "Sync typographies of shape" :shape (:name shape))
|
||||||
|
|
||||||
|
;; Synchronize a shape that uses some typographies of the library. The attributes
|
||||||
|
;; of the typography are copied to the shape."
|
||||||
|
(let [typographies (get-assets library-id :typographies state)
|
||||||
|
update-node (fn [node]
|
||||||
|
(if-let [typography (get typographies (:typography-ref-id node))]
|
||||||
|
(merge node (dissoc typography :name :id))
|
||||||
|
(dissoc node :typography-ref-id
|
||||||
|
:typography-ref-file)))]
|
||||||
|
(generate-sync-text-shape changes shape container update-node)))
|
||||||
|
|
||||||
|
(defn- get-assets
|
||||||
|
[library-id asset-type state]
|
||||||
|
(if (= library-id (:current-file-id state))
|
||||||
|
(get-in state [:workspace-data asset-type])
|
||||||
|
(get-in state [:workspace-libraries library-id :data asset-type])))
|
||||||
|
|
||||||
(defn- generate-sync-text-shape
|
(defn- generate-sync-text-shape
|
||||||
[changes shape container update-node]
|
[changes shape container update-node]
|
||||||
(let [old-content (:content shape)
|
(let [old-content (:content shape)
|
||||||
|
@ -368,99 +376,6 @@
|
||||||
changes
|
changes
|
||||||
changes')))
|
changes')))
|
||||||
|
|
||||||
(defmethod generate-sync-shape :colors
|
|
||||||
[_ changes library-id state container shape]
|
|
||||||
(log/debug :msg "Sync colors of shape" :shape (:name shape))
|
|
||||||
|
|
||||||
;; Synchronize a shape that uses some colors of the library. The value of the
|
|
||||||
;; color in the library is copied to the shape.
|
|
||||||
(let [colors (get-assets library-id :colors state)]
|
|
||||||
(if (= :text (:type shape))
|
|
||||||
(let [update-node (fn [node]
|
|
||||||
(if-let [color (get colors (:fill-color-ref-id node))]
|
|
||||||
(assoc node
|
|
||||||
:fill-color (:color color)
|
|
||||||
:fill-opacity (:opacity color)
|
|
||||||
:fill-color-gradient (:gradient color))
|
|
||||||
(assoc node
|
|
||||||
:fill-color-ref-id nil
|
|
||||||
:fill-color-ref-file nil)))]
|
|
||||||
(generate-sync-text-shape changes shape container update-node))
|
|
||||||
(loop [attrs (seq color-sync-attrs)
|
|
||||||
roperations []
|
|
||||||
uoperations []]
|
|
||||||
(let [[attr-ref-id attr-ref-file color-attr attr] (first attrs)]
|
|
||||||
(if (nil? attr)
|
|
||||||
(if (empty? roperations)
|
|
||||||
changes
|
|
||||||
(-> changes
|
|
||||||
(update :redo-changes (make-change
|
|
||||||
container
|
|
||||||
{:type :mod-obj
|
|
||||||
:id (:id shape)
|
|
||||||
:operations roperations}))
|
|
||||||
(update :undo-changes (make-change
|
|
||||||
container
|
|
||||||
{:type :mod-obj
|
|
||||||
:id (:id shape)
|
|
||||||
:operations uoperations}))))
|
|
||||||
(if-not (contains? shape attr-ref-id)
|
|
||||||
(recur (next attrs)
|
|
||||||
roperations
|
|
||||||
uoperations)
|
|
||||||
(let [color (get colors (get shape attr-ref-id))
|
|
||||||
roperations' (if color
|
|
||||||
[{:type :set
|
|
||||||
:attr attr
|
|
||||||
:val (color-attr color)
|
|
||||||
:ignore-touched true}]
|
|
||||||
;; If the referenced color does no longer exist in the library,
|
|
||||||
;; we must unlink the color in the shape
|
|
||||||
[{:type :set
|
|
||||||
:attr attr-ref-id
|
|
||||||
:val nil
|
|
||||||
:ignore-touched true}
|
|
||||||
{:type :set
|
|
||||||
:attr attr-ref-file
|
|
||||||
:val nil
|
|
||||||
:ignore-touched true}])
|
|
||||||
uoperations' (if color
|
|
||||||
[{:type :set
|
|
||||||
:attr attr
|
|
||||||
:val (get shape attr)
|
|
||||||
:ignore-touched true}]
|
|
||||||
[{:type :set
|
|
||||||
:attr attr-ref-id
|
|
||||||
:val (get shape attr-ref-id)
|
|
||||||
:ignore-touched true}
|
|
||||||
{:type :set
|
|
||||||
:attr attr-ref-file
|
|
||||||
:val (get shape attr-ref-file)
|
|
||||||
:ignore-touched true}])]
|
|
||||||
(recur (next attrs)
|
|
||||||
(into roperations roperations')
|
|
||||||
(into uoperations uoperations'))))))))))
|
|
||||||
|
|
||||||
(defmethod generate-sync-shape :typographies
|
|
||||||
[_ changes library-id state container shape]
|
|
||||||
(log/debug :msg "Sync typographies of shape" :shape (:name shape))
|
|
||||||
|
|
||||||
;; Synchronize a shape that uses some typographies of the library. The attributes
|
|
||||||
;; of the typography are copied to the shape."
|
|
||||||
(let [typographies (get-assets library-id :typographies state)
|
|
||||||
update-node (fn [node]
|
|
||||||
(if-let [typography (get typographies (:typography-ref-id node))]
|
|
||||||
(merge node (dissoc typography :name :id))
|
|
||||||
(dissoc node :typography-ref-id
|
|
||||||
:typography-ref-file)))]
|
|
||||||
(generate-sync-text-shape changes shape container update-node)))
|
|
||||||
|
|
||||||
(defn- get-assets
|
|
||||||
[library-id asset-type state]
|
|
||||||
(if (= library-id (:current-file-id state))
|
|
||||||
(get-in state [:workspace-data asset-type])
|
|
||||||
(get-in state [:workspace-libraries library-id :data asset-type])))
|
|
||||||
|
|
||||||
|
|
||||||
;; ---- Component synchronization helpers ----
|
;; ---- Component synchronization helpers ----
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue