mirror of
https://github.com/penpot/penpot.git
synced 2025-05-11 09:36:38 +02:00
🎉 Scaffolding to write unit tests of common types
This commit is contained in:
parent
165cdd871f
commit
54e0071c9c
35 changed files with 724 additions and 228 deletions
|
@ -11,6 +11,7 @@
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
[app.common.pages.migrations :as pmg]
|
[app.common.pages.migrations :as pmg]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
|
[app.common.types.file :as ctf]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.db :as db]
|
[app.db :as db]
|
||||||
|
@ -69,7 +70,7 @@
|
||||||
:or {is-shared false revn 0}
|
:or {is-shared false revn 0}
|
||||||
:as params}]
|
:as params}]
|
||||||
(let [id (or id (:id data) (uuid/next))
|
(let [id (or id (:id data) (uuid/next))
|
||||||
data (or data (cp/make-file-data id))
|
data (or data (ctf/make-file-data id))
|
||||||
file (db/insert! conn :file
|
file (db/insert! conn :file
|
||||||
(d/without-nils
|
(d/without-nils
|
||||||
{:id id
|
{:id id
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.pages.migrations :as pmg]
|
[app.common.pages.migrations :as pmg]
|
||||||
[app.common.types.shape-tree :as ctt]
|
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
|
[app.common.types.shape-tree :as ctt]
|
||||||
[app.db :as db]
|
[app.db :as db]
|
||||||
[app.db.sql :as sql]
|
[app.db.sql :as sql]
|
||||||
[app.rpc.helpers :as rpch]
|
[app.rpc.helpers :as rpch]
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.logging :as l]
|
[app.common.logging :as l]
|
||||||
[app.common.pages.helpers :as cph]
|
|
||||||
[app.common.pages.migrations :as pmg]
|
[app.common.pages.migrations :as pmg]
|
||||||
[app.common.types.shape-tree :as ctt]
|
[app.common.types.shape-tree :as ctt]
|
||||||
[app.db :as db]
|
[app.db :as db]
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages.changes :as ch]
|
[app.common.pages.changes :as ch]
|
||||||
[app.common.pages.changes-spec :as pcs]
|
[app.common.pages.changes-spec :as pcs]
|
||||||
[app.common.pages.init :as init]
|
|
||||||
[app.common.types.page :as ctp]
|
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
|
[app.common.types.file :as ctf]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
|
[app.common.types.shape :as cts]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]))
|
||||||
|
|
||||||
|
@ -169,7 +169,7 @@
|
||||||
([id name]
|
([id name]
|
||||||
{:id id
|
{:id id
|
||||||
:name name
|
:name name
|
||||||
:data (-> init/empty-file-data
|
:data (-> ctf/empty-file-data
|
||||||
(assoc :id id))
|
(assoc :id id))
|
||||||
|
|
||||||
;; We keep the changes so we can send them to the backend
|
;; We keep the changes so we can send them to the backend
|
||||||
|
@ -209,7 +209,7 @@
|
||||||
|
|
||||||
(defn add-artboard [file data]
|
(defn add-artboard [file data]
|
||||||
(assert (nil? (:current-component-id file)))
|
(assert (nil? (:current-component-id file)))
|
||||||
(let [obj (-> (init/make-minimal-shape :frame)
|
(let [obj (-> (cts/make-minimal-shape :frame)
|
||||||
(merge data)
|
(merge data)
|
||||||
(check-name file :frame)
|
(check-name file :frame)
|
||||||
(setup-selrect)
|
(setup-selrect)
|
||||||
|
@ -233,9 +233,9 @@
|
||||||
|
|
||||||
(defn add-group [file data]
|
(defn add-group [file data]
|
||||||
(let [frame-id (:current-frame-id file)
|
(let [frame-id (:current-frame-id file)
|
||||||
selrect init/empty-selrect
|
selrect cts/empty-selrect
|
||||||
name (:name data)
|
name (:name data)
|
||||||
obj (-> (init/make-minimal-group frame-id selrect name)
|
obj (-> (cts/make-minimal-group frame-id selrect name)
|
||||||
(merge data)
|
(merge data)
|
||||||
(check-name file :group)
|
(check-name file :group)
|
||||||
(d/without-nils))]
|
(d/without-nils))]
|
||||||
|
@ -347,7 +347,7 @@
|
||||||
(update :parent-stack pop))))
|
(update :parent-stack pop))))
|
||||||
|
|
||||||
(defn create-shape [file type data]
|
(defn create-shape [file type data]
|
||||||
(let [obj (-> (init/make-minimal-shape type)
|
(let [obj (-> (cts/make-minimal-shape type)
|
||||||
(merge data)
|
(merge data)
|
||||||
(check-name file :type)
|
(check-name file :type)
|
||||||
(setup-selrect)
|
(setup-selrect)
|
||||||
|
@ -515,10 +515,10 @@
|
||||||
(defn start-component
|
(defn start-component
|
||||||
[file data]
|
[file data]
|
||||||
|
|
||||||
(let [selrect init/empty-selrect
|
(let [selrect cts/empty-selrect
|
||||||
name (:name data)
|
name (:name data)
|
||||||
path (:path data)
|
path (:path data)
|
||||||
obj (-> (init/make-minimal-group nil selrect name)
|
obj (-> (cts/make-minimal-group nil selrect name)
|
||||||
(merge data)
|
(merge data)
|
||||||
(check-name file :group)
|
(check-name file :group)
|
||||||
(d/without-nils))]
|
(d/without-nils))]
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
[app.common.pages.common :as common]
|
[app.common.pages.common :as common]
|
||||||
[app.common.pages.focus :as focus]
|
[app.common.pages.focus :as focus]
|
||||||
[app.common.pages.indices :as indices]
|
[app.common.pages.indices :as indices]
|
||||||
[app.common.pages.init :as init]))
|
[app.common.types.file :as ctf]))
|
||||||
|
|
||||||
;; Common
|
;; Common
|
||||||
(dm/export common/root)
|
(dm/export common/root)
|
||||||
|
@ -36,11 +36,5 @@
|
||||||
(dm/export changes/process-changes)
|
(dm/export changes/process-changes)
|
||||||
|
|
||||||
;; Initialization
|
;; Initialization
|
||||||
(dm/export init/default-frame-attrs)
|
(dm/export ctf/make-file-data)
|
||||||
(dm/export init/default-shape-attrs)
|
(dm/export ctf/empty-file-data)
|
||||||
(dm/export init/make-file-data)
|
|
||||||
(dm/export init/make-minimal-shape)
|
|
||||||
(dm/export init/make-minimal-group)
|
|
||||||
(dm/export init/empty-file-data)
|
|
||||||
(dm/export init/setup-shape)
|
|
||||||
(dm/export init/setup-rect-selrect)
|
|
||||||
|
|
|
@ -14,9 +14,9 @@
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages.common :refer [component-sync-attrs]]
|
[app.common.pages.common :refer [component-sync-attrs]]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.pages.init :as init]
|
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.pages.changes-spec :as pcs]
|
[app.common.pages.changes-spec :as pcs]
|
||||||
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
[app.common.types.pages-list :as ctpl]
|
[app.common.types.pages-list :as ctpl]
|
||||||
[app.common.types.shape :as cts]
|
[app.common.types.shape :as cts]
|
||||||
|
@ -346,13 +346,13 @@
|
||||||
|
|
||||||
(defmethod process-change :add-component
|
(defmethod process-change :add-component
|
||||||
[data {:keys [id name path main-instance-id main-instance-page shapes]}]
|
[data {:keys [id name path main-instance-id main-instance-page shapes]}]
|
||||||
(assoc-in data [:components id]
|
(ctkl/add-component data
|
||||||
{:id id
|
id
|
||||||
:name name
|
name
|
||||||
:path path
|
path
|
||||||
:main-instance-id main-instance-id
|
main-instance-id
|
||||||
:main-instance-page main-instance-page
|
main-instance-page
|
||||||
:objects (d/index-by :id shapes)}))
|
shapes))
|
||||||
|
|
||||||
(defmethod process-change :mod-component
|
(defmethod process-change :mod-component
|
||||||
[data {:keys [id name path objects]}]
|
[data {:keys [id name path objects]}]
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
|
[app.common.types.file :as ctf]
|
||||||
[app.common.uuid :as uuid]))
|
[app.common.uuid :as uuid]))
|
||||||
|
|
||||||
;; Auxiliary functions to help create a set of changes (undo + redo)
|
;; Auxiliary functions to help create a set of changes (undo + redo)
|
||||||
|
@ -49,7 +50,7 @@
|
||||||
|
|
||||||
(defn with-objects
|
(defn with-objects
|
||||||
[changes objects]
|
[changes objects]
|
||||||
(let [file-data (-> (cp/make-file-data (uuid/next) uuid/zero)
|
(let [file-data (-> (ctf/make-file-data (uuid/next) uuid/zero)
|
||||||
(assoc-in [:pages-index uuid/zero :objects] objects))]
|
(assoc-in [:pages-index uuid/zero :objects] objects))]
|
||||||
(vary-meta changes assoc ::file-data file-data
|
(vary-meta changes assoc ::file-data file-data
|
||||||
::applied-changes-count 0)))
|
::applied-changes-count 0)))
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.geom.shapes.path :as gsp]
|
[app.common.geom.shapes.path :as gsp]
|
||||||
[app.common.geom.shapes.text :as gsht]
|
[app.common.geom.shapes.text :as gsht]
|
||||||
|
@ -16,9 +15,10 @@
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.types.container :as ctc]
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
[app.common.types.pages-list :as ctpl]
|
[app.common.types.pages-list :as ctpl]
|
||||||
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]))
|
||||||
|
@ -89,7 +89,7 @@
|
||||||
|
|
||||||
(fix-empty-points [shape]
|
(fix-empty-points [shape]
|
||||||
(let [shape (cond-> shape
|
(let [shape (cond-> shape
|
||||||
(empty? (:selrect shape)) (cp/setup-rect-selrect))]
|
(empty? (:selrect shape)) (cts/setup-rect-selrect))]
|
||||||
(cond-> shape
|
(cond-> shape
|
||||||
(empty? (:points shape))
|
(empty? (:points shape))
|
||||||
(assoc :points (gsh/rect->points (:selrect shape))))))
|
(assoc :points (gsh/rect->points (:selrect shape))))))
|
||||||
|
@ -456,7 +456,7 @@
|
||||||
(let [page (ctpl/get-page data page-id)
|
(let [page (ctpl/get-page data page-id)
|
||||||
|
|
||||||
[new-shape new-shapes]
|
[new-shape new-shapes]
|
||||||
(ctc/instantiate-component page
|
(ctn/instantiate-component page
|
||||||
component
|
component
|
||||||
(:id data)
|
(:id data)
|
||||||
position)
|
position)
|
||||||
|
|
28
common/src/app/common/types/components_list.cljc
Normal file
28
common/src/app/common/types/components_list.cljc
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
;; 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) UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns app.common.types.components-list
|
||||||
|
(:require
|
||||||
|
[app.common.data :as d]))
|
||||||
|
|
||||||
|
(defn components-seq
|
||||||
|
[file-data]
|
||||||
|
(vals (:components file-data)))
|
||||||
|
|
||||||
|
(defn add-component
|
||||||
|
[file-data id name path main-instance-id main-instance-page shapes]
|
||||||
|
(assoc-in file-data [:components id]
|
||||||
|
{:id id
|
||||||
|
:name name
|
||||||
|
:path path
|
||||||
|
:main-instance-id main-instance-id
|
||||||
|
:main-instance-page main-instance-page
|
||||||
|
:objects (d/index-by :id shapes)}))
|
||||||
|
|
||||||
|
(defn get-component
|
||||||
|
[file-data component-id]
|
||||||
|
(get-in file-data [:components component-id]))
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.types.shape-tree :as ctt]
|
[app.common.types.shape-tree :as ctst]
|
||||||
[clojure.spec.alpha :as s]))
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
(s/def ::type #{:page :component})
|
(s/def ::type #{:page :component})
|
||||||
|
@ -18,9 +18,32 @@
|
||||||
(s/def ::path (s/nilable string?))
|
(s/def ::path (s/nilable string?))
|
||||||
|
|
||||||
(s/def ::container
|
(s/def ::container
|
||||||
(s/keys :req-un [::id ::name ::ctt/objects]
|
(s/keys :req-un [::id ::name ::ctst/objects]
|
||||||
:opt-un [::type ::path]))
|
:opt-un [::type ::path]))
|
||||||
|
|
||||||
|
(defn make-container
|
||||||
|
[page-or-component type]
|
||||||
|
(assoc page-or-component :type type))
|
||||||
|
|
||||||
|
(defn page?
|
||||||
|
[container]
|
||||||
|
(= (:type container) :page))
|
||||||
|
|
||||||
|
(defn component?
|
||||||
|
[container]
|
||||||
|
(= (:type container) :component))
|
||||||
|
|
||||||
|
(defn get-container
|
||||||
|
[file type id]
|
||||||
|
(us/assert map? file)
|
||||||
|
(us/assert ::type type)
|
||||||
|
(us/assert uuid? id)
|
||||||
|
|
||||||
|
(-> (if (= type :page)
|
||||||
|
(get-in file [:pages-index id])
|
||||||
|
(get-in file [:components id]))
|
||||||
|
(assoc :type type)))
|
||||||
|
|
||||||
(defn get-shape
|
(defn get-shape
|
||||||
[container shape-id]
|
[container shape-id]
|
||||||
(us/assert ::container container)
|
(us/assert ::container container)
|
||||||
|
@ -29,21 +52,65 @@
|
||||||
(get :objects)
|
(get :objects)
|
||||||
(get shape-id)))
|
(get shape-id)))
|
||||||
|
|
||||||
|
(defn shapes-seq
|
||||||
|
[container]
|
||||||
|
(vals (:objects container)))
|
||||||
|
|
||||||
|
(defn make-component-shape
|
||||||
|
"Clone the shape and all children. Generate new ids and detach
|
||||||
|
from parent and frame. Update the original shapes to have links
|
||||||
|
to the new ones."
|
||||||
|
[shape objects file-id]
|
||||||
|
(assert (nil? (:component-id shape)))
|
||||||
|
(assert (nil? (:component-file shape)))
|
||||||
|
(assert (nil? (:shape-ref shape)))
|
||||||
|
(let [;; Ensure that the component root is not an instance and
|
||||||
|
;; it's no longer tied to a frame.
|
||||||
|
update-new-shape (fn [new-shape _original-shape]
|
||||||
|
(cond-> new-shape
|
||||||
|
true
|
||||||
|
(-> (assoc :frame-id nil)
|
||||||
|
(dissoc :component-root?))
|
||||||
|
|
||||||
|
(nil? (:parent-id new-shape))
|
||||||
|
(dissoc :component-id
|
||||||
|
:component-file
|
||||||
|
:shape-ref)))
|
||||||
|
|
||||||
|
;; Make the original shape an instance of the new component.
|
||||||
|
;; If one of the original shape children already was a component
|
||||||
|
;; instance, maintain this instanceness untouched.
|
||||||
|
update-original-shape (fn [original-shape new-shape]
|
||||||
|
(cond-> original-shape
|
||||||
|
(nil? (:shape-ref original-shape))
|
||||||
|
(-> (assoc :shape-ref (:id new-shape))
|
||||||
|
(dissoc :touched))
|
||||||
|
|
||||||
|
(nil? (:parent-id new-shape))
|
||||||
|
(assoc :component-id (:id new-shape)
|
||||||
|
:component-file file-id
|
||||||
|
:component-root? true)
|
||||||
|
|
||||||
|
(some? (:parent-id new-shape))
|
||||||
|
(dissoc :component-root?)))]
|
||||||
|
|
||||||
|
(ctst/clone-object shape nil objects update-new-shape update-original-shape)))
|
||||||
|
|
||||||
(defn instantiate-component
|
(defn instantiate-component
|
||||||
[container component component-file position]
|
[container component component-file-id position]
|
||||||
(let [component-shape (get-shape component (:id component))
|
(let [component-shape (get-shape component (:id component))
|
||||||
|
|
||||||
orig-pos (gpt/point (:x component-shape) (:y component-shape))
|
orig-pos (gpt/point (:x component-shape) (:y component-shape))
|
||||||
delta (gpt/subtract position orig-pos)
|
delta (gpt/subtract position orig-pos)
|
||||||
|
|
||||||
objects (:objects container)
|
objects (:objects container)
|
||||||
unames (volatile! (ctt/retrieve-used-names objects))
|
unames (volatile! (ctst/retrieve-used-names objects))
|
||||||
|
|
||||||
frame-id (ctt/frame-id-by-position objects (gpt/add orig-pos delta))
|
frame-id (ctst/frame-id-by-position objects (gpt/add orig-pos delta))
|
||||||
|
|
||||||
update-new-shape
|
update-new-shape
|
||||||
(fn [new-shape original-shape]
|
(fn [new-shape original-shape]
|
||||||
(let [new-name (ctt/generate-unique-name @unames (:name new-shape))]
|
(let [new-name (ctst/generate-unique-name @unames (:name new-shape))]
|
||||||
|
|
||||||
(when (nil? (:parent-id original-shape))
|
(when (nil? (:parent-id original-shape))
|
||||||
(vswap! unames conj new-name))
|
(vswap! unames conj new-name))
|
||||||
|
@ -62,7 +129,7 @@
|
||||||
|
|
||||||
(nil? (:parent-id original-shape))
|
(nil? (:parent-id original-shape))
|
||||||
(assoc :component-id (:id original-shape)
|
(assoc :component-id (:id original-shape)
|
||||||
:component-file component-file
|
:component-file component-file-id
|
||||||
:component-root? true
|
:component-root? true
|
||||||
:name new-name)
|
:name new-name)
|
||||||
|
|
||||||
|
@ -70,7 +137,7 @@
|
||||||
(dissoc :component-root?))))
|
(dissoc :component-root?))))
|
||||||
|
|
||||||
[new-shape new-shapes _]
|
[new-shape new-shapes _]
|
||||||
(ctt/clone-object component-shape
|
(ctst/clone-object component-shape
|
||||||
nil
|
nil
|
||||||
(get component :objects)
|
(get component :objects)
|
||||||
update-new-shape)]
|
update-new-shape)]
|
||||||
|
|
|
@ -6,10 +6,20 @@
|
||||||
|
|
||||||
(ns app.common.types.file
|
(ns app.common.types.file
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.common.pages.common :refer [file-version]]
|
||||||
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.types.color :as ctc]
|
[app.common.types.color :as ctc]
|
||||||
|
[app.common.types.components-list :as ctkl]
|
||||||
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
[clojure.spec.alpha :as s]))
|
[app.common.types.pages-list :as ctpl]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
|
[clojure.spec.alpha :as s]
|
||||||
|
[cuerdas.core :as str]))
|
||||||
|
|
||||||
|
;; Specs
|
||||||
|
|
||||||
(s/def :internal.media-object/name string?)
|
(s/def :internal.media-object/name string?)
|
||||||
(s/def :internal.media-object/width ::us/safe-integer)
|
(s/def :internal.media-object/width ::us/safe-integer)
|
||||||
|
@ -57,3 +67,158 @@
|
||||||
::recent-colors
|
::recent-colors
|
||||||
::typographies
|
::typographies
|
||||||
::media]))
|
::media]))
|
||||||
|
|
||||||
|
;; Initialization
|
||||||
|
|
||||||
|
(def empty-file-data
|
||||||
|
{:version file-version
|
||||||
|
:pages []
|
||||||
|
:pages-index {}})
|
||||||
|
|
||||||
|
(defn make-file-data
|
||||||
|
([file-id]
|
||||||
|
(make-file-data file-id (uuid/next)))
|
||||||
|
|
||||||
|
([file-id page-id]
|
||||||
|
(let [page (ctp/make-empty-page page-id "Page-1")]
|
||||||
|
(-> empty-file-data
|
||||||
|
(assoc :id file-id)
|
||||||
|
(ctpl/add-page page)))))
|
||||||
|
|
||||||
|
;; Helpers
|
||||||
|
|
||||||
|
(defn update-file-data
|
||||||
|
[file f]
|
||||||
|
(update file :data f))
|
||||||
|
|
||||||
|
(defn containers-seq
|
||||||
|
"Generate a sequence of all pages and all components, wrapped as containers"
|
||||||
|
[file-data]
|
||||||
|
(concat (map #(ctn/make-container % :page) (ctpl/pages-seq file-data))
|
||||||
|
(map #(ctn/make-container % :component) (ctkl/components-seq file-data))))
|
||||||
|
|
||||||
|
(defn absorb-assets
|
||||||
|
"Find all assets of a library that are used in the file, and
|
||||||
|
move them to the file local library."
|
||||||
|
[file-data library-data]
|
||||||
|
(let [library-page-id (uuid/next)
|
||||||
|
|
||||||
|
add-library-page
|
||||||
|
(fn [file-data]
|
||||||
|
(let [page (ctp/make-empty-page library-page-id "Library page")]
|
||||||
|
(-> file-data
|
||||||
|
(ctpl/add-page page))))
|
||||||
|
|
||||||
|
find-instances-in-container
|
||||||
|
(fn [container component]
|
||||||
|
(let [instances (filter #(= (:component-id %) (:id component))
|
||||||
|
(ctn/shapes-seq container))]
|
||||||
|
(when (d/not-empty? instances)
|
||||||
|
[[container instances]])))
|
||||||
|
|
||||||
|
find-instances
|
||||||
|
(fn [file-data component]
|
||||||
|
(mapcat #(find-instances-in-container % component) (containers-seq file-data)))
|
||||||
|
|
||||||
|
absorb-component
|
||||||
|
(fn [file-data _component]
|
||||||
|
;; TODO: complete this
|
||||||
|
file-data)
|
||||||
|
|
||||||
|
used-components
|
||||||
|
(mapcat (fn [component]
|
||||||
|
(let [instances (find-instances file-data component)]
|
||||||
|
(when instances
|
||||||
|
[[component instances]])))
|
||||||
|
(ctkl/components-seq library-data))]
|
||||||
|
|
||||||
|
(if (empty? used-components)
|
||||||
|
file-data
|
||||||
|
(as-> file-data $
|
||||||
|
(add-library-page $)
|
||||||
|
(reduce absorb-component
|
||||||
|
$
|
||||||
|
used-components)))))
|
||||||
|
|
||||||
|
;; Debug helpers
|
||||||
|
|
||||||
|
(defn dump-tree
|
||||||
|
([file-data page-id libraries]
|
||||||
|
(dump-tree file-data page-id libraries false false))
|
||||||
|
|
||||||
|
([file-data page-id libraries show-ids]
|
||||||
|
(dump-tree file-data page-id libraries show-ids false))
|
||||||
|
|
||||||
|
([file-data page-id libraries show-ids show-touched]
|
||||||
|
(let [page (ctpl/get-page file-data page-id)
|
||||||
|
objects (:objects page)
|
||||||
|
components (:components file-data)
|
||||||
|
root (d/seek #(nil? (:parent-id %)) (vals objects))]
|
||||||
|
|
||||||
|
(letfn [(show-shape [shape-id level objects]
|
||||||
|
(let [shape (get objects shape-id)]
|
||||||
|
(println (str/pad (str (str/repeat " " level)
|
||||||
|
(:name shape)
|
||||||
|
(when (seq (:touched shape)) "*")
|
||||||
|
(when show-ids (str/format " <%s>" (:id shape))))
|
||||||
|
{:length 20
|
||||||
|
:type :right})
|
||||||
|
(show-component shape objects))
|
||||||
|
(when show-touched
|
||||||
|
(when (seq (:touched shape))
|
||||||
|
(println (str (str/repeat " " level)
|
||||||
|
" "
|
||||||
|
(str (:touched shape)))))
|
||||||
|
(when (:remote-synced? shape)
|
||||||
|
(println (str (str/repeat " " level)
|
||||||
|
" (remote-synced)"))))
|
||||||
|
(when (:shapes shape)
|
||||||
|
(dorun (for [shape-id (:shapes shape)]
|
||||||
|
(show-shape shape-id (inc level) objects))))))
|
||||||
|
|
||||||
|
(show-component [shape objects]
|
||||||
|
(if (nil? (:shape-ref shape))
|
||||||
|
""
|
||||||
|
(let [root-shape (cph/get-component-shape objects shape)
|
||||||
|
component-id (when root-shape (:component-id root-shape))
|
||||||
|
component-file-id (when root-shape (:component-file root-shape))
|
||||||
|
component-file (when component-file-id (get libraries component-file-id nil))
|
||||||
|
component (when component-id
|
||||||
|
(if component-file
|
||||||
|
(get-in component-file [:data :components component-id])
|
||||||
|
(get components component-id)))
|
||||||
|
component-shape (when (and component (:shape-ref shape))
|
||||||
|
(get-in component [:objects (:shape-ref shape)]))]
|
||||||
|
(str/format " %s--> %s%s%s"
|
||||||
|
(cond (:component-root? shape) "#"
|
||||||
|
(:component-id shape) "@"
|
||||||
|
:else "-")
|
||||||
|
(when component-file (str/format "<%s> " (:name component-file)))
|
||||||
|
(or (:name component-shape) "?")
|
||||||
|
(if (or (:component-root? shape)
|
||||||
|
(nil? (:component-id shape))
|
||||||
|
true)
|
||||||
|
""
|
||||||
|
(let [component-id (:component-id shape)
|
||||||
|
component-file-id (:component-file shape)
|
||||||
|
component-file (when component-file-id (get libraries component-file-id nil))
|
||||||
|
component (if component-file
|
||||||
|
(get-in component-file [:data :components component-id])
|
||||||
|
(get components component-id))]
|
||||||
|
(str/format " (%s%s)"
|
||||||
|
(when component-file (str/format "<%s> " (:name component-file)))
|
||||||
|
(:name component))))))))]
|
||||||
|
|
||||||
|
(println "[Page]")
|
||||||
|
(show-shape (:id root) 0 objects)
|
||||||
|
|
||||||
|
(dorun (for [component (vals components)]
|
||||||
|
(do
|
||||||
|
(println)
|
||||||
|
(println (str/format "[%s]" (:name component))
|
||||||
|
(when show-ids
|
||||||
|
(str/format " (main: %s/%s)"
|
||||||
|
(:main-instance-page component)
|
||||||
|
(:main-instance-id component))))
|
||||||
|
(show-shape (:id component) 0 (:objects component)))))))))
|
||||||
|
|
||||||
|
|
|
@ -24,3 +24,11 @@
|
||||||
(update :pages conj-if-not-exists (:id page))
|
(update :pages conj-if-not-exists (:id page))
|
||||||
(update :pages-index assoc (:id page) page))))
|
(update :pages-index assoc (:id page) page))))
|
||||||
|
|
||||||
|
(defn pages-seq
|
||||||
|
[file-data]
|
||||||
|
(vals (:pages-index file-data)))
|
||||||
|
|
||||||
|
(defn update-page
|
||||||
|
[file-data page-id f]
|
||||||
|
(update-in file-data [:pages-index page-id] f))
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,13 @@
|
||||||
|
|
||||||
(ns app.common.types.shape
|
(ns app.common.types.shape
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.colors :as clr]
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.common.exceptions :as ex]
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.common.pages.common :refer [default-color]]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.types.color :as ctc]
|
[app.common.types.color :as ctc]
|
||||||
[app.common.types.shape.blur :as ctsb]
|
[app.common.types.shape.blur :as ctsb]
|
||||||
|
@ -16,6 +21,7 @@
|
||||||
[app.common.types.shape.layout :as ctsl]
|
[app.common.types.shape.layout :as ctsl]
|
||||||
[app.common.types.shape.radius :as ctsr]
|
[app.common.types.shape.radius :as ctsr]
|
||||||
[app.common.types.shape.shadow :as ctss]
|
[app.common.types.shape.shadow :as ctss]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
[clojure.set :as set]
|
[clojure.set :as set]
|
||||||
[clojure.spec.alpha :as s]))
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
|
@ -316,3 +322,155 @@
|
||||||
(s/and (s/multi-spec shape-spec :type)
|
(s/and (s/multi-spec shape-spec :type)
|
||||||
#(contains? % :type)
|
#(contains? % :type)
|
||||||
#(contains? % :name)))
|
#(contains? % :name)))
|
||||||
|
|
||||||
|
|
||||||
|
;; --- Initialization
|
||||||
|
|
||||||
|
(def default-shape-attrs
|
||||||
|
{})
|
||||||
|
|
||||||
|
(def default-frame-attrs
|
||||||
|
{:frame-id uuid/zero
|
||||||
|
:fills [{:fill-color clr/white
|
||||||
|
:fill-opacity 1}]
|
||||||
|
:strokes []
|
||||||
|
:shapes []
|
||||||
|
:hide-fill-on-export false})
|
||||||
|
|
||||||
|
(def ^:private minimal-shapes
|
||||||
|
[{:type :rect
|
||||||
|
:name "Rect-1"
|
||||||
|
:fills [{:fill-color default-color
|
||||||
|
:fill-opacity 1}]
|
||||||
|
:strokes []
|
||||||
|
:rx 0
|
||||||
|
:ry 0}
|
||||||
|
|
||||||
|
{:type :image
|
||||||
|
:rx 0
|
||||||
|
:ry 0
|
||||||
|
:fills []
|
||||||
|
:strokes []}
|
||||||
|
|
||||||
|
{:type :circle
|
||||||
|
:name "Circle-1"
|
||||||
|
:fills [{:fill-color default-color
|
||||||
|
:fill-opacity 1}]
|
||||||
|
:strokes []}
|
||||||
|
|
||||||
|
{:type :path
|
||||||
|
:name "Path-1"
|
||||||
|
:fills []
|
||||||
|
:strokes [{:stroke-style :solid
|
||||||
|
:stroke-alignment :center
|
||||||
|
:stroke-width 2
|
||||||
|
:stroke-color clr/black
|
||||||
|
:stroke-opacity 1}]}
|
||||||
|
|
||||||
|
{:type :frame
|
||||||
|
:name "Board-1"
|
||||||
|
:fills [{:fill-color clr/white
|
||||||
|
:fill-opacity 1}]
|
||||||
|
:strokes []
|
||||||
|
:stroke-style :none
|
||||||
|
:stroke-alignment :center
|
||||||
|
:stroke-width 0
|
||||||
|
:stroke-color clr/black
|
||||||
|
:stroke-opacity 0
|
||||||
|
:rx 0
|
||||||
|
:ry 0}
|
||||||
|
|
||||||
|
{:type :text
|
||||||
|
:name "Text-1"
|
||||||
|
:content nil}
|
||||||
|
|
||||||
|
{:type :svg-raw}])
|
||||||
|
|
||||||
|
(def empty-selrect
|
||||||
|
{:x 0 :y 0
|
||||||
|
:x1 0 :y1 0
|
||||||
|
:x2 0.01 :y2 0.01
|
||||||
|
:width 0.01 :height 0.01})
|
||||||
|
|
||||||
|
(defn make-minimal-shape
|
||||||
|
[type]
|
||||||
|
(let [type (cond (= type :curve) :path
|
||||||
|
:else type)
|
||||||
|
shape (d/seek #(= type (:type %)) minimal-shapes)]
|
||||||
|
(when-not shape
|
||||||
|
(ex/raise :type :assertion
|
||||||
|
:code :shape-type-not-implemented
|
||||||
|
:context {:type type}))
|
||||||
|
|
||||||
|
(cond-> shape
|
||||||
|
:always
|
||||||
|
(assoc :id (uuid/next))
|
||||||
|
|
||||||
|
(not= :path (:type shape))
|
||||||
|
(assoc :x 0
|
||||||
|
:y 0
|
||||||
|
:width 0.01
|
||||||
|
:height 0.01
|
||||||
|
:selrect {:x 0
|
||||||
|
:y 0
|
||||||
|
:x1 0
|
||||||
|
:y1 0
|
||||||
|
:x2 0.01
|
||||||
|
:y2 0.01
|
||||||
|
:width 0.01
|
||||||
|
:height 0.01}))))
|
||||||
|
|
||||||
|
(defn make-minimal-group
|
||||||
|
[frame-id rect group-name]
|
||||||
|
{:id (uuid/next)
|
||||||
|
:type :group
|
||||||
|
:name group-name
|
||||||
|
:shapes []
|
||||||
|
:frame-id frame-id
|
||||||
|
:x (:x rect)
|
||||||
|
:y (:y rect)
|
||||||
|
:width (:width rect)
|
||||||
|
:height (:height rect)})
|
||||||
|
|
||||||
|
(defn setup-rect-selrect
|
||||||
|
"Initializes the selrect and points for a shape."
|
||||||
|
[shape]
|
||||||
|
(let [selrect (gsh/rect->selrect shape)
|
||||||
|
points (gsh/rect->points shape)]
|
||||||
|
(-> shape
|
||||||
|
(assoc :selrect selrect
|
||||||
|
:points points))))
|
||||||
|
|
||||||
|
(defn- setup-rect
|
||||||
|
"A specialized function for setup rect-like shapes."
|
||||||
|
[shape {:keys [x y width height]}]
|
||||||
|
(-> shape
|
||||||
|
(assoc :x x :y y :width width :height height)
|
||||||
|
(setup-rect-selrect)))
|
||||||
|
|
||||||
|
(defn- setup-image
|
||||||
|
[{:keys [metadata] :as shape} props]
|
||||||
|
(-> (setup-rect shape props)
|
||||||
|
(assoc
|
||||||
|
:proportion (/ (:width metadata)
|
||||||
|
(:height metadata))
|
||||||
|
:proportion-lock true)))
|
||||||
|
|
||||||
|
(defn setup-shape
|
||||||
|
"A function that initializes the geometric data of
|
||||||
|
the shape. The props must have :x :y :width :height."
|
||||||
|
([props]
|
||||||
|
(setup-shape {:type :rect} props))
|
||||||
|
|
||||||
|
([shape props]
|
||||||
|
(case (:type shape)
|
||||||
|
:image (setup-image shape props)
|
||||||
|
(setup-rect shape props))))
|
||||||
|
|
||||||
|
(defn make-shape
|
||||||
|
"Make a non group shape, ready to use."
|
||||||
|
[type geom-props attrs]
|
||||||
|
(-> (make-minimal-shape type)
|
||||||
|
(setup-shape geom-props)
|
||||||
|
(merge attrs)))
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,11 @@
|
||||||
|
|
||||||
(update container :objects update-objects parent-id)))
|
(update container :objects update-objects parent-id)))
|
||||||
|
|
||||||
|
(defn set-shape
|
||||||
|
"Replace a shape in the tree with a new one"
|
||||||
|
[container shape]
|
||||||
|
(assoc-in container [:objects (:id shape)] shape))
|
||||||
|
|
||||||
(defn get-frames
|
(defn get-frames
|
||||||
"Retrieves all frame objects as vector"
|
"Retrieves all frame objects as vector"
|
||||||
[objects]
|
[objects]
|
||||||
|
@ -149,7 +154,6 @@
|
||||||
|
|
||||||
[base index-base-a index-base-b]))
|
[base index-base-a index-base-b]))
|
||||||
|
|
||||||
|
|
||||||
(defn is-shape-over-shape?
|
(defn is-shape-over-shape?
|
||||||
[objects base-shape-id over-shape-id {:keys [top-frames?]}]
|
[objects base-shape-id over-shape-id {:keys [top-frames?]}]
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth :refer [close?]]
|
[app.common.math :as mth :refer [close?]]
|
||||||
[app.common.pages :refer [make-minimal-shape]]
|
[app.common.types.shape :as cts]
|
||||||
[clojure.test :as t]))
|
[clojure.test :as t]))
|
||||||
|
|
||||||
(def default-path
|
(def default-path
|
||||||
|
@ -41,7 +41,7 @@
|
||||||
(defn create-test-shape
|
(defn create-test-shape
|
||||||
([type] (create-test-shape type {}))
|
([type] (create-test-shape type {}))
|
||||||
([type params]
|
([type params]
|
||||||
(-> (make-minimal-shape type)
|
(-> (cts/make-minimal-shape type)
|
||||||
(merge params)
|
(merge params)
|
||||||
(cond->
|
(cond->
|
||||||
(= type :path) (add-path-data)
|
(= type :path) (add-path-data)
|
||||||
|
|
|
@ -9,12 +9,13 @@
|
||||||
[clojure.test :as t]
|
[clojure.test :as t]
|
||||||
[clojure.pprint :refer [pprint]]
|
[clojure.pprint :refer [pprint]]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
|
[app.common.types.file :as ctf]
|
||||||
[app.common.uuid :as uuid]))
|
[app.common.uuid :as uuid]))
|
||||||
|
|
||||||
(t/deftest process-change-set-option
|
(t/deftest process-change-set-option
|
||||||
(let [file-id (uuid/custom 2 2)
|
(let [file-id (uuid/custom 2 2)
|
||||||
page-id (uuid/custom 1 1)
|
page-id (uuid/custom 1 1)
|
||||||
data (cp/make-file-data file-id page-id)]
|
data (ctf/make-file-data file-id page-id)]
|
||||||
(t/testing "Sets option single"
|
(t/testing "Sets option single"
|
||||||
(let [chg {:type :set-option
|
(let [chg {:type :set-option
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
|
@ -80,7 +81,7 @@
|
||||||
(t/deftest process-change-add-obj
|
(t/deftest process-change-add-obj
|
||||||
(let [file-id (uuid/custom 2 2)
|
(let [file-id (uuid/custom 2 2)
|
||||||
page-id (uuid/custom 1 1)
|
page-id (uuid/custom 1 1)
|
||||||
data (cp/make-file-data file-id page-id)
|
data (ctf/make-file-data file-id page-id)
|
||||||
id-a (uuid/custom 2 1)
|
id-a (uuid/custom 2 1)
|
||||||
id-b (uuid/custom 2 2)
|
id-b (uuid/custom 2 2)
|
||||||
id-c (uuid/custom 2 3)]
|
id-c (uuid/custom 2 3)]
|
||||||
|
@ -134,7 +135,7 @@
|
||||||
(t/deftest process-change-mod-obj
|
(t/deftest process-change-mod-obj
|
||||||
(let [file-id (uuid/custom 2 2)
|
(let [file-id (uuid/custom 2 2)
|
||||||
page-id (uuid/custom 1 1)
|
page-id (uuid/custom 1 1)
|
||||||
data (cp/make-file-data file-id page-id)]
|
data (ctf/make-file-data file-id page-id)]
|
||||||
(t/testing "simple mod-obj"
|
(t/testing "simple mod-obj"
|
||||||
(let [chg {:type :mod-obj
|
(let [chg {:type :mod-obj
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
|
@ -161,7 +162,7 @@
|
||||||
(let [file-id (uuid/custom 2 2)
|
(let [file-id (uuid/custom 2 2)
|
||||||
page-id (uuid/custom 1 1)
|
page-id (uuid/custom 1 1)
|
||||||
id (uuid/custom 2 1)
|
id (uuid/custom 2 1)
|
||||||
data (cp/make-file-data file-id page-id)
|
data (ctf/make-file-data file-id page-id)
|
||||||
data (-> data
|
data (-> data
|
||||||
(assoc-in [:pages-index page-id :objects uuid/zero :shapes] [id])
|
(assoc-in [:pages-index page-id :objects uuid/zero :shapes] [id])
|
||||||
(assoc-in [:pages-index page-id :objects id]
|
(assoc-in [:pages-index page-id :objects id]
|
||||||
|
@ -205,7 +206,7 @@
|
||||||
|
|
||||||
file-id (uuid/custom 2 2)
|
file-id (uuid/custom 2 2)
|
||||||
page-id (uuid/custom 1 1)
|
page-id (uuid/custom 1 1)
|
||||||
data (cp/make-file-data file-id page-id)
|
data (ctf/make-file-data file-id page-id)
|
||||||
|
|
||||||
data (update-in data [:pages-index page-id :objects]
|
data (update-in data [:pages-index page-id :objects]
|
||||||
#(-> %
|
#(-> %
|
||||||
|
@ -449,7 +450,7 @@
|
||||||
:obj {:type :rect
|
:obj {:type :rect
|
||||||
:name "Shape 3"}}
|
:name "Shape 3"}}
|
||||||
]
|
]
|
||||||
data (cp/make-file-data file-id page-id)
|
data (ctf/make-file-data file-id page-id)
|
||||||
data (cp/process-changes data changes)]
|
data (cp/process-changes data changes)]
|
||||||
|
|
||||||
(t/testing "preserve order on multiple shape mov 1"
|
(t/testing "preserve order on multiple shape mov 1"
|
||||||
|
@ -556,7 +557,7 @@
|
||||||
:parent-id group-1-id
|
:parent-id group-1-id
|
||||||
:shapes [shape-1-id shape-2-id]}]
|
:shapes [shape-1-id shape-2-id]}]
|
||||||
|
|
||||||
data (cp/make-file-data file-id page-id)
|
data (ctf/make-file-data file-id page-id)
|
||||||
data (cp/process-changes data changes)]
|
data (cp/process-changes data changes)]
|
||||||
|
|
||||||
(t/testing "case 1"
|
(t/testing "case 1"
|
||||||
|
|
110
common/test/app/common/test_helpers/files.cljc
Normal file
110
common/test/app/common/test_helpers/files.cljc
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
;; 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) UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns app.common.test-helpers.files
|
||||||
|
(:require
|
||||||
|
[app.common.geom.point :as gpt]
|
||||||
|
[app.common.types.components-list :as ctkl]
|
||||||
|
[app.common.types.container :as ctn]
|
||||||
|
[app.common.types.file :as ctf]
|
||||||
|
[app.common.types.pages-list :as ctpl]
|
||||||
|
[app.common.types.shape :as cts]
|
||||||
|
[app.common.types.shape-tree :as ctst]
|
||||||
|
[app.common.uuid :as uuid]))
|
||||||
|
|
||||||
|
(def ^:private idmap (atom {}))
|
||||||
|
|
||||||
|
(defn reset-idmap! []
|
||||||
|
(reset! idmap {}))
|
||||||
|
|
||||||
|
(defn id
|
||||||
|
[label]
|
||||||
|
(get @idmap label))
|
||||||
|
|
||||||
|
(defn sample-file
|
||||||
|
([file-id page-id] (sample-file file-id page-id nil))
|
||||||
|
([file-id page-id props]
|
||||||
|
(merge {:id file-id
|
||||||
|
:name (get props :name "File1")
|
||||||
|
:data (ctf/make-file-data file-id page-id)}
|
||||||
|
props)))
|
||||||
|
|
||||||
|
(defn sample-shape
|
||||||
|
[file label type page-id props]
|
||||||
|
(ctf/update-file-data
|
||||||
|
file
|
||||||
|
(fn [file-data]
|
||||||
|
(let [frame-id (get props :frame-id uuid/zero)
|
||||||
|
parent-id (get props :parent-id uuid/zero)
|
||||||
|
shape (if (= type :group)
|
||||||
|
(cts/make-minimal-group frame-id
|
||||||
|
{:x 0 :y 0 :width 1 :height 1}
|
||||||
|
(get props :name "Group1"))
|
||||||
|
(cts/make-shape type
|
||||||
|
{:x 0 :y 0 :width 1 :height 1}
|
||||||
|
props))]
|
||||||
|
|
||||||
|
(swap! idmap assoc label (:id shape))
|
||||||
|
(ctpl/update-page file-data
|
||||||
|
page-id
|
||||||
|
#(ctst/add-shape (:id shape)
|
||||||
|
shape
|
||||||
|
%
|
||||||
|
frame-id
|
||||||
|
parent-id
|
||||||
|
0
|
||||||
|
true))))))
|
||||||
|
|
||||||
|
(defn sample-component
|
||||||
|
[file label page-id shape-id]
|
||||||
|
(ctf/update-file-data
|
||||||
|
file
|
||||||
|
(fn [file-data]
|
||||||
|
(let [page (ctpl/get-page file-data page-id)
|
||||||
|
|
||||||
|
[component-shape component-shapes updated-shapes]
|
||||||
|
(ctn/make-component-shape (ctn/get-shape page shape-id)
|
||||||
|
(:objects page)
|
||||||
|
(:id file))]
|
||||||
|
|
||||||
|
(swap! idmap assoc label (:id component-shape))
|
||||||
|
(-> file-data
|
||||||
|
(ctpl/update-page page-id
|
||||||
|
#(reduce (fn [page shape] (ctst/set-shape page shape))
|
||||||
|
%
|
||||||
|
updated-shapes))
|
||||||
|
(ctkl/add-component (:id component-shape)
|
||||||
|
(:name component-shape)
|
||||||
|
""
|
||||||
|
shape-id
|
||||||
|
page-id
|
||||||
|
component-shapes))))))
|
||||||
|
|
||||||
|
(defn sample-instance
|
||||||
|
[file label page-id library component-id]
|
||||||
|
(ctf/update-file-data
|
||||||
|
file
|
||||||
|
(fn [file-data]
|
||||||
|
(let [[instance-shape instance-shapes]
|
||||||
|
(ctn/instantiate-component (ctpl/get-page file-data page-id)
|
||||||
|
(ctkl/get-component (:data library) component-id)
|
||||||
|
(:id library)
|
||||||
|
(gpt/point 0 0))]
|
||||||
|
|
||||||
|
(swap! idmap assoc label (:id instance-shape))
|
||||||
|
(-> file-data
|
||||||
|
(ctpl/update-page page-id
|
||||||
|
#(reduce (fn [page shape]
|
||||||
|
(ctst/add-shape (:id shape)
|
||||||
|
shape
|
||||||
|
page
|
||||||
|
uuid/zero
|
||||||
|
(:parent-id shape)
|
||||||
|
0
|
||||||
|
true))
|
||||||
|
%
|
||||||
|
instance-shapes)))))))
|
||||||
|
|
79
common/test/app/common/types/file_test.cljc
Normal file
79
common/test/app/common/types/file_test.cljc
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
;; 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) UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns app.common.types.file-test
|
||||||
|
(:require
|
||||||
|
[clojure.test :as t]
|
||||||
|
[app.common.geom.point :as gpt]
|
||||||
|
[app.common.types.components-list :as ctkl]
|
||||||
|
[app.common.types.file :as ctf]
|
||||||
|
[app.common.types.pages-list :as ctpl]
|
||||||
|
[app.common.types.shape :as cts]
|
||||||
|
[app.common.types.shape-tree :as ctst]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
|
[app.common.test-helpers.files :as thf]
|
||||||
|
|
||||||
|
[app.common.data :as d]
|
||||||
|
[app.common.pages.helpers :as cph]
|
||||||
|
[cuerdas.core :as str]
|
||||||
|
))
|
||||||
|
|
||||||
|
(t/use-fixtures :each
|
||||||
|
{:before thf/reset-idmap!})
|
||||||
|
|
||||||
|
(t/deftest test-absorb-assets
|
||||||
|
(let [library-id (uuid/custom 1 1)
|
||||||
|
library-page-id (uuid/custom 2 2)
|
||||||
|
file-id (uuid/custom 3 3)
|
||||||
|
file-page-id (uuid/custom 4 4)
|
||||||
|
|
||||||
|
library (-> (thf/sample-file library-id library-page-id {:is-shared true})
|
||||||
|
(thf/sample-shape :group1
|
||||||
|
:group
|
||||||
|
library-page-id
|
||||||
|
{:name "Group1"})
|
||||||
|
(thf/sample-shape :shape1
|
||||||
|
:rect
|
||||||
|
library-page-id
|
||||||
|
{:name "Rect1"
|
||||||
|
:parent-id (thf/id :group1)})
|
||||||
|
(thf/sample-component :component1
|
||||||
|
library-page-id
|
||||||
|
(thf/id :group1)))
|
||||||
|
|
||||||
|
file (-> (thf/sample-file file-id file-page-id)
|
||||||
|
(thf/sample-instance :instance1
|
||||||
|
file-page-id
|
||||||
|
library
|
||||||
|
(thf/id :component1)))
|
||||||
|
|
||||||
|
absorbed-file (ctf/update-file-data
|
||||||
|
file
|
||||||
|
#(ctf/absorb-assets % (:data library)))]
|
||||||
|
|
||||||
|
(println "\n===== library")
|
||||||
|
(ctf/dump-tree (:data library)
|
||||||
|
library-page-id
|
||||||
|
{}
|
||||||
|
true)
|
||||||
|
|
||||||
|
(println "\n===== file")
|
||||||
|
(ctf/dump-tree (:data file)
|
||||||
|
file-page-id
|
||||||
|
{library-id {:id library-id
|
||||||
|
:name "Library 1"
|
||||||
|
:data library}}
|
||||||
|
true)
|
||||||
|
|
||||||
|
(println "\n===== absorbed file")
|
||||||
|
(ctf/dump-tree (:data absorbed-file)
|
||||||
|
file-page-id
|
||||||
|
{}
|
||||||
|
true)
|
||||||
|
|
||||||
|
(t/is (= library-id (:id library)))
|
||||||
|
(t/is (= file-id (:id absorbed-file)))))
|
||||||
|
|
|
@ -4,20 +4,20 @@
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) UXBOX Labs SL
|
;; Copyright (c) UXBOX Labs SL
|
||||||
|
|
||||||
(ns app.common.spec-interactions-test
|
(ns app.common.types.shape.spec-interactions-test
|
||||||
(:require
|
(:require
|
||||||
[clojure.test :as t]
|
[clojure.test :as t]
|
||||||
[clojure.pprint :refer [pprint]]
|
[clojure.pprint :refer [pprint]]
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.pages.init :as cpi]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape.interactions :as ctsi]
|
[app.common.types.shape.interactions :as ctsi]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.common.geom.point :as gpt]))
|
[app.common.geom.point :as gpt]))
|
||||||
|
|
||||||
(t/deftest set-event-type
|
(t/deftest set-event-type
|
||||||
(let [interaction ctsi/default-interaction
|
(let [interaction ctsi/default-interaction
|
||||||
shape (cpi/make-minimal-shape :rect)
|
shape (cts/make-minimal-shape :rect)
|
||||||
frame (cpi/make-minimal-shape :frame)]
|
frame (cts/make-minimal-shape :frame)]
|
||||||
|
|
||||||
(t/testing "Set event type unchanged"
|
(t/testing "Set event type unchanged"
|
||||||
(let [new-interaction
|
(let [new-interaction
|
||||||
|
@ -148,7 +148,7 @@
|
||||||
|
|
||||||
|
|
||||||
(t/deftest option-delay
|
(t/deftest option-delay
|
||||||
(let [frame (cpi/make-minimal-shape :frame)
|
(let [frame (cts/make-minimal-shape :frame)
|
||||||
i1 ctsi/default-interaction
|
i1 ctsi/default-interaction
|
||||||
i2 (ctsi/set-event-type i1 :after-delay frame)]
|
i2 (ctsi/set-event-type i1 :after-delay frame)]
|
||||||
|
|
||||||
|
@ -211,10 +211,10 @@
|
||||||
|
|
||||||
|
|
||||||
(t/deftest option-overlay-opts
|
(t/deftest option-overlay-opts
|
||||||
(let [base-frame (-> (cpi/make-minimal-shape :frame)
|
(let [base-frame (-> (cts/make-minimal-shape :frame)
|
||||||
(assoc-in [:selrect :width] 100)
|
(assoc-in [:selrect :width] 100)
|
||||||
(assoc-in [:selrect :height] 100))
|
(assoc-in [:selrect :height] 100))
|
||||||
overlay-frame (-> (cpi/make-minimal-shape :frame)
|
overlay-frame (-> (cts/make-minimal-shape :frame)
|
||||||
(assoc-in [:selrect :width] 30)
|
(assoc-in [:selrect :width] 30)
|
||||||
(assoc-in [:selrect :height] 20))
|
(assoc-in [:selrect :height] 20))
|
||||||
objects {(:id base-frame) base-frame
|
objects {(:id base-frame) base-frame
|
||||||
|
@ -542,12 +542,12 @@
|
||||||
|
|
||||||
|
|
||||||
(t/deftest remap-interactions
|
(t/deftest remap-interactions
|
||||||
(let [frame1 (cpi/make-minimal-shape :frame)
|
(let [frame1 (cts/make-minimal-shape :frame)
|
||||||
frame2 (cpi/make-minimal-shape :frame)
|
frame2 (cts/make-minimal-shape :frame)
|
||||||
frame3 (cpi/make-minimal-shape :frame)
|
frame3 (cts/make-minimal-shape :frame)
|
||||||
frame4 (cpi/make-minimal-shape :frame)
|
frame4 (cts/make-minimal-shape :frame)
|
||||||
frame5 (cpi/make-minimal-shape :frame)
|
frame5 (cts/make-minimal-shape :frame)
|
||||||
frame6 (cpi/make-minimal-shape :frame)
|
frame6 (cts/make-minimal-shape :frame)
|
||||||
|
|
||||||
objects {(:id frame3) frame3
|
objects {(:id frame3) frame3
|
||||||
(:id frame4) frame4
|
(:id frame4) frame4
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
[app.common.geom.proportions :as gpr]
|
[app.common.geom.proportions :as gpr]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages :as cp]
|
|
||||||
[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]
|
||||||
|
@ -1591,7 +1590,7 @@
|
||||||
page-id (:current-page-id state)
|
page-id (:current-page-id state)
|
||||||
frame-id (-> (wsh/lookup-page-objects state page-id)
|
frame-id (-> (wsh/lookup-page-objects state page-id)
|
||||||
(ctst/frame-id-by-position @ms/mouse-position))
|
(ctst/frame-id-by-position @ms/mouse-position))
|
||||||
shape (cp/setup-rect-selrect
|
shape (cts/setup-rect-selrect
|
||||||
{:id id
|
{:id id
|
||||||
:type :text
|
:type :text
|
||||||
:name "Text"
|
:name "Text"
|
||||||
|
@ -1681,12 +1680,12 @@
|
||||||
(let [srect (gsh/selection-rect selected-objs)
|
(let [srect (gsh/selection-rect selected-objs)
|
||||||
frame-id (get-in objects [(first selected) :frame-id])
|
frame-id (get-in objects [(first selected) :frame-id])
|
||||||
parent-id (get-in objects [(first selected) :parent-id])
|
parent-id (get-in objects [(first selected) :parent-id])
|
||||||
shape (-> (cp/make-minimal-shape :frame)
|
shape (-> (cts/make-minimal-shape :frame)
|
||||||
(merge {:x (:x srect) :y (:y srect) :width (:width srect) :height (:height srect)})
|
(merge {:x (:x srect) :y (:y srect) :width (:width srect) :height (:height srect)})
|
||||||
(assoc :frame-id frame-id :parent-id parent-id)
|
(assoc :frame-id frame-id :parent-id parent-id)
|
||||||
(cond-> (not= frame-id uuid/zero)
|
(cond-> (not= frame-id uuid/zero)
|
||||||
(assoc :fills [] :hide-in-viewer true))
|
(assoc :fills [] :hide-in-viewer true))
|
||||||
(cp/setup-rect-selrect))]
|
(cts/setup-rect-selrect))]
|
||||||
(rx/of
|
(rx/of
|
||||||
(dwu/start-undo-transaction)
|
(dwu/start-undo-transaction)
|
||||||
(dwsh/add-shape shape)
|
(dwsh/add-shape shape)
|
||||||
|
|
|
@ -7,15 +7,6 @@
|
||||||
(ns app.main.data.workspace.common
|
(ns app.main.data.workspace.common
|
||||||
(:require
|
(:require
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.pages :as cp]
|
|
||||||
[app.common.pages.changes-builder :as pcb]
|
|
||||||
[app.common.pages.helpers :as cph]
|
|
||||||
[app.common.spec :as us]
|
|
||||||
[app.common.types.page :as ctp]
|
|
||||||
[app.common.types.shape :as cts]
|
|
||||||
[app.common.types.shape-tree :as ctt]
|
|
||||||
[app.common.types.shape.interactions :as ctsi]
|
|
||||||
[app.common.uuid :as uuid]
|
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.worker :as uw]
|
[app.main.worker :as uw]
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
(ns app.main.data.workspace.drawing
|
(ns app.main.data.workspace.drawing
|
||||||
"Drawing interactions."
|
"Drawing interactions."
|
||||||
(:require
|
(:require
|
||||||
[app.common.pages :as cp]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.drawing.box :as box]
|
[app.main.data.workspace.drawing.box :as box]
|
||||||
|
@ -91,7 +91,7 @@
|
||||||
(ptk/reify ::handle-drawing
|
(ptk/reify ::handle-drawing
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [data (cp/make-minimal-shape type)]
|
(let [data (cts/make-minimal-shape type)]
|
||||||
(update-in state [:workspace-drawing :object] merge data)))
|
(update-in state [:workspace-drawing :object] merge data)))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages :as cp]
|
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape-tree :as ctt]
|
[app.common.types.shape-tree :as ctt]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace.drawing.common :as common]
|
[app.main.data.workspace.drawing.common :as common]
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
|
|
||||||
shape (get-in state [:workspace-drawing :object])
|
shape (get-in state [:workspace-drawing :object])
|
||||||
shape (-> shape
|
shape (-> shape
|
||||||
(cp/setup-shape {:x (:x initial)
|
(cts/setup-shape {:x (:x initial)
|
||||||
:y (:y initial)
|
:y (:y initial)
|
||||||
:width 0.01
|
:width 0.01
|
||||||
:height 0.01})
|
:height 0.01})
|
||||||
|
|
|
@ -9,8 +9,9 @@
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages :as cp]
|
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
|
[app.common.types.shape :as cts]
|
||||||
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.shapes :as dwsh]
|
[app.main.data.workspace.shapes :as dwsh]
|
||||||
[app.main.data.workspace.state-helpers :as wsh]
|
[app.main.data.workspace.state-helpers :as wsh]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
|
@ -55,7 +56,7 @@
|
||||||
(assoc :height 17 :width 4 :grow-type :auto-width)
|
(assoc :height 17 :width 4 :grow-type :auto-width)
|
||||||
|
|
||||||
click-draw?
|
click-draw?
|
||||||
(cp/setup-rect-selrect)
|
(cts/setup-rect-selrect)
|
||||||
|
|
||||||
:always
|
:always
|
||||||
(-> (gsh/transform-shape)
|
(-> (gsh/transform-shape)
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages :as cp]
|
|
||||||
[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.types.shape :as cts]
|
||||||
[app.common.types.shape-tree :as ctt]
|
[app.common.types.shape-tree :as ctt]
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
[app.main.data.workspace.selection :as dws]
|
[app.main.data.workspace.selection :as dws]
|
||||||
|
@ -75,8 +75,8 @@
|
||||||
(ctt/generate-unique-name base-name)))
|
(ctt/generate-unique-name base-name)))
|
||||||
|
|
||||||
selrect (gsh/selection-rect shapes)
|
selrect (gsh/selection-rect shapes)
|
||||||
group (-> (cp/make-minimal-group frame-id selrect gname)
|
group (-> (cts/make-minimal-group frame-id selrect gname)
|
||||||
(cp/setup-shape selrect)
|
(cts/setup-shape selrect)
|
||||||
(assoc :shapes (mapv :id shapes)
|
(assoc :shapes (mapv :id shapes)
|
||||||
:parent-id parent-id
|
:parent-id parent-id
|
||||||
:frame-id frame-id
|
:frame-id frame-id
|
||||||
|
|
|
@ -56,46 +56,6 @@
|
||||||
|
|
||||||
;; ---- Components and instances creation ----
|
;; ---- Components and instances creation ----
|
||||||
|
|
||||||
(defn make-component-shape
|
|
||||||
"Clone the shape and all children. Generate new ids and detach
|
|
||||||
from parent and frame. Update the original shapes to have links
|
|
||||||
to the new ones."
|
|
||||||
[shape objects file-id]
|
|
||||||
(assert (nil? (:component-id shape)))
|
|
||||||
(assert (nil? (:component-file shape)))
|
|
||||||
(assert (nil? (:shape-ref shape)))
|
|
||||||
(let [;; Ensure that the component root is not an instance and
|
|
||||||
;; it's no longer tied to a frame.
|
|
||||||
update-new-shape (fn [new-shape _original-shape]
|
|
||||||
(cond-> new-shape
|
|
||||||
true
|
|
||||||
(-> (assoc :frame-id nil)
|
|
||||||
(dissoc :component-root?))
|
|
||||||
|
|
||||||
(nil? (:parent-id new-shape))
|
|
||||||
(dissoc :component-id
|
|
||||||
:component-file
|
|
||||||
:shape-ref)))
|
|
||||||
|
|
||||||
;; Make the original shape an instance of the new component.
|
|
||||||
;; If one of the original shape children already was a component
|
|
||||||
;; instance, maintain this instanceness untouched.
|
|
||||||
update-original-shape (fn [original-shape new-shape]
|
|
||||||
(cond-> original-shape
|
|
||||||
(nil? (:shape-ref original-shape))
|
|
||||||
(-> (assoc :shape-ref (:id new-shape))
|
|
||||||
(dissoc :touched))
|
|
||||||
|
|
||||||
(nil? (:parent-id new-shape))
|
|
||||||
(assoc :component-id (:id new-shape)
|
|
||||||
:component-file file-id
|
|
||||||
:component-root? true)
|
|
||||||
|
|
||||||
(some? (:parent-id new-shape))
|
|
||||||
(dissoc :component-root?)))]
|
|
||||||
|
|
||||||
(ctst/clone-object shape nil objects update-new-shape update-original-shape)))
|
|
||||||
|
|
||||||
(defn generate-add-component
|
(defn generate-add-component
|
||||||
"If there is exactly one id, and it's a group, use it as root. Otherwise,
|
"If there is exactly one id, and it's a group, use it as root. Otherwise,
|
||||||
create a group that contains all ids. Then, make a component with it,
|
create a group that contains all ids. Then, make a component with it,
|
||||||
|
@ -115,7 +75,7 @@
|
||||||
(dwg/prepare-create-group it objects page-id shapes name true))
|
(dwg/prepare-create-group it objects page-id shapes name true))
|
||||||
|
|
||||||
[new-shape new-shapes updated-shapes]
|
[new-shape new-shapes updated-shapes]
|
||||||
(make-component-shape group objects file-id)
|
(ctn/make-component-shape group objects file-id)
|
||||||
|
|
||||||
changes (-> changes
|
changes (-> changes
|
||||||
(pcb/add-component (:id new-shape)
|
(pcb/add-component (:id new-shape)
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages :as cp]
|
|
||||||
[app.common.pages.changes-builder :as pcb]
|
[app.common.pages.changes-builder :as pcb]
|
||||||
[app.common.spec :refer [max-safe-int min-safe-int]]
|
[app.common.spec :refer [max-safe-int min-safe-int]]
|
||||||
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape-tree :as ctt]
|
[app.common.types.shape-tree :as ctt]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
|
@ -182,7 +182,7 @@
|
||||||
(assoc :svg-attrs attrs)
|
(assoc :svg-attrs attrs)
|
||||||
(assoc :svg-viewbox (-> (select-keys svg-data [:width :height])
|
(assoc :svg-viewbox (-> (select-keys svg-data [:width :height])
|
||||||
(assoc :x offset-x :y offset-y)))
|
(assoc :x offset-x :y offset-y)))
|
||||||
(cp/setup-rect-selrect))))
|
(cts/setup-rect-selrect))))
|
||||||
|
|
||||||
(defn create-svg-root [frame-id svg-data]
|
(defn create-svg-root [frame-id svg-data]
|
||||||
(let [{:keys [name x y width height offset-x offset-y]} svg-data]
|
(let [{:keys [name x y width height offset-x offset-y]} svg-data]
|
||||||
|
@ -194,7 +194,7 @@
|
||||||
:height height
|
:height height
|
||||||
:x (+ x offset-x)
|
:x (+ x offset-x)
|
||||||
:y (+ y offset-y)}
|
:y (+ y offset-y)}
|
||||||
(cp/setup-rect-selrect)
|
(cts/setup-rect-selrect)
|
||||||
(assoc :svg-attrs (-> (:attrs svg-data)
|
(assoc :svg-attrs (-> (:attrs svg-data)
|
||||||
(dissoc :viewBox :xmlns)
|
(dissoc :viewBox :xmlns)
|
||||||
(d/without-keys usvg/inheritable-props))))))
|
(d/without-keys usvg/inheritable-props))))))
|
||||||
|
@ -214,7 +214,7 @@
|
||||||
(assoc :svg-attrs (d/without-keys attrs usvg/inheritable-props))
|
(assoc :svg-attrs (d/without-keys attrs usvg/inheritable-props))
|
||||||
(assoc :svg-viewbox (-> (select-keys svg-data [:width :height])
|
(assoc :svg-viewbox (-> (select-keys svg-data [:width :height])
|
||||||
(assoc :x offset-x :y offset-y)))
|
(assoc :x offset-x :y offset-y)))
|
||||||
(cp/setup-rect-selrect))))
|
(cts/setup-rect-selrect))))
|
||||||
|
|
||||||
(defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}]
|
(defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}]
|
||||||
(when (and (contains? attrs :d) (seq (:d attrs)))
|
(when (and (contains? attrs :d) (seq (:d attrs)))
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages :as cp]
|
[app.common.types.shape :as cts]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
@ -343,7 +343,7 @@
|
||||||
#(->> shapes
|
#(->> shapes
|
||||||
(map gsh/transform-shape)
|
(map gsh/transform-shape)
|
||||||
(gsh/selection-rect)
|
(gsh/selection-rect)
|
||||||
(cp/setup-shape)))
|
(cts/setup-shape)))
|
||||||
on-resize
|
on-resize
|
||||||
(fn [current-position _initial-position event]
|
(fn [current-position _initial-position event]
|
||||||
(when (dom/left-mouse? event)
|
(when (dom/left-mouse? event)
|
||||||
|
@ -371,7 +371,7 @@
|
||||||
#(->> shapes
|
#(->> shapes
|
||||||
(map gsh/transform-shape)
|
(map gsh/transform-shape)
|
||||||
(gsh/selection-rect)
|
(gsh/selection-rect)
|
||||||
(cp/setup-shape)))]
|
(cts/setup-shape)))]
|
||||||
|
|
||||||
[:& controls-selection
|
[:& controls-selection
|
||||||
{:shape shape
|
{:shape shape
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
[app.common.geom.shapes.path :as gpa]
|
[app.common.geom.shapes.path :as gpa]
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.media :as cm]
|
[app.common.media :as cm]
|
||||||
[app.common.pages :as cp]
|
|
||||||
[app.common.text :as ct]
|
[app.common.text :as ct]
|
||||||
|
[app.common.types.file :as ctf]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.repo :as rp]
|
[app.main.repo :as rp]
|
||||||
[app.util.http :as http]
|
[app.util.http :as http]
|
||||||
|
@ -133,7 +133,7 @@
|
||||||
:name (:name context)
|
:name (:name context)
|
||||||
:is-shared (:shared context)
|
:is-shared (:shared context)
|
||||||
:project-id (:project-id context)
|
:project-id (:project-id context)
|
||||||
:data (-> cp/empty-file-data (assoc :id file-id))})))
|
:data (-> ctf/empty-file-data (assoc :id file-id))})))
|
||||||
|
|
||||||
(defn link-file-libraries
|
(defn link-file-libraries
|
||||||
"Create a new file on the back-end"
|
"Create a new file on the back-end"
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.logging :as l]
|
[app.common.logging :as l]
|
||||||
[app.common.pages.helpers :as cph]
|
|
||||||
[app.common.transit :as t]
|
[app.common.transit :as t]
|
||||||
|
[app.common.types.file :as ctf]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.dashboard.shortcuts]
|
[app.main.data.dashboard.shortcuts]
|
||||||
[app.main.data.viewer.shortcuts]
|
[app.main.data.viewer.shortcuts]
|
||||||
|
@ -211,77 +211,9 @@
|
||||||
([state show-ids] (dump-tree' state show-ids false))
|
([state show-ids] (dump-tree' state show-ids false))
|
||||||
([state show-ids show-touched]
|
([state show-ids show-touched]
|
||||||
(let [page-id (get state :current-page-id)
|
(let [page-id (get state :current-page-id)
|
||||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
file-data (get state :workspace-data)
|
||||||
components (get-in state [:workspace-data :components])
|
libraries (get state :workspace-libraries)]
|
||||||
libraries (get state :workspace-libraries)
|
(ctf/dump-tree file-data page-id libraries show-ids show-touched))))
|
||||||
root (d/seek #(nil? (:parent-id %)) (vals objects))]
|
|
||||||
|
|
||||||
(letfn [(show-shape [shape-id level objects]
|
|
||||||
(let [shape (get objects shape-id)]
|
|
||||||
(println (str/pad (str (str/repeat " " level)
|
|
||||||
(:name shape)
|
|
||||||
(when (seq (:touched shape)) "*")
|
|
||||||
(when show-ids (str/format " <%s>" (:id shape))))
|
|
||||||
{:length 20
|
|
||||||
:type :right})
|
|
||||||
(show-component shape objects))
|
|
||||||
(when show-touched
|
|
||||||
(when (seq (:touched shape))
|
|
||||||
(println (str (str/repeat " " level)
|
|
||||||
" "
|
|
||||||
(str (:touched shape)))))
|
|
||||||
(when (:remote-synced? shape)
|
|
||||||
(println (str (str/repeat " " level)
|
|
||||||
" (remote-synced)"))))
|
|
||||||
(when (:shapes shape)
|
|
||||||
(dorun (for [shape-id (:shapes shape)]
|
|
||||||
(show-shape shape-id (inc level) objects))))))
|
|
||||||
|
|
||||||
(show-component [shape objects]
|
|
||||||
(if (nil? (:shape-ref shape))
|
|
||||||
""
|
|
||||||
(let [root-shape (cph/get-component-shape objects shape)
|
|
||||||
component-id (when root-shape (:component-id root-shape))
|
|
||||||
component-file-id (when root-shape (:component-file root-shape))
|
|
||||||
component-file (when component-file-id (get libraries component-file-id nil))
|
|
||||||
component (when component-id
|
|
||||||
(if component-file
|
|
||||||
(get-in component-file [:data :components component-id])
|
|
||||||
(get components component-id)))
|
|
||||||
component-shape (when (and component (:shape-ref shape))
|
|
||||||
(get-in component [:objects (:shape-ref shape)]))]
|
|
||||||
(str/format " %s--> %s%s%s"
|
|
||||||
(cond (:component-root? shape) "#"
|
|
||||||
(:component-id shape) "@"
|
|
||||||
:else "-")
|
|
||||||
(when component-file (str/format "<%s> " (:name component-file)))
|
|
||||||
(or (:name component-shape) "?")
|
|
||||||
(if (or (:component-root? shape)
|
|
||||||
(nil? (:component-id shape))
|
|
||||||
true)
|
|
||||||
""
|
|
||||||
(let [component-id (:component-id shape)
|
|
||||||
component-file-id (:component-file shape)
|
|
||||||
component-file (when component-file-id (get libraries component-file-id nil))
|
|
||||||
component (if component-file
|
|
||||||
(get-in component-file [:data :components component-id])
|
|
||||||
(get components component-id))]
|
|
||||||
(str/format " (%s%s)"
|
|
||||||
(when component-file (str/format "<%s> " (:name component-file)))
|
|
||||||
(:name component))))))))]
|
|
||||||
|
|
||||||
(println "[Page]")
|
|
||||||
(show-shape (:id root) 0 objects)
|
|
||||||
|
|
||||||
(dorun (for [component (vals components)]
|
|
||||||
(do
|
|
||||||
(println)
|
|
||||||
(println (str/format "[%s]" (:name component))
|
|
||||||
(when show-ids
|
|
||||||
(str/format " (main: %s/%s)"
|
|
||||||
(:main-instance-page component)
|
|
||||||
(:main-instance-id component))))
|
|
||||||
(show-shape (:id component) 0 (:objects component)))))))))
|
|
||||||
|
|
||||||
(defn ^:export dump-tree
|
(defn ^:export dump-tree
|
||||||
([] (dump-tree' @st/state))
|
([] (dump-tree' @st/state))
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.types.container :as ctc]
|
[app.common.types.container :as ctn]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.groups :as dwg]
|
[app.main.data.workspace.groups :as dwg]
|
||||||
[app.main.data.workspace.libraries :as dwl]
|
[app.main.data.workspace.libraries :as dwl]
|
||||||
|
@ -521,7 +521,7 @@
|
||||||
;
|
;
|
||||||
(let [page (thp/current-page new-state)
|
(let [page (thp/current-page new-state)
|
||||||
shape1 (thp/get-shape new-state :shape1)
|
shape1 (thp/get-shape new-state :shape1)
|
||||||
parent1 (ctc/get-shape page (:parent-id shape1))
|
parent1 (ctn/get-shape page (:parent-id shape1))
|
||||||
|
|
||||||
[[group shape1 shape2]
|
[[group shape1 shape2]
|
||||||
[c-group c-shape1 c-shape2]
|
[c-group c-shape1 c-shape2]
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.types.container :as ctc]
|
[app.common.types.container :as ctn]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
[app.main.data.workspace.shapes :as dwsh]
|
[app.main.data.workspace.shapes :as dwsh]
|
||||||
|
@ -1353,7 +1353,7 @@
|
||||||
instance1 (thp/get-shape state :instance1)
|
instance1 (thp/get-shape state :instance1)
|
||||||
instance2 (thp/get-shape state :instance2)
|
instance2 (thp/get-shape state :instance2)
|
||||||
|
|
||||||
shape2 (ctc/get-shape (wsh/lookup-page state)
|
shape2 (ctn/get-shape (wsh/lookup-page state)
|
||||||
(first (:shapes instance2)))
|
(first (:shapes instance2)))
|
||||||
|
|
||||||
update-fn1 (fn [shape]
|
update-fn1 (fn [shape]
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.types.container :as ctc]
|
[app.common.types.container :as ctn]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.libraries-helpers :as dwlh]
|
[app.main.data.workspace.libraries-helpers :as dwlh]
|
||||||
[app.main.data.workspace.state-helpers :as wsh]
|
[app.main.data.workspace.state-helpers :as wsh]
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
verify that they are a well constructed instance tree."
|
verify that they are a well constructed instance tree."
|
||||||
[state root-inst-id]
|
[state root-inst-id]
|
||||||
(let [page (thp/current-page state)
|
(let [page (thp/current-page state)
|
||||||
root-inst (ctc/get-shape page root-inst-id)
|
root-inst (ctn/get-shape page root-inst-id)
|
||||||
shapes-inst (cph/get-children-with-self (:objects page)
|
shapes-inst (cph/get-children-with-self (:objects page)
|
||||||
root-inst-id)]
|
root-inst-id)]
|
||||||
(is-instance-root (first shapes-inst))
|
(is-instance-root (first shapes-inst))
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
verify that they are not a component instance."
|
verify that they are not a component instance."
|
||||||
[state root-inst-id]
|
[state root-inst-id]
|
||||||
(let [page (thp/current-page state)
|
(let [page (thp/current-page state)
|
||||||
root-inst (ctc/get-shape page root-inst-id)
|
root-inst (ctn/get-shape page root-inst-id)
|
||||||
shapes-inst (cph/get-children-with-self (:objects page)
|
shapes-inst (cph/get-children-with-self (:objects page)
|
||||||
root-inst-id)]
|
root-inst-id)]
|
||||||
(run! is-noninstance shapes-inst)
|
(run! is-noninstance shapes-inst)
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
the main component and all its shapes."
|
the main component and all its shapes."
|
||||||
[state root-inst-id]
|
[state root-inst-id]
|
||||||
(let [page (thp/current-page state)
|
(let [page (thp/current-page state)
|
||||||
root-inst (ctc/get-shape page root-inst-id)
|
root-inst (ctn/get-shape page root-inst-id)
|
||||||
|
|
||||||
libs (wsh/get-libraries state)
|
libs (wsh/get-libraries state)
|
||||||
component (cph/get-component libs (:component-id root-inst))
|
component (cph/get-component libs (:component-id root-inst))
|
||||||
|
@ -103,7 +103,7 @@
|
||||||
(cph/get-component libs (:component-id component-shape))
|
(cph/get-component libs (:component-id component-shape))
|
||||||
|
|
||||||
main-shape
|
main-shape
|
||||||
(ctc/get-shape component (:shape-ref shape))]
|
(ctn/get-shape component (:shape-ref shape))]
|
||||||
|
|
||||||
(t/is (some? main-shape))))]
|
(t/is (some? main-shape))))]
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@
|
||||||
corresponding component shape missing."
|
corresponding component shape missing."
|
||||||
[state root-inst-id]
|
[state root-inst-id]
|
||||||
(let [page (thp/current-page state)
|
(let [page (thp/current-page state)
|
||||||
root-inst (ctc/get-shape page root-inst-id)
|
root-inst (ctn/get-shape page root-inst-id)
|
||||||
|
|
||||||
libs (wsh/get-libraries state)
|
libs (wsh/get-libraries state)
|
||||||
component (cph/get-component libs (:component-id root-inst))
|
component (cph/get-component libs (:component-id root-inst))
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
(cph/get-component libs (:component-id component-shape))
|
(cph/get-component libs (:component-id component-shape))
|
||||||
|
|
||||||
main-shape
|
main-shape
|
||||||
(ctc/get-shape component (:shape-ref shape))]
|
(ctn/get-shape component (:shape-ref shape))]
|
||||||
|
|
||||||
(t/is (some? main-shape))))]
|
(t/is (some? main-shape))))]
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
|
[app.common.types.shape :as cts]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.groups :as dwg]
|
[app.main.data.workspace.groups :as dwg]
|
||||||
[app.main.data.workspace.layout :as layout]
|
[app.main.data.workspace.layout :as layout]
|
||||||
|
@ -69,9 +70,7 @@
|
||||||
([state label type props]
|
([state label type props]
|
||||||
(let [page (current-page state)
|
(let [page (current-page state)
|
||||||
frame (cph/get-frame (:objects page))
|
frame (cph/get-frame (:objects page))
|
||||||
shape (-> (cp/make-minimal-shape type)
|
shape (cts/make-shape type {:x 0 :y 0 :width 1 :height 1} props)]
|
||||||
(cp/setup-shape {:x 0 :y 0 :width 1 :height 1})
|
|
||||||
(merge props))]
|
|
||||||
(swap! idmap assoc label (:id shape))
|
(swap! idmap assoc label (:id shape))
|
||||||
(update state :workspace-data
|
(update state :workspace-data
|
||||||
cp/process-changes
|
cp/process-changes
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[cljs.test :as t :include-macros true]
|
[cljs.test :as t :include-macros true]
|
||||||
[cljs.pprint :refer [pprint]]
|
[cljs.pprint :refer [pprint]]
|
||||||
[app.common.pages.init :as init]
|
|
||||||
[app.common.file-builder :as fb]
|
[app.common.file-builder :as fb]
|
||||||
[app.util.snap-data :as sd]))
|
[app.util.snap-data :as sd]))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue