mirror of
https://github.com/penpot/penpot.git
synced 2025-05-15 14:26:38 +02:00
146 lines
3.2 KiB
Clojure
146 lines
3.2 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) KALEIDOS INC
|
|
|
|
(ns app.render-wasm.shape
|
|
(:require
|
|
[app.common.transit :as t]
|
|
[app.common.types.shape :as shape]
|
|
[app.render-wasm.api :as api]
|
|
[clojure.core :as c]
|
|
[cuerdas.core :as str]))
|
|
|
|
(declare ^:private impl-assoc)
|
|
(declare ^:private impl-conj)
|
|
(declare ^:private impl-dissoc)
|
|
|
|
(deftype ShapeProxy [delegate]
|
|
Object
|
|
(toString [coll]
|
|
(str "{" (str/join ", " (for [[k v] coll] (str k " " v))) "}"))
|
|
|
|
(equiv [this other]
|
|
(-equiv this other))
|
|
|
|
;; Marker protocol
|
|
shape/IShape
|
|
|
|
IWithMeta
|
|
(-with-meta [_ meta]
|
|
(ShapeProxy. (with-meta delegate meta)))
|
|
|
|
IMeta
|
|
(-meta [_] (meta delegate))
|
|
|
|
ICollection
|
|
(-conj [coll entry]
|
|
(impl-conj coll entry))
|
|
|
|
IEquiv
|
|
(-equiv [coll other]
|
|
(c/equiv-map coll other))
|
|
|
|
IHash
|
|
(-hash [coll] (hash (into {} coll)))
|
|
|
|
ISequential
|
|
|
|
ISeqable
|
|
(-seq [_]
|
|
(c/-seq delegate))
|
|
|
|
ICounted
|
|
(-count [_]
|
|
(+ 1 (count delegate)))
|
|
|
|
ILookup
|
|
(-lookup [coll k]
|
|
(-lookup coll k nil))
|
|
|
|
(-lookup [_ k not-found]
|
|
(c/-lookup delegate k not-found))
|
|
|
|
IFind
|
|
(-find [_ k]
|
|
(c/-find delegate k))
|
|
|
|
IAssociative
|
|
(-assoc [coll k v]
|
|
(impl-assoc coll k v))
|
|
|
|
(-contains-key? [_ k]
|
|
(contains? delegate k))
|
|
|
|
IMap
|
|
(-dissoc [coll k]
|
|
(impl-dissoc coll k))
|
|
|
|
IFn
|
|
(-invoke [coll k]
|
|
(-lookup coll k))
|
|
|
|
(-invoke [coll k not-found]
|
|
(-lookup coll k not-found))
|
|
|
|
IPrintWithWriter
|
|
(-pr-writer [_ writer _]
|
|
(-write writer (str "#penpot/shape " (:id delegate)))))
|
|
|
|
;; --- SHAPE IMPL
|
|
|
|
(defn- impl-assoc
|
|
[self k v]
|
|
(when ^boolean shape/*wasm-sync*
|
|
(api/use-shape (:id self))
|
|
(case k
|
|
:selrect (api/set-shape-selrect v)
|
|
:rotation (api/set-shape-rotation v)
|
|
:transform (api/set-shape-transform v)
|
|
:fills (api/set-shape-fills v)
|
|
:blend-mode (api/set-shape-blend-mode v)
|
|
:opacity (api/set-shape-opacity v)
|
|
:shapes (api/set-shape-children v)
|
|
nil)
|
|
;; when something synced with wasm
|
|
;; is modified, we need to request
|
|
;; a new render.
|
|
(api/request-render))
|
|
(let [delegate (.-delegate ^ShapeProxy self)
|
|
delegate' (assoc delegate k v)]
|
|
(if (identical? delegate' delegate)
|
|
self
|
|
(ShapeProxy. delegate'))))
|
|
|
|
(defn- impl-dissoc
|
|
[self k]
|
|
(let [delegate (.-delegate ^ShapeProxy self)
|
|
delegate' (dissoc delegate k)]
|
|
(if (identical? delegate delegate')
|
|
self
|
|
(ShapeProxy. delegate'))))
|
|
|
|
(defn- impl-conj
|
|
[self entry]
|
|
(if (vector? entry)
|
|
(-assoc self (-nth entry 0) (-nth entry 1))
|
|
(loop [ret self es (seq entry)]
|
|
(if (nil? es)
|
|
ret
|
|
(let [e (first es)]
|
|
(if (vector? e)
|
|
(recur (-assoc ret (-nth e 0) (-nth e 1))
|
|
(next es))
|
|
(throw (js/Error. "conj on a map takes map entries or seqables of map entries"))))))))
|
|
|
|
(defn create-shape
|
|
"Instanciate a shape from a map"
|
|
[attrs]
|
|
(ShapeProxy. attrs))
|
|
|
|
(t/add-handlers!
|
|
;; We only add a write handler, read handler uses the dynamic dispatch
|
|
{:id "shape"
|
|
:class ShapeProxy
|
|
:wfn #(into {} %)})
|