aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json199
-rw-r--r--package.json1
-rw-r--r--src/client/util/Transform.ts94
-rw-r--r--src/client/views/Main.tsx5
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx11
-rw-r--r--src/client/views/collections/CollectionFreeFormView.tsx24
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx6
-rw-r--r--src/client/views/collections/CollectionViewBase.tsx11
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx7
-rw-r--r--src/client/views/nodes/DocumentView.tsx8
10 files changed, 354 insertions, 12 deletions
diff --git a/package-lock.json b/package-lock.json
index 535c348d5..a4939f1cb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -684,6 +684,11 @@
"integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
"dev": true
},
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ },
"asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
@@ -745,6 +750,11 @@
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c="
},
+ "ast-types": {
+ "version": "0.9.6",
+ "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.9.6.tgz",
+ "integrity": "sha1-ECyenpAF0+fjgpvwxPok7oYu6bk="
+ },
"async": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
@@ -883,6 +893,11 @@
}
}
},
+ "base62": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/base62/-/base62-1.2.8.tgz",
+ "integrity": "sha512-V6YHUbjLxN1ymqNLb1DPHoU1CpfdL7d2YTIp5W3U4hhoG4hhxNmsFDs66M9EXxBiSEke5Bt5dwdfMwwZF70iLA=="
+ },
"base64-js": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
@@ -1445,8 +1460,7 @@
"commander": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
- "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
- "dev": true
+ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag=="
},
"commondir": {
"version": "1.0.1",
@@ -1454,6 +1468,36 @@
"integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=",
"dev": true
},
+ "commoner": {
+ "version": "0.10.8",
+ "resolved": "https://registry.npmjs.org/commoner/-/commoner-0.10.8.tgz",
+ "integrity": "sha1-NPw2cs0kOT6LtH5wyqApOBH08sU=",
+ "requires": {
+ "commander": "^2.5.0",
+ "detective": "^4.3.1",
+ "glob": "^5.0.15",
+ "graceful-fs": "^4.1.2",
+ "iconv-lite": "^0.4.5",
+ "mkdirp": "^0.5.0",
+ "private": "^0.1.6",
+ "q": "^1.1.2",
+ "recast": "^0.11.17"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "requires": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
"component-emitter": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz",
@@ -1594,6 +1638,11 @@
"serialize-javascript": "^1.4.0"
}
},
+ "core-js": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
+ },
"core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
@@ -1884,6 +1933,11 @@
}
}
},
+ "defined": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+ "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
+ },
"del": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz",
@@ -1969,6 +2023,15 @@
"integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==",
"dev": true
},
+ "detective": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/detective/-/detective-4.7.1.tgz",
+ "integrity": "sha512-H6PmeeUcZloWtdt4DAkFyzFL94arpHr3NOwwmVILFiy+9Qd4JTxxXrzfyGk/lmct2qVGBwTSwSXagqu2BxmWig==",
+ "requires": {
+ "acorn": "^5.2.1",
+ "defined": "^1.0.0"
+ }
+ },
"diff": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
@@ -2127,6 +2190,15 @@
"tapable": "^1.0.0"
}
},
+ "envify": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/envify/-/envify-3.4.1.tgz",
+ "integrity": "sha1-1xIjKejfFoi6dxsSUBkXyc5cvOg=",
+ "requires": {
+ "jstransform": "^11.0.3",
+ "through": "~2.3.4"
+ }
+ },
"errno": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
@@ -2196,6 +2268,11 @@
"estraverse": "^4.1.1"
}
},
+ "esprima-fb": {
+ "version": "15001.1.0-dev-harmony-fb",
+ "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-15001.1.0-dev-harmony-fb.tgz",
+ "integrity": "sha1-MKlHMDxrjV6VW+4rmbHSMyBqaQE="
+ },
"esrecurse": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
@@ -2479,6 +2556,18 @@
"websocket-driver": ">=0.5.1"
}
},
+ "fbjs": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.6.1.tgz",
+ "integrity": "sha1-lja3cF9bqWhNRLcveDISVK/IYPc=",
+ "requires": {
+ "core-js": "^1.0.0",
+ "loose-envify": "^1.0.0",
+ "promise": "^7.0.3",
+ "ua-parser-js": "^0.7.9",
+ "whatwg-fetch": "^0.9.0"
+ }
+ },
"figgy-pudding": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
@@ -3649,6 +3738,11 @@
"resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz",
"integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk="
},
+ "immutable": {
+ "version": "4.0.0-rc.12",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.0.0-rc.12.tgz",
+ "integrity": "sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A=="
+ },
"import-lazy": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz",
@@ -4092,6 +4186,11 @@
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
+ "json-stringify-pretty-compact": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-1.2.0.tgz",
+ "integrity": "sha512-/11Pj1OyX814QMKO7K8l85SHPTr/KsFxHp8GE2zVa0BtJgGimDjXHfM3FhC7keQdWDea7+nXf+f1de7ATZcZkQ=="
+ },
"json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
@@ -4122,6 +4221,46 @@
"verror": "1.10.0"
}
},
+ "jstransform": {
+ "version": "11.0.3",
+ "resolved": "https://registry.npmjs.org/jstransform/-/jstransform-11.0.3.tgz",
+ "integrity": "sha1-CaeJk+CuTU70SH9hVakfYZDLQiM=",
+ "requires": {
+ "base62": "^1.1.0",
+ "commoner": "^0.10.1",
+ "esprima-fb": "^15001.1.0-dev-harmony-fb",
+ "object-assign": "^2.0.0",
+ "source-map": "^0.4.2"
+ },
+ "dependencies": {
+ "object-assign": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz",
+ "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo="
+ }
+ }
+ },
+ "jsx-to-string": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/jsx-to-string/-/jsx-to-string-1.4.0.tgz",
+ "integrity": "sha1-Ztw013PaufQP6ZPP+ZQOXaZVtwU=",
+ "requires": {
+ "immutable": "^4.0.0-rc.9",
+ "json-stringify-pretty-compact": "^1.0.1",
+ "react": "^0.14.0"
+ },
+ "dependencies": {
+ "react": {
+ "version": "0.14.9",
+ "resolved": "https://registry.npmjs.org/react/-/react-0.14.9.tgz",
+ "integrity": "sha1-kRCmSXxJ1EuhwO3TF67CnC4NkdE=",
+ "requires": {
+ "envify": "^3.0.0",
+ "fbjs": "^0.6.1"
+ }
+ }
+ }
+ },
"killable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -8491,6 +8630,11 @@
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
"integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw="
},
+ "private": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
+ "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg=="
+ },
"process": {
"version": "0.11.10",
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
@@ -8502,6 +8646,14 @@
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
"integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw=="
},
+ "promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "requires": {
+ "asap": "~2.0.3"
+ }
+ },
"promise-inflight": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
@@ -8659,6 +8811,11 @@
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
+ "q": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
+ "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
+ },
"qs": {
"version": "6.5.2",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
@@ -8879,6 +9036,29 @@
"readable-stream": "^2.0.2"
}
},
+ "recast": {
+ "version": "0.11.23",
+ "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz",
+ "integrity": "sha1-RR/TAEqx5N+bTktmN2sqIZEkYtM=",
+ "requires": {
+ "ast-types": "0.9.6",
+ "esprima": "~3.1.0",
+ "private": "~0.1.5",
+ "source-map": "~0.5.0"
+ },
+ "dependencies": {
+ "esprima": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+ "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
+ }
+ }
+ },
"redent": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
@@ -10075,6 +10255,11 @@
"native-promise-only": "^0.8.1"
}
},
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+ },
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
@@ -10263,6 +10448,11 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.3.1.tgz",
"integrity": "sha512-cTmIDFW7O0IHbn1DPYjkiebHxwtCMU+eTy30ZtJNBPF9j2O1ITu5XH2YnBeVRKWHqF+3JQwWJv0Q0aUgX8W7IA=="
},
+ "ua-parser-js": {
+ "version": "0.7.19",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.19.tgz",
+ "integrity": "sha512-T3PVJ6uz8i0HzPxOF9SWzWAlfN/DavlpQqepn22xgve/5QecC+XMCAtmUNnY7C9StehaV6exjUCI801lOI7QlQ=="
+ },
"undefsafe": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.2.tgz",
@@ -11238,6 +11428,11 @@
"integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
"dev": true
},
+ "whatwg-fetch": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz",
+ "integrity": "sha1-DjaExsuZlbQ+/J3wPkw2XZX9nMA="
+ },
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
diff --git a/package.json b/package.json
index 6697b5f47..657bb875d 100644
--- a/package.json
+++ b/package.json
@@ -50,6 +50,7 @@
"express": "^4.16.4",
"flexlayout-react": "^0.3.3",
"golden-layout": "^1.5.9",
+ "jsx-to-string": "^1.4.0",
"mobx": "^5.9.0",
"mobx-react": "^5.3.5",
"mobx-react-devtools": "^6.0.3",
diff --git a/src/client/util/Transform.ts b/src/client/util/Transform.ts
new file mode 100644
index 000000000..7861ed308
--- /dev/null
+++ b/src/client/util/Transform.ts
@@ -0,0 +1,94 @@
+export class Transform {
+ private _translateX: number = 0;
+ private _translateY: number = 0;
+ private _scale: number = 1;
+
+ static get Identity(): Transform {
+ return new Transform(0, 0, 1);
+ }
+
+ constructor(x: number, y: number, scale: number) {
+ this._translateX = x;
+ this._translateY = y;
+ this._scale = scale;
+ }
+
+ translate = (x: number, y: number): Transform => {
+ this._translateX += x;
+ this._translateY += y;
+ return this;
+ }
+
+ translated = (x: number, y: number): Transform => {
+ return this.copy().translate(x, y);
+ }
+
+ preTranslate = (x: number, y: number): Transform => {
+ this._translateX += x * this._scale;
+ this._translateY += y * this._scale;
+ return this;
+ }
+
+ preTranslated = (x: number, y: number): Transform => {
+ return this.copy().preTranslate(x, y);
+ }
+
+ scale = (scale: number): Transform => {
+ this._scale *= scale;
+ return this;
+ }
+
+ scaled = (scale: number): Transform => {
+ return this.copy().scale(scale);
+ }
+
+ preScale = (scale: number): Transform => {
+ this._scale *= scale;
+ this._translateX *= scale;
+ this._translateY *= scale;
+ return this;
+ }
+
+ preScaled = (scale: number): Transform => {
+ return this.copy().preScale(scale);
+ }
+
+ transform = (transform: Transform): Transform => {
+ this._translateX += transform._translateX * this._scale;
+ this._translateY += transform._translateY * this._scale;
+ this._scale *= transform._scale;
+ return this;
+ }
+
+ transformed = (transform: Transform): Transform => {
+ return this.copy().transform(transform);
+ }
+
+ preTransform = (transform: Transform): Transform => {
+ this._translateX = transform._translateX + this._translateX * transform._scale;
+ this._translateY = transform._translateY + this._translateY * transform._scale;
+ this._scale *= transform._scale;
+ return this;
+ }
+
+ preTransformed = (transform: Transform): Transform => {
+ return this.copy().preTransform(transform);
+ }
+
+ transformPoint = (x: number, y: number): [number, number] => {
+ x *= this._scale;
+ x += this._translateX;
+ y *= this._scale;
+ y += this._translateY;
+ return [x, y];
+ }
+
+ inverse = () => {
+ return new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale)
+ }
+
+ copy = () => {
+ return new Transform(this._translateX, this._translateY, this._scale);
+ }
+
+} \ No newline at end of file
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 9a359e868..ac6f1de00 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -13,6 +13,7 @@ import "./Main.scss";
import { ContextMenu } from './ContextMenu';
import { DocumentView } from './nodes/DocumentView';
import { ImageField } from '../../fields/ImageField';
+import { Transform } from '../util/Transform';
configure({
@@ -84,7 +85,9 @@ document.addEventListener("pointerdown", action(function (e: PointerEvent) {
ReactDOM.render((
<div style={{ position: "absolute", width: "100%", height: "100%" }}>
- <DocumentView Document={mainContainer} ContainingCollectionView={undefined} DocumentView={undefined} />
+ <DocumentView Document={mainContainer}
+ AddDocument={undefined} RemoveDocument={undefined} GetTransform={() => Transform.Identity}
+ ContainingCollectionView={undefined} DocumentView={undefined} />
<DocumentDecorations />
<ContextMenu />
</div>),
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 9aee9c10f..32d00d41a 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -14,6 +14,7 @@ import * as GoldenLayout from "golden-layout";
import * as ReactDOM from 'react-dom';
import { DragManager } from "../../util/DragManager";
import { CollectionViewBase, CollectionViewProps, COLLECTION_BORDER_WIDTH } from "./CollectionViewBase";
+import { Transform } from "../../util/Transform";
@observer
export class CollectionDockingView extends CollectionViewBase {
@@ -95,7 +96,10 @@ export class CollectionDockingView extends CollectionViewBase {
const value: Document[] = Document.GetData(fieldKey, ListField, []);
for (var i: number = 0; i < value.length; i++) {
if (value[i].Id === component) {
- return (<DocumentView key={value[i].Id} ContainingCollectionView={this} Document={value[i]} DocumentView={undefined} />);
+ return (<DocumentView key={value[i].Id} Document={value[i]}
+ AddDocument={this.addDocument} RemoveDocument={this.removeDocument}
+ GetTransform={() => Transform.Identity}
+ ContainingCollectionView={this} DocumentView={undefined} />);
}
}
if (component === "text") {
@@ -236,7 +240,10 @@ export class CollectionDockingView extends CollectionViewBase {
container.getElement().html("<div id='" + containingDiv + "'></div>");
setTimeout(function () {
ReactDOM.render((
- <DocumentView key={state.doc.Id} Document={state.doc} ContainingCollectionView={me} DocumentView={undefined} />
+ <DocumentView key={state.doc.Id} Document={state.doc}
+ AddDocument={me.addDocument} RemoveDocument={me.removeDocument}
+ GetTransform={() => Transform.Identity}
+ ContainingCollectionView={me} DocumentView={undefined} />
),
document.getElementById(containingDiv)
);
diff --git a/src/client/views/collections/CollectionFreeFormView.tsx b/src/client/views/collections/CollectionFreeFormView.tsx
index 9cf29d000..50f4f1892 100644
--- a/src/client/views/collections/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/CollectionFreeFormView.tsx
@@ -13,6 +13,7 @@ import { ListField } from "../../../fields/ListField";
import { NumberField } from "../../../fields/NumberField";
import { Documents } from "../../documents/Documents";
import { FieldWaiting } from "../../../fields/Field";
+import { Transform } from "../../util/Transform";
@observer
export class CollectionFreeFormView extends CollectionViewBase {
@@ -172,6 +173,23 @@ export class CollectionFreeFormView extends CollectionViewBase {
}
}
+ @computed
+ get translate(): [number, number] {
+ const x = this.props.DocumentForCollection.GetNumber(KeyStore.PanX, 0);
+ const y = this.props.DocumentForCollection.GetNumber(KeyStore.PanY, 0);
+ return [x, y];
+ }
+
+ @computed
+ get scale(): number {
+ return this.props.DocumentForCollection.GetNumber(KeyStore.Scale, 1);
+ }
+
+ getTransform = (): Transform => {
+ const [x, y] = this.translate;
+ return this.props.GetTransform().scaled(this.scale).translate(x, y);
+ }
+
render() {
const { CollectionFieldKey: fieldKey, DocumentForCollection: Document } = this.props;
const value: Document[] = Document.GetList<Document>(fieldKey, []);
@@ -194,7 +212,11 @@ export class CollectionFreeFormView extends CollectionViewBase {
<div className="node-container" ref={this._nodeContainerRef}>
{value.map(doc => {
- return (<CollectionFreeFormDocumentView key={doc.Id} ContainingCollectionView={this} Document={doc} DocumentView={undefined} />);
+ return (<CollectionFreeFormDocumentView key={doc.Id} Document={doc}
+ AddDocument={this.addDocument}
+ RemoveDocument={this.removeDocument}
+ GetTransform={this.getTransform}
+ ContainingCollectionView={this} DocumentView={undefined} />);
})}
</div>
</div>
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index 2d5bd6c99..b897fd481 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -14,6 +14,7 @@ import { CompileScript, ToField } from "../../util/Scripting";
import { KeyStore as KS, Key } from "../../../fields/Key";
import { Document } from "../../../fields/Document";
import { Field } from "../../../fields/Field";
+import { Transform } from "../../util/Transform";
@observer
export class CollectionSchemaView extends CollectionViewBase {
@@ -104,7 +105,10 @@ export class CollectionSchemaView extends CollectionViewBase {
let content;
if (this.selectedIndex != -1) {
content = (
- <DocumentView Document={children[this.selectedIndex]} DocumentView={undefined} ContainingCollectionView={this} />
+ <DocumentView Document={children[this.selectedIndex]}
+ AddDocument={this.addDocument} RemoveDocument={this.removeDocument}
+ GetTransform={() => Transform.Identity}//TODO This should probably be an actual transform
+ DocumentView={undefined} ContainingCollectionView={this} />
)
} else {
content = <div />
diff --git a/src/client/views/collections/CollectionViewBase.tsx b/src/client/views/collections/CollectionViewBase.tsx
index 09e8ec729..ff54d88d7 100644
--- a/src/client/views/collections/CollectionViewBase.tsx
+++ b/src/client/views/collections/CollectionViewBase.tsx
@@ -10,12 +10,14 @@ import React = require("react");
import { DocumentView } from "../nodes/DocumentView";
import { CollectionDockingView } from "./CollectionDockingView";
import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView";
+import { Transform } from "../../util/Transform";
export interface CollectionViewProps {
CollectionFieldKey: Key;
DocumentForCollection: Document;
ContainingDocumentView: Opt<DocumentView>;
+ GetTransform: () => Transform;
}
export const COLLECTION_BORDER_WIDTH = 2;
@@ -43,15 +45,18 @@ export class CollectionViewBase extends React.Component<CollectionViewProps> {
}
@action
- removeDocument = (doc: Document): void => {
+ removeDocument = (doc: Document): boolean => {
//TODO This won't create the field if it doesn't already exist
const value = this.props.DocumentForCollection.GetData(this.props.CollectionFieldKey, ListField, new Array<Document>())
- if (value.indexOf(doc) !== -1) {
- value.splice(value.indexOf(doc), 1)
+ let index = value.indexOf(doc);
+ if (index !== -1) {
+ value.splice(index, 1)
SelectionManager.DeselectAll()
ContextMenu.Instance.clearItems()
+ return true;
}
+ return false
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index a111a9936..0defc8f1d 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -10,6 +10,7 @@ import { ContextMenu } from "../ContextMenu";
import "./NodeView.scss";
import React = require("react");
import { DocumentView, DocumentViewProps } from "./DocumentView";
+import { Transform } from "../../util/Transform";
@observer
@@ -204,6 +205,10 @@ export class CollectionFreeFormDocumentView extends DocumentView {
}
}
+ getTransform = (): Transform => {
+ return this.props.GetTransform().translated(this.x, this.y);
+ }
+
render() {
var freestyling = this.props.ContainingCollectionView instanceof CollectionFreeFormView;
return (
@@ -217,7 +222,7 @@ export class CollectionFreeFormDocumentView extends DocumentView {
onContextMenu={this.onContextMenu}
onPointerDown={this.onPointerDown}>
- <DocumentView {...this.props} DocumentView={this.props.DocumentView} />
+ <DocumentView {...this.props} GetTransform={this.getTransform} DocumentView={this.props.DocumentView} />
</div>
);
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 730ce62f2..ce23a70a6 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -15,13 +15,19 @@ import { FormattedTextBox } from "../nodes/FormattedTextBox";
import { ImageBox } from "../nodes/ImageBox";
import "./NodeView.scss";
import React = require("react");
+import { Transform } from "../../util/Transform";
const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this?
export interface DocumentViewProps {
- Document: Document;
DocumentView: Opt<DocumentView> // needed only to set ContainingDocumentView on CollectionViewProps when invoked from JsxParser -- is there a better way?
ContainingCollectionView: Opt<CollectionViewBase>;
+
+ Document: Document;
+ AddDocument?: (doc: Document) => void;
+ RemoveDocument?: (doc: Document) => boolean;
+ GetTransform: () => Transform;
}
+
@observer
export class DocumentView extends React.Component<DocumentViewProps> {