From 481ca03c47962b301199285feebdb73a66818a9f Mon Sep 17 00:00:00 2001 From: yipstanley Date: Sun, 20 Jan 2019 19:48:04 -0500 Subject: switching to cffv --- src/Main.scss | 1 + src/Main.tsx | 31 +++++++++++++++------- .../freeformcanvas/CollectionFreeFormView.tsx | 5 ++-- 3 files changed, 25 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/Main.scss b/src/Main.scss index f986d2c96..441716e5c 100644 --- a/src/Main.scss +++ b/src/Main.scss @@ -4,6 +4,7 @@ body { height: 100%; overflow: hidden; font-family: 'Hind Siliguri', sans-serif; + margin: 0; } h1 { diff --git a/src/Main.tsx b/src/Main.tsx index f911b6098..e417c0690 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -5,24 +5,31 @@ import { NodeCollectionStore } from './stores/NodeCollectionStore'; import { StaticTextNodeStore } from './stores/StaticTextNodeStore'; import { VideoNodeStore } from './stores/VideoNodeStore'; import { FreeFormCanvas } from './views/freeformcanvas/FreeFormCanvas'; -import { Key, KeyStore as KS } from './fields/Key'; +import { Key, KeyStore as KS, KeyStore } from './fields/Key'; import { NumberField } from './fields/NumberField'; import { Document } from './fields/Document'; import { configure, runInAction } from 'mobx'; import { NodeStore } from './stores/NodeStore'; import { Documents } from './documents/Documents'; import { DocumentDecorations } from './DocumentDecorations'; +import { CollectionFreeFormView } from './views/freeformcanvas/CollectionFreeFormView'; +import { ListField } from './fields/ListField'; +import { DocumentView } from './views/nodes/DocumentView'; +import { DocumentViewModel } from './viewmodels/DocumentViewModel'; configure({ enforceActions: "observed" }); -const mainNodeCollection = new NodeCollectionStore(); +const mainNodeCollection = new Array(); +let mainContainer = Documents.CollectionDocument(mainNodeCollection, { + x: 0, y: 0, width: window.screen.width, height: window.screen.height +}) ReactDOM.render(( -
+

Dash Web

- +
), document.getElementById('root')); @@ -41,7 +48,6 @@ for (let i = 0; i < 20; i++) { } runInAction(() => { - mainNodeCollection.AddNodes(nodes); let doc1 = Documents.TextDocument("Hello world"); let doc2 = doc1.MakeDelegate(); doc2.SetField(KS.X, new NumberField(150)); @@ -56,9 +62,14 @@ runInAction(() => { let doc5 = Documents.ImageDocument("https://static.boredpanda.com/blog/wp-content/uploads/2018/04/5acb63d83493f__700-png.jpg", { x: 650, y: 500 }); - mainNodeCollection.Docs.push(doc1); - mainNodeCollection.Docs.push(doc2); - mainNodeCollection.Docs.push(doc4); - mainNodeCollection.Docs.push(doc3); - mainNodeCollection.Docs.push(doc5); + let mainNodes = mainContainer.GetFieldT(KeyStore.Data, ListField); + if (!mainNodes) { + mainNodes = new ListField(); + mainContainer.SetField(KeyStore.Data, mainNodes); + } + mainNodes.Data.push(doc1); + mainNodes.Data.push(doc2); + mainNodes.Data.push(doc4); + mainNodes.Data.push(doc3); + mainNodes.Data.push(doc5); }); \ No newline at end of file diff --git a/src/views/freeformcanvas/CollectionFreeFormView.tsx b/src/views/freeformcanvas/CollectionFreeFormView.tsx index 4e9e0cd21..4c8fcec10 100644 --- a/src/views/freeformcanvas/CollectionFreeFormView.tsx +++ b/src/views/freeformcanvas/CollectionFreeFormView.tsx @@ -10,6 +10,7 @@ import { ListField } from "../../fields/ListField"; import { NumberField } from "../../fields/NumberField"; import { SSL_OP_SINGLE_DH_USE } from "constants"; import { DocumentDecorations } from "../../DocumentDecorations"; +import { SelectionManager } from "../../util/SelectionManager"; interface IProps { fieldKey: Key; @@ -94,8 +95,8 @@ export class CollectionFreeFormView extends React.Component { height: "calc(100% - 4px)", overflow: "hidden" }}> -
-
+
+
{value.map(doc => { return (); })} -- cgit v1.2.3-70-g09d2 From 6a04f60ce76fbd8274dd9daf285042f9cab16656 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 21 Jan 2019 21:42:03 -0500 Subject: context menu basics working --- package-lock.json | 73 +++++++++------- package.json | 1 + src/DocumentDecorations.scss | 1 - src/Main.tsx | 21 ++++- src/documents/Documents.ts | 6 +- src/fields/Key.ts | 1 + src/viewmodels/DocumentViewModel.ts | 10 +-- src/views/ContextMenu.scss | 34 ++++++++ src/views/ContextMenu.tsx | 68 +++++++++++++++ src/views/ContextMenuItem.tsx | 17 ++++ .../freeformcanvas/CollectionFreeFormView.tsx | 96 ++++++++++++++++++---- src/views/freeformcanvas/FreeFormCanvas.tsx | 6 +- src/views/nodes/DocumentView.tsx | 48 +++++++++-- src/views/nodes/FieldTextBox.scss | 10 +++ src/views/nodes/FieldTextBox.tsx | 5 +- 15 files changed, 329 insertions(+), 68 deletions(-) create mode 100644 src/views/ContextMenu.scss create mode 100644 src/views/ContextMenu.tsx create mode 100644 src/views/ContextMenuItem.tsx create mode 100644 src/views/nodes/FieldTextBox.scss (limited to 'src') diff --git a/package-lock.json b/package-lock.json index 955f0f3ae..7dfe02494 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,16 +4,29 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@fortawesome/fontawesome-common-types": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.12.tgz", + "integrity": "sha512-ISLNpEx6fhJTYYkvBeo/4DHeL5EIA+VybJoOOnH67m6uXt6V6VFizdEN4qchHagNIeZfzI0LnA22gk0wbVPv/g==" + }, + "@fortawesome/fontawesome-svg-core": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.12.tgz", + "integrity": "sha512-cqTfa3vZ+Z9UYQnmLfCOwyLnf0Xcoxkmm/BSaI29Yikzu9zIeD4es7lBZMDqLOXYSEQC+rCr8caxFlGJcJVA+w==", + "requires": { + "@fortawesome/fontawesome-common-types": "^0.2.12" + } + }, "@types/chai": { "version": "4.1.7", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.7.tgz", - "integrity": "sha512-2Y8uPt0/jwjhQ6EiluT0XCri1Dbplr0ZxfFXUz+ye13gaqE8u5gL5ppao1JrUYr9cIip5S6MvQzBS7Kke7U9VA==", + "integrity": "sha1-G44zthqMCcvh+FEzBxuqDb+fpxo=", "dev": true }, "@types/mocha": { "version": "5.2.5", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.5.tgz", - "integrity": "sha512-lAVp+Kj54ui/vLUFxsJTMtWvZraZxum3w3Nwkble2dNuV5VnPA+Mi2oGX9XYJAaIvZi3tn3cbjS/qcJXRb6Bww==", + "integrity": "sha1-ikrM/EA8EkoLr+ip/GGgXsEDIHM=", "dev": true }, "@types/node": { @@ -117,7 +130,7 @@ "@types/react-dom": { "version": "16.0.11", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.0.11.tgz", - "integrity": "sha512-x6zUx9/42B5Kl2Vl9HlopV8JF64wLpX3c+Pst9kc1HgzrsH+mkehe/zmHMQTplIrR48H2gpU7ZqurQolYu8XBA==", + "integrity": "sha1-vRDMsNkmA0P0uaSdT3qDMKXB8IE=", "dev": true, "requires": { "@types/react": "*" @@ -126,7 +139,7 @@ "@types/uuid": { "version": "3.4.4", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.4.tgz", - "integrity": "sha512-tPIgT0GUmdJQNSHxp0X2jnpQfBSTfGxUMc/2CXBU2mnyTFVYVa2ojpoQ74w0U2yn2vw3jnC640+77lkFFpdVDw==", + "integrity": "sha1-evaTYPpl7w3stB/RUL9MpcDO/fU=", "requires": { "@types/node": "*" } @@ -579,7 +592,7 @@ "awesome-typescript-loader": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/awesome-typescript-loader/-/awesome-typescript-loader-5.2.1.tgz", - "integrity": "sha512-slv66OAJB8orL+UUaTI3pKlLorwIvS4ARZzYR9iJJyGsEgOqueMfOMdKySWzZ73vIkEe3fcwFgsKMg4d8zyb1g==", + "integrity": "sha1-pB2veEdRX0klzbqjB11h8onpE/w=", "dev": true, "requires": { "chalk": "^2.4.1", @@ -982,7 +995,7 @@ "chai": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", + "integrity": "sha1-dgqnLPION5XoSxKHfODoNzeqKeU=", "dev": true, "requires": { "assertion-error": "^1.1.0", @@ -1289,7 +1302,7 @@ "copy-webpack-plugin": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-4.6.0.tgz", - "integrity": "sha512-Y+SQCF+0NoWQryez2zXn5J5knmr9z/9qSQt7fbL78u83rxmigOy8X5+BFn8CFSuX+nKT8gpYwJX68ekqtQt6ZA==", + "integrity": "sha1-5/QN2KaEd9QF3Rt6hUquMksVi64=", "dev": true, "requires": { "cacache": "^10.0.4", @@ -1388,7 +1401,7 @@ "p-limit": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "integrity": "sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg=", "dev": true, "requires": { "p-try": "^1.0.0" @@ -1534,7 +1547,7 @@ "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, "requires": { "ajv": "^6.1.0", @@ -4165,12 +4178,12 @@ "mobx": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/mobx/-/mobx-5.8.0.tgz", - "integrity": "sha512-NsZB+9bF5j+nv9Qwk6bNeE3np26a4TbTGkMpOLf6o1zXoM9BtHPQn/00px4uZ2AXJXtQML5P4MEWdMm6icMIfQ==" + "integrity": "sha1-z1nq5Lqi/eQ4f/tkYrfM87SXsDw=" }, "mobx-react": { "version": "5.4.3", "resolved": "https://registry.npmjs.org/mobx-react/-/mobx-react-5.4.3.tgz", - "integrity": "sha512-WC8yFlwvJ91hy8j6CrydAuFteUafcuvdITFQeHl3LRIf5ayfT/4W3M/byhEYD2BcJWejeXr8y4Rh2H26RunCRQ==", + "integrity": "sha1-Zwm33YlnDEDpgVkUrCyknMAr+0c=", "requires": { "hoist-non-react-statics": "^3.0.0", "react-lifecycles-compat": "^3.0.2" @@ -4179,12 +4192,12 @@ "mobx-react-devtools": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/mobx-react-devtools/-/mobx-react-devtools-6.0.3.tgz", - "integrity": "sha512-PY+lG6XeWaC0DFnDaVC7ImrHJQu7XVXNy4z4fmqHzWc3p+fJisKmaZNwgToO2vJGBghz98Mx2yXUBLw1Ba2mPQ==" + "integrity": "sha1-TVNsjN132fS4H16EFde+3MxqKpk=" }, "mocha": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "integrity": "sha1-bYrlCPWRZ/lA8rWzxKYSrlDJCuY=", "dev": true, "requires": { "browser-stdout": "1.3.1", @@ -4203,13 +4216,13 @@ "commander": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "integrity": "sha1-30boZ9D8Kuxmo0ZitAapzK//Ww8=", "dev": true }, "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", "dev": true, "requires": { "ms": "2.0.0" @@ -4218,7 +4231,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -4232,7 +4245,7 @@ "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "integrity": "sha1-HGszdALCE3YF7+GfEP7DkPb6q1Q=", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -4398,7 +4411,7 @@ "node-sass": { "version": "4.11.0", "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz", - "integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==", + "integrity": "sha1-GD+uw5jpy+k7pDNi4naMqYimNpo=", "requires": { "async-foreach": "^0.1.3", "chalk": "^1.1.1", @@ -5206,7 +5219,7 @@ "react": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/react/-/react-16.7.0.tgz", - "integrity": "sha512-StCz3QY8lxTb5cl2HJxjwLFOXPIFQp+p+hxQfc8WE0QiLfCtIlKj8/+5tjjKm8uSTlAW+fCPaavGFS06V9Ar3A==", + "integrity": "sha512-ZUj2lkUDLjwJaGu4WD0dYSvsfIyhQt2l/AJDlg4ij+rCDU3fSFKgHWanNovViUoaWHAxgrpft3KGFfvWPZH5LA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -5217,7 +5230,7 @@ "react-dom": { "version": "16.7.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.7.0.tgz", - "integrity": "sha512-D0Ufv1ExCAmF38P2Uh1lwpminZFRXEINJe53zRAbm4KPwSyd6DY/uDoS0Blj9jvPpn1+wivKpZYc8aAAN/nAkg==", + "integrity": "sha512-GfG8Vh/jMcnJKDpv7T6O1pS/WVqiocjPQ9o9cscW8bjR9W36DT3Xb4pDZT70t1xyVvX48/NrTQGz0H7I3fCLhQ==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", @@ -5233,7 +5246,7 @@ "react-jsx-parser": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/react-jsx-parser/-/react-jsx-parser-1.13.0.tgz", - "integrity": "sha512-oypIhM30ESZ8UkU0xDmzSV2Mtb2mVvtVnyNzjDxx2h2PCHpYFdDVLx1c15E3ot6nTIVlIh072tWwS3iJ7VVgmg==", + "integrity": "sha1-Dstuus1O41S68+h85SXcJuiPJtQ=", "requires": { "acorn-jsx": "^4.1.1", "react": "^16.4.0" @@ -5618,7 +5631,7 @@ "sass-loader": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz", - "integrity": "sha512-+G+BKGglmZM2GUSfT9TLuEp6tzehHPjAMoRRItOojWIqIGPloVCMhNIQuG639eJ+y033PaGTSjLaTHts8Kw79w==", + "integrity": "sha1-Fv1ROMuLQkv4p1lSihly1yqtBp0=", "dev": true, "requires": { "clone-deep": "^2.0.1", @@ -6321,7 +6334,7 @@ "style-loader": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", - "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "integrity": "sha1-y5FUYG8+dxq2xKtjcCahBJF02SU=", "dev": true, "requires": { "loader-utils": "^1.1.0", @@ -6331,7 +6344,7 @@ "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, "requires": { "ajv": "^6.1.0", @@ -6525,7 +6538,7 @@ "ts-node": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-7.0.1.tgz", - "integrity": "sha512-BVwVbPJRspzNh2yfslyT1PSbl5uIk03EZlb493RKHN4qej/D06n1cEhjlOJG69oFsE7OT8XjpTUcYf6pKTLMhw==", + "integrity": "sha1-lWLcLR5tJI0kvFX3c+P2FDN9m68=", "dev": true, "requires": { "arrify": "^1.0.0", @@ -6775,7 +6788,7 @@ "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + "integrity": "sha1-G0r0lV6zB3xQHCOHL8ZROBFYcTE=" }, "v8-compile-cache": { "version": "2.0.2", @@ -6925,7 +6938,7 @@ "webpack-dev-server": { "version": "3.1.14", "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.1.14.tgz", - "integrity": "sha512-mGXDgz5SlTxcF3hUpfC8hrQ11yhAttuUQWf1Wmb+6zo3x6rb7b9mIfuQvAPLdfDRCGRGvakBWHdHOa0I9p/EVQ==", + "integrity": "sha1-YPsim5l/xaCh/GI3QhAwGAlZ1Gk=", "dev": true, "requires": { "ansi-html": "0.0.7", @@ -6963,7 +6976,7 @@ "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "integrity": "sha1-6D0X3hbYp++3cX7b5fsQE17uYps=", "dev": true, "requires": { "ms": "^2.1.1" @@ -6978,7 +6991,7 @@ "schema-utils": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "integrity": "sha1-C3mpMgTXtgDUsoUNH2bCo0lRx3A=", "dev": true, "requires": { "ajv": "^6.1.0", @@ -6989,7 +7002,7 @@ "webpack-log": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", - "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "integrity": "sha1-W3ko4GN1k/EZ0y9iJ8HgrDHhtH8=", "dev": true, "requires": { "ansi-colors": "^3.0.0", diff --git a/package.json b/package.json index 08e999058..71ca3cc8b 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "webpack-dev-server": "^3.1.14" }, "dependencies": { + "@fortawesome/fontawesome-svg-core": "^1.2.12", "@types/prosemirror-commands": "^1.0.1", "@types/prosemirror-history": "^1.0.1", "@types/prosemirror-keymap": "^1.0.1", diff --git a/src/DocumentDecorations.scss b/src/DocumentDecorations.scss index fff4d201a..5a9ff7d01 100644 --- a/src/DocumentDecorations.scss +++ b/src/DocumentDecorations.scss @@ -1,6 +1,5 @@ #documentDecorations-container { position: absolute; - z-index: 1000; display: grid; grid-template-rows: 20px 1fr 20px; grid-template-columns: 20px 1fr 20px; diff --git a/src/Main.tsx b/src/Main.tsx index 0a683c858..cb91c33a3 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -9,7 +9,7 @@ import { FreeFormCanvas } from './views/freeformcanvas/FreeFormCanvas'; import { Key, KeyStore as KS, KeyStore } from './fields/Key'; import { NumberField } from './fields/NumberField'; import { Document } from './fields/Document'; -import { configure, runInAction } from 'mobx'; +import { configure, runInAction, action } from 'mobx'; import { NodeStore } from './stores/NodeStore'; import { Documents } from './documents/Documents'; import { DocumentDecorations } from './DocumentDecorations'; @@ -17,6 +17,7 @@ import { CollectionFreeFormView } from './views/freeformcanvas/CollectionFreeFor import { ListField } from './fields/ListField'; import { DocumentView } from './views/nodes/DocumentView'; import { DocumentViewModel } from './viewmodels/DocumentViewModel'; +import { ContextMenu } from './views/ContextMenu'; configure({ enforceActions: "observed" @@ -26,11 +27,27 @@ const mainNodeCollection = new Array(); let mainContainer = Documents.CollectionDocument(mainNodeCollection, { x: 0, y: 0, width: window.screen.width, height: window.screen.height }) +let mainContvm = new DocumentViewModel(mainContainer); +mainContvm.IsMainDoc = true; + +window.addEventListener("drop", function(e) { + e.preventDefault(); +}, false) +window.addEventListener("dragover", function(e) { + e.preventDefault(); +}, false) +document.addEventListener("pointerdown", action(function(e: PointerEvent) { + if (!ContextMenu.Instance.intersects(e.pageX, e.pageY)) { + ContextMenu.Instance.clearItems() + } +}), true) + ReactDOM.render((

Dash Web

+ - +
), document.getElementById('root')); diff --git a/src/documents/Documents.ts b/src/documents/Documents.ts index cc08f4123..75cc3b491 100644 --- a/src/documents/Documents.ts +++ b/src/documents/Documents.ts @@ -35,7 +35,7 @@ export namespace Documents { textProto.SetField(KeyStore.Y, new NumberField(0)); textProto.SetField(KeyStore.Width, new NumberField(300)); textProto.SetField(KeyStore.Height, new NumberField(150)); - textProto.SetField(KeyStore.Layout, new TextField("")); + textProto.SetField(KeyStore.Layout, new TextField("")); textProto.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); } return textProto; @@ -73,11 +73,11 @@ export namespace Documents { function GetCollectionPrototype(): Document { if(!collectionProto) { collectionProto = new Document(); - collectionProto.SetField(KeyStore.X, new NumberField(150)); + collectionProto.SetField(KeyStore.X, new NumberField(0)); collectionProto.SetField(KeyStore.Y, new NumberField(0)); collectionProto.SetField(KeyStore.Width, new NumberField(300)); collectionProto.SetField(KeyStore.Height, new NumberField(300)); - collectionProto.SetField(KeyStore.Layout, new TextField('')); + collectionProto.SetField(KeyStore.Layout, new TextField('')); collectionProto.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); } return collectionProto; diff --git a/src/fields/Key.ts b/src/fields/Key.ts index db30f545d..1f8ba0be5 100644 --- a/src/fields/Key.ts +++ b/src/fields/Key.ts @@ -36,6 +36,7 @@ export namespace KeyStore { export let Y = new Key("Y"); export let PanX = new Key("PanX"); export let PanY = new Key("PanY"); + export let Scale = new Key("Scale"); export let Width = new Key("Width"); export let Height = new Key("Height"); export let Data = new Key("Data"); diff --git a/src/viewmodels/DocumentViewModel.ts b/src/viewmodels/DocumentViewModel.ts index f3154db54..21e88f964 100644 --- a/src/viewmodels/DocumentViewModel.ts +++ b/src/viewmodels/DocumentViewModel.ts @@ -9,13 +9,13 @@ export class DocumentViewModel { return this.doc; } - private _selected = false; + private _isMainDoc = false - get Selected() : boolean { - return this._selected; + get IsMainDoc(): boolean { + return this._isMainDoc; } - set Selected(isSelected: boolean) { - this._selected = isSelected; + set IsMainDoc(v: boolean) { + this._isMainDoc = v; } } \ No newline at end of file diff --git a/src/views/ContextMenu.scss b/src/views/ContextMenu.scss new file mode 100644 index 000000000..234f82eb9 --- /dev/null +++ b/src/views/ContextMenu.scss @@ -0,0 +1,34 @@ +.contextMenu-cont { + position: absolute; + display: flex; + z-index: 1000; + box-shadow: #AAAAAA .2vw .2vw .4vw; +} + +.contextMenu-item { + width: 10vw; + height: 4vh; + background: #DDDDDD; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + transition: all .1s; +} + +.contextMenu-item:hover { + transition: all .1s; + background: #AAAAAA +} + +.contextMenu-description { + font-size: 1.5vw; + text-align: left; + width: 8vw; +} \ No newline at end of file diff --git a/src/views/ContextMenu.tsx b/src/views/ContextMenu.tsx new file mode 100644 index 000000000..299ce91c6 --- /dev/null +++ b/src/views/ContextMenu.tsx @@ -0,0 +1,68 @@ +import React = require("react"); +import { ContextMenuItem, ContextMenuProps } from "./ContextMenuItem"; +import { observable } from "mobx"; +import { observer } from "mobx-react"; +import "./ContextMenu.scss" + +@observer +export class ContextMenu extends React.Component { + static Instance: ContextMenu + + @observable private _items: Array = [{description:"test", event:(e:React.MouseEvent) => e.preventDefault()}]; + @observable private _pageX: number = 0; + @observable private _pageY: number = 0; + @observable private _display: string = "none"; + + private ref: React.RefObject; + + constructor(props: Readonly<{}>) { + super(props); + + this.ref = React.createRef() + + ContextMenu.Instance = this; + } + + clearItems() { + this._items = [] + this._display = "none" + } + + addItem(item: ContextMenuProps) { + if (this._items.indexOf(item) === -1) { + this._items.push(item); + } + } + + getItems() { + return this._items; + } + + displayMenu(x: number, y: number) { + this._pageX = x + this._pageY = y + + this._display = "flex" + } + + intersects = (x: number, y: number): boolean => { + if (this.ref.current && this._display !== "none") { + if (x >= this._pageX && x <= this._pageX + this.ref.current.getBoundingClientRect().width) { + if (y >= this._pageY && y <= this._pageY + this.ref.current.getBoundingClientRect().height) { + return true; + } + } + } + return false; + } + + render() { + return( +
+ {this._items.map(prop => { + return + })} +
+ ) + } +} \ No newline at end of file diff --git a/src/views/ContextMenuItem.tsx b/src/views/ContextMenuItem.tsx new file mode 100644 index 000000000..beacb44d2 --- /dev/null +++ b/src/views/ContextMenuItem.tsx @@ -0,0 +1,17 @@ +import React = require("react"); +import { ContextMenu } from "./ContextMenu"; + +export interface ContextMenuProps { + description: string; + event: (e: React.MouseEvent) => void; +} + +export class ContextMenuItem extends React.Component { + render() { + return( +
+
{this.props.description}
+
+ ) + } +} \ No newline at end of file diff --git a/src/views/freeformcanvas/CollectionFreeFormView.tsx b/src/views/freeformcanvas/CollectionFreeFormView.tsx index 4c8fcec10..84b30ac38 100644 --- a/src/views/freeformcanvas/CollectionFreeFormView.tsx +++ b/src/views/freeformcanvas/CollectionFreeFormView.tsx @@ -2,7 +2,7 @@ import { observer } from "mobx-react"; import { Key, KeyStore } from "../../fields/Key"; import "./FreeFormCanvas.scss"; import React = require("react"); -import { action } from "mobx"; +import { action, observable } from "mobx"; import { Document } from "../../fields/Document"; import { DocumentViewModel } from "../../viewmodels/DocumentViewModel"; import { DocumentView } from "../nodes/DocumentView"; @@ -11,10 +11,12 @@ import { NumberField } from "../../fields/NumberField"; import { SSL_OP_SINGLE_DH_USE } from "constants"; import { DocumentDecorations } from "../../DocumentDecorations"; import { SelectionManager } from "../../util/SelectionManager"; +import { Documents } from "../../documents/Documents"; +import { ContextMenu } from "../ContextMenu"; interface IProps { fieldKey: Key; - doc: Document; + dvm: DocumentViewModel; isSelected: boolean; } @@ -29,10 +31,14 @@ export class CollectionFreeFormView extends React.Component { @action onPointerDown = (e: React.PointerEvent): void => { - if (!this.props.isSelected) { + if (!this.props.isSelected && !this.props.dvm.IsMainDoc) { return; } + if (this.props.dvm.IsMainDoc) { + SelectionManager.DeselectAll() + } + e.stopPropagation(); if (e.button === 2) { this._isPointerDown = true; @@ -60,14 +66,14 @@ export class CollectionFreeFormView extends React.Component { if (!this._isPointerDown) { return; } - const { doc } = this.props; + const { dvm } = this.props; + const doc = dvm.Doc; let x = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); let y = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); doc.SetFieldValue(KeyStore.PanX, x + e.movementX, NumberField); doc.SetFieldValue(KeyStore.PanY, y + e.movementY, NumberField); - DocumentDecorations.Instance.forceUpdate() } @@ -76,16 +82,75 @@ export class CollectionFreeFormView extends React.Component { e.stopPropagation(); let scaleAmount = 1 - (e.deltaY / 1000); - //this.props.store.Scale *= scaleAmount; + let currScale = this.props.dvm.Doc.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + this.props.dvm.Doc.SetField(KeyStore.Scale, new NumberField(currScale * scaleAmount)); + + const panx: number = this.props.dvm.Doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + const pany: number = this.props.dvm.Doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + let dx = (e.pageX - window.screen.width / 2) * currScale * (scaleAmount - 1) + let dy = (e.pageY - window.screen.height / 2) * currScale * (scaleAmount - 1) + + this.props.dvm.Doc.SetFieldValue(KeyStore.PanX, panx - dx, NumberField); + this.props.dvm.Doc.SetFieldValue(KeyStore.PanY, pany - dy, NumberField); + + DocumentDecorations.Instance.forceUpdate() + } + + onDrop = (e: React.DragEvent): void => { + e.stopPropagation() + e.preventDefault() + let fReader = new FileReader() + let file = e.dataTransfer.items[0].getAsFile(); + let that = this; + const panx: number = this.props.dvm.Doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + const pany: number = this.props.dvm.Doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + let x = e.pageX - panx + let y = e.pageY - pany + + fReader.addEventListener("load", action("drop", (event) => { + if (fReader.result) { + let url = "" + fReader.result; + let doc = Documents.ImageDocument(url, { + x: x, y: y + }) + let docs = that.props.dvm.Doc.GetFieldT(KeyStore.Data, ListField); + if (!docs) { + docs = new ListField(); + that.props.dvm.Doc.SetField(KeyStore.Data, docs) + } + docs.Data.push(doc); + } + }), false) + + if (file) { + fReader.readAsDataURL(file) + } + } + + @action + removeDocument = (doc: Document): void => { + const value: Document[] = this.props.dvm.Doc.GetFieldValue(this.props.fieldKey, ListField, []) + if (value.indexOf(doc) !== -1) { + value.splice(value.indexOf(doc), 1) + + SelectionManager.DeselectAll() + ContextMenu.Instance.clearItems() + } + } + + onDragOver = (e: React.DragEvent): void => { + // console.log(e.dataTransfer) } render() { - const { fieldKey, doc } = this.props; - const value: Document[] = doc.GetFieldValue(fieldKey, ListField, []); - const panx: number = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - const pany: number = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + const { fieldKey, dvm } = this.props; + + const value: Document[] = dvm.Doc.GetFieldValue(fieldKey, ListField, []); + const panx: number = dvm.Doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + const pany: number = dvm.Doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + const currScale: number = dvm.Doc.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + // DocumentDecorations.Instance.forceUpdate() return ( -
{ width: "100%", height: "calc(100% - 4px)", overflow: "hidden" - }}> -
-
+ }} onDrop={this.onDrop} onDragOver={this.onDragOver}> +
+ +
{value.map(doc => { - return (); + return (); })}
diff --git a/src/views/freeformcanvas/FreeFormCanvas.tsx b/src/views/freeformcanvas/FreeFormCanvas.tsx index de5e88fa1..d7dc0ecaa 100644 --- a/src/views/freeformcanvas/FreeFormCanvas.tsx +++ b/src/views/freeformcanvas/FreeFormCanvas.tsx @@ -79,9 +79,9 @@ export class FreeFormCanvas extends React.Component {
e.preventDefault()}>
- {this.props.store.Docs.map(doc => { - return (); - })} + {/* {this.props.store.Docs.map(doc => { + return (); + })} */}
diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx index e37172943..ee6269430 100644 --- a/src/views/nodes/DocumentView.tsx +++ b/src/views/nodes/DocumentView.tsx @@ -1,6 +1,6 @@ import { observer } from "mobx-react"; import React = require("react"); -import { computed, observable } from "mobx"; +import { computed, observable, action } from "mobx"; import { KeyStore, Key } from "../../fields/Key"; import { NumberField } from "../../fields/NumberField"; import { TextField } from "../../fields/TextField"; @@ -12,15 +12,19 @@ import { CollectionFreeFormView } from "../freeformcanvas/CollectionFreeFormView import "./NodeView.scss" import { SelectionManager } from "../../util/SelectionManager"; import { DocumentDecorations } from "../../DocumentDecorations"; +import { ContextMenu } from "../ContextMenu"; +import { Opt } from "../../fields/Field"; const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? interface IProps { dvm: DocumentViewModel; + parent: Opt; } @observer export class DocumentView extends React.Component { private _mainCont = React.createRef(); + private _contextMenuCanOpen = false; get mainCont(): React.RefObject { return this._mainCont @@ -91,8 +95,10 @@ export class DocumentView extends React.Component { onPointerDown = (e: React.PointerEvent): void => { e.stopPropagation(); + if (e.button === 2) { this._isPointerDown = true; + this._contextMenuCanOpen = true; document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); @@ -120,6 +126,7 @@ export class DocumentView extends React.Component { if (!this._isPointerDown) { return; } + this._contextMenuCanOpen = false this.x += e.movementX; this.y += e.movementY; DocumentDecorations.Instance.opacity = 0 @@ -132,10 +139,39 @@ export class DocumentView extends React.Component { } } + onClick = (e: React.MouseEvent): void => { } + + deleteClicked = (e: React.MouseEvent): void => { + if (this.props.parent) { + this.props.parent.removeDocument(this.props.dvm.Doc) + } + } + + @action + onContextMenu = (e: React.MouseEvent): void => { + e.preventDefault() + + if (!this._contextMenuCanOpen) { + return; + } + + if (this.props.dvm.IsMainDoc) { + ContextMenu.Instance.clearItems() + } + else { + // DocumentViews should stop propogation of this event + e.stopPropagation(); + + ContextMenu.Instance.clearItems(); + ContextMenu.Instance.addItem({description: "Delete", event: this.deleteClicked}) + ContextMenu.Instance.displayMenu(e.pageX, e.pageY) + } + } + render() { let doc = this.props.dvm.Doc; let bindings: any = { - doc: doc, + dvm: this.props.dvm, isSelected: this.selected }; for (const key of this.layoutKeys) { @@ -154,11 +190,9 @@ export class DocumentView extends React.Component { width: this.width, height: this.height, }} - onContextMenu={ - (e) => { - e.preventDefault() - }} - onPointerDown={this.onPointerDown}> + onContextMenu={this.onContextMenu} + onPointerDown={this.onPointerDown} + onClick={this.onClick}> { private _ref: React.RefObject; private _editorView: Opt; @@ -112,6 +113,6 @@ export class FieldTextBox extends React.Component { } render() { - return (
) + return (
) } } \ No newline at end of file -- cgit v1.2.3-70-g09d2 From f98e634ae7070cd841bc523514d147195308696c Mon Sep 17 00:00:00 2001 From: bob Date: Fri, 25 Jan 2019 18:34:28 -0500 Subject: got rid of documentviewmodel. fixed panning/zooming. --- src/Main.tsx | 11 +- src/documents/Documents.ts | 10 +- src/fields/Document.ts | 3 +- src/viewmodels/DocumentViewModel.ts | 10 -- .../freeformcanvas/CollectionFreeFormView.tsx | 150 +++++++++++++-------- src/views/freeformcanvas/FreeFormCanvas.scss | 15 --- src/views/freeformcanvas/FreeFormCanvas.tsx | 90 ------------- src/views/nodes/DocumentView.tsx | 118 +++++++++------- 8 files changed, 176 insertions(+), 231 deletions(-) delete mode 100644 src/views/freeformcanvas/FreeFormCanvas.scss delete mode 100644 src/views/freeformcanvas/FreeFormCanvas.tsx (limited to 'src') diff --git a/src/Main.tsx b/src/Main.tsx index cb91c33a3..c2275b6a7 100644 --- a/src/Main.tsx +++ b/src/Main.tsx @@ -5,7 +5,6 @@ import "normalize.css" import { NodeCollectionStore } from './stores/NodeCollectionStore'; import { StaticTextNodeStore } from './stores/StaticTextNodeStore'; import { VideoNodeStore } from './stores/VideoNodeStore'; -import { FreeFormCanvas } from './views/freeformcanvas/FreeFormCanvas'; import { Key, KeyStore as KS, KeyStore } from './fields/Key'; import { NumberField } from './fields/NumberField'; import { Document } from './fields/Document'; @@ -27,8 +26,6 @@ const mainNodeCollection = new Array(); let mainContainer = Documents.CollectionDocument(mainNodeCollection, { x: 0, y: 0, width: window.screen.width, height: window.screen.height }) -let mainContvm = new DocumentViewModel(mainContainer); -mainContvm.IsMainDoc = true; window.addEventListener("drop", function(e) { e.preventDefault(); @@ -43,9 +40,9 @@ document.addEventListener("pointerdown", action(function(e: PointerEvent) { }), true) ReactDOM.render(( -
+

Dash Web

- +
), document.getElementById('root')); @@ -75,10 +72,10 @@ runInAction(() => { }); let docset = new Array(doc1, doc2); let doc4 = Documents.CollectionDocument(docset, { - x: 100, y: 400 + x: 0, y: 400 }); let doc5 = Documents.ImageDocument("https://static.boredpanda.com/blog/wp-content/uploads/2018/04/5acb63d83493f__700-png.jpg", { - x: 650, y: 500 + x: 1280, y: 500 }); let mainNodes = mainContainer.GetFieldT(KeyStore.Data, ListField); if (!mainNodes) { diff --git a/src/documents/Documents.ts b/src/documents/Documents.ts index 75cc3b491..5fee7343b 100644 --- a/src/documents/Documents.ts +++ b/src/documents/Documents.ts @@ -25,6 +25,9 @@ export namespace Documents { if(options.height) { doc.SetFieldValue(KeyStore.Height, options.height, NumberField); } + doc.SetFieldValue(KeyStore.Scale, 1, NumberField); + doc.SetFieldValue(KeyStore.PanX, 0, NumberField); + doc.SetFieldValue(KeyStore.PanY, 0, NumberField); } let textProto:Document; @@ -35,7 +38,7 @@ export namespace Documents { textProto.SetField(KeyStore.Y, new NumberField(0)); textProto.SetField(KeyStore.Width, new NumberField(300)); textProto.SetField(KeyStore.Height, new NumberField(150)); - textProto.SetField(KeyStore.Layout, new TextField("")); + textProto.SetField(KeyStore.Layout, new TextField("")); textProto.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); } return textProto; @@ -75,9 +78,12 @@ export namespace Documents { collectionProto = new Document(); collectionProto.SetField(KeyStore.X, new NumberField(0)); collectionProto.SetField(KeyStore.Y, new NumberField(0)); + collectionProto.SetField(KeyStore.Scale, new NumberField(1)); + collectionProto.SetField(KeyStore.PanX, new NumberField(0)); + collectionProto.SetField(KeyStore.PanY, new NumberField(0)); collectionProto.SetField(KeyStore.Width, new NumberField(300)); collectionProto.SetField(KeyStore.Height, new NumberField(300)); - collectionProto.SetField(KeyStore.Layout, new TextField('')); + collectionProto.SetField(KeyStore.Layout, new TextField('')); collectionProto.SetField(KeyStore.LayoutKeys, new ListField([KeyStore.Data])); } return collectionProto; diff --git a/src/fields/Document.ts b/src/fields/Document.ts index 0bba9c21e..6b1cccaf9 100644 --- a/src/fields/Document.ts +++ b/src/fields/Document.ts @@ -31,7 +31,8 @@ export class Document extends Field { GetFieldValue(key: Key, ctor: { new(): U }, defaultVal: T): T { let val = this.GetField(key); - return (val && val instanceof ctor) ? val.Data : defaultVal; + let vval = (val && val instanceof ctor) ? val.Data : defaultVal; + return vval; } SetField(key: Key, field: Opt): void { diff --git a/src/viewmodels/DocumentViewModel.ts b/src/viewmodels/DocumentViewModel.ts index 21e88f964..008275f3c 100644 --- a/src/viewmodels/DocumentViewModel.ts +++ b/src/viewmodels/DocumentViewModel.ts @@ -8,14 +8,4 @@ export class DocumentViewModel { get Doc(): Document { return this.doc; } - - private _isMainDoc = false - - get IsMainDoc(): boolean { - return this._isMainDoc; - } - - set IsMainDoc(v: boolean) { - this._isMainDoc = v; - } } \ No newline at end of file diff --git a/src/views/freeformcanvas/CollectionFreeFormView.tsx b/src/views/freeformcanvas/CollectionFreeFormView.tsx index 84b30ac38..383d71d83 100644 --- a/src/views/freeformcanvas/CollectionFreeFormView.tsx +++ b/src/views/freeformcanvas/CollectionFreeFormView.tsx @@ -1,8 +1,7 @@ import { observer } from "mobx-react"; import { Key, KeyStore } from "../../fields/Key"; -import "./FreeFormCanvas.scss"; import React = require("react"); -import { action, observable } from "mobx"; +import { action, observable, computed } from "mobx"; import { Document } from "../../fields/Document"; import { DocumentViewModel } from "../../viewmodels/DocumentViewModel"; import { DocumentView } from "../nodes/DocumentView"; @@ -13,85 +12,123 @@ import { DocumentDecorations } from "../../DocumentDecorations"; import { SelectionManager } from "../../util/SelectionManager"; import { Documents } from "../../documents/Documents"; import { ContextMenu } from "../ContextMenu"; +import { Opt } from "../../fields/Field"; interface IProps { fieldKey: Key; - dvm: DocumentViewModel; - isSelected: boolean; + Document: Document; + ContainingDocumentView: Opt; } @observer export class CollectionFreeFormView extends React.Component { - private _isPointerDown: boolean = false; - constructor(props: IProps) { super(props); } - @action - onPointerDown = (e: React.PointerEvent): void => { - if (!this.props.isSelected && !this.props.dvm.IsMainDoc) { - return; - } - - if (this.props.dvm.IsMainDoc) { - SelectionManager.DeselectAll() - } + @computed + public get active():boolean { + var isSelected = (this.props.ContainingDocumentView != undefined && SelectionManager.IsSelected(this.props.ContainingDocumentView)); + var childSelected = SelectionManager.SelectedDocuments().some(view => view.props.ContainingCollectionView == this ); + var topMost = this.props.ContainingDocumentView != undefined && this.props.ContainingDocumentView.props.ContainingCollectionView == undefined; + return isSelected || childSelected || topMost; + } - e.stopPropagation(); - if (e.button === 2) { - this._isPointerDown = true; + _lastX: number = 0; + _lastY:number = 0; + @action + onPointerDown = (e: React.PointerEvent): void => + { + if (this.active && e.button === 2) { + e.stopPropagation(); + e.preventDefault(); document.removeEventListener("pointermove", this.onPointerMove); document.addEventListener("pointermove", this.onPointerMove); document.removeEventListener("pointerup", this.onPointerUp); document.addEventListener("pointerup", this.onPointerUp); + this._lastX = e.pageX; + this._lastY = e.pageY; } } @action onPointerUp = (e: PointerEvent): void => { + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); e.stopPropagation(); - if (e.button === 2) { - this._isPointerDown = false; - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); + + var topMost = this.props.ContainingDocumentView != undefined && this.props.ContainingDocumentView.props.ContainingCollectionView == undefined; + if (topMost) { + SelectionManager.DeselectAll() } } @action - onPointerMove = (e: PointerEvent): void => { - e.preventDefault(); - e.stopPropagation(); - if (!this._isPointerDown) { - return; + onPointerMove = (e: PointerEvent): void => + { + if (!e.cancelBubble) { + e.preventDefault(); + e.stopPropagation(); + const doc = this.props.Document; + let me = this; + let currScale:number = this.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + if (me.props.ContainingDocumentView!.props.ContainingDocumentView != undefined) { + let pme = me.props.ContainingDocumentView!.props.ContainingDocumentView!.props.Document; + currScale = pme.GetFieldValue(KeyStore.Scale, NumberField, Number(0)); + } + let x = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + let y = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + doc.SetFieldValue(KeyStore.PanX, x + (e.pageX - this._lastX)/currScale, NumberField); + doc.SetFieldValue(KeyStore.PanY, y + (e.pageY - this._lastY)/currScale, NumberField); + this._lastX = e.pageX; + this._lastY = e.pageY; + + DocumentDecorations.Instance.forceUpdate() } - const { dvm } = this.props; - const doc = dvm.Doc; + } - let x = doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - let y = doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); - doc.SetFieldValue(KeyStore.PanX, x + e.movementX, NumberField); - doc.SetFieldValue(KeyStore.PanY, y + e.movementY, NumberField); - DocumentDecorations.Instance.forceUpdate() + private getLocalPoint(me:DocumentView, inputX: number, inputY: number) { + let ContainerX = inputX; + let ContainerY = inputY; + if (me.props.ContainingDocumentView != undefined) { + let pme = me.props.ContainingDocumentView!; + let {LocalX, Ss, W, Panxx, Xx, LocalY, Panyy, Yy} = this.getLocalPoint(pme, ContainerX, ContainerY); + ContainerX = LocalX; + ContainerY = LocalY; + } + + let W = me.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)); + let Xx = me.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0)); + let Yy = me.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0)); + let Ss = me.props.Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + let Panxx = me.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + let Panyy = me.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + let LocalX = W / 2 - (Xx + Panxx) / Ss + (ContainerX - W / 2) / Ss; + let LocalY = -(Yy + Panyy) / Ss + ContainerY / Ss; + + return {LocalX, Ss, W, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY}; } @action - onPointerWheel = (e: React.WheelEvent): void => { + onPointerWheel = (e: React.WheelEvent): void => + { e.stopPropagation(); - let scaleAmount = 1 - (e.deltaY / 1000); - let currScale = this.props.dvm.Doc.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); - this.props.dvm.Doc.SetField(KeyStore.Scale, new NumberField(currScale * scaleAmount)); + let {LocalX, Ss, W, Panxx, Xx, LocalY, Panyy, Yy, ContainerX, ContainerY} = this.getLocalPoint(this.props.ContainingDocumentView!, e.pageX, e.pageY); + + var deltaScale = (1 - (e.deltaY / 1000)) * Ss; - const panx: number = this.props.dvm.Doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - const pany: number = this.props.dvm.Doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); - let dx = (e.pageX - window.screen.width / 2) * currScale * (scaleAmount - 1) - let dy = (e.pageY - window.screen.height / 2) * currScale * (scaleAmount - 1) + var newContainerX = LocalX * deltaScale + W/2-W/2 * deltaScale + Panxx + Xx; + var newContainerY = LocalY * deltaScale + Panyy+ Yy; - this.props.dvm.Doc.SetFieldValue(KeyStore.PanX, panx - dx, NumberField); - this.props.dvm.Doc.SetFieldValue(KeyStore.PanY, pany - dy, NumberField); + let dx = ContainerX - newContainerX; + let dy = ContainerY - newContainerY; + + this.props.Document.SetField(KeyStore.Scale, new NumberField(deltaScale)); + this.props.Document.SetFieldValue(KeyStore.PanX, Panxx+dx, NumberField); + this.props.Document.SetFieldValue(KeyStore.PanY, Panyy+dy, NumberField); DocumentDecorations.Instance.forceUpdate() } @@ -102,8 +139,8 @@ export class CollectionFreeFormView extends React.Component { let fReader = new FileReader() let file = e.dataTransfer.items[0].getAsFile(); let that = this; - const panx: number = this.props.dvm.Doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - const pany: number = this.props.dvm.Doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + const panx: number = this.props.Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + const pany: number = this.props.Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); let x = e.pageX - panx let y = e.pageY - pany @@ -113,10 +150,10 @@ export class CollectionFreeFormView extends React.Component { let doc = Documents.ImageDocument(url, { x: x, y: y }) - let docs = that.props.dvm.Doc.GetFieldT(KeyStore.Data, ListField); + let docs = that.props.Document.GetFieldT(KeyStore.Data, ListField); if (!docs) { docs = new ListField(); - that.props.dvm.Doc.SetField(KeyStore.Data, docs) + that.props.Document.SetField(KeyStore.Data, docs) } docs.Data.push(doc); } @@ -129,7 +166,7 @@ export class CollectionFreeFormView extends React.Component { @action removeDocument = (doc: Document): void => { - const value: Document[] = this.props.dvm.Doc.GetFieldValue(this.props.fieldKey, ListField, []) + const value: Document[] = this.props.Document.GetFieldValue(this.props.fieldKey, ListField, []) if (value.indexOf(doc) !== -1) { value.splice(value.indexOf(doc), 1) @@ -141,14 +178,13 @@ export class CollectionFreeFormView extends React.Component { onDragOver = (e: React.DragEvent): void => { // console.log(e.dataTransfer) } - render() { - const { fieldKey, dvm } = this.props; + const { fieldKey, Document: Document } = this.props; - const value: Document[] = dvm.Doc.GetFieldValue(fieldKey, ListField, []); - const panx: number = dvm.Doc.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); - const pany: number = dvm.Doc.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); - const currScale: number = dvm.Doc.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); + const value: Document[] = Document.GetFieldValue(fieldKey, ListField, []); + const panx: number = Document.GetFieldValue(KeyStore.PanX, NumberField, Number(0)); + const pany: number = Document.GetFieldValue(KeyStore.PanY, NumberField, Number(0)); + const currScale: number = Document.GetFieldValue(KeyStore.Scale, NumberField, Number(1)); // DocumentDecorations.Instance.forceUpdate() return (
{ height: "calc(100% - 4px)", overflow: "hidden" }} onDrop={this.onDrop} onDragOver={this.onDragOver}> -
+
{value.map(doc => { - return (); + return (); })}
diff --git a/src/views/freeformcanvas/FreeFormCanvas.scss b/src/views/freeformcanvas/FreeFormCanvas.scss deleted file mode 100644 index 884ef90e6..000000000 --- a/src/views/freeformcanvas/FreeFormCanvas.scss +++ /dev/null @@ -1,15 +0,0 @@ -.freeformcanvas-container { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - overflow: hidden; - - .freeformcanvas { - position: absolute; - top: 0; - left: 0; - } -} - diff --git a/src/views/freeformcanvas/FreeFormCanvas.tsx b/src/views/freeformcanvas/FreeFormCanvas.tsx deleted file mode 100644 index d7dc0ecaa..000000000 --- a/src/views/freeformcanvas/FreeFormCanvas.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { observer } from "mobx-react"; -import { Key } from "../../fields/Key"; -import { NodeCollectionStore } from "../../stores/NodeCollectionStore"; -import "./FreeFormCanvas.scss"; -import React = require("react"); -import { action } from "mobx"; -import { Document } from "../../fields/Document"; -import {DocumentViewModel} from "../../viewmodels/DocumentViewModel"; -import {DocumentView} from "../nodes/DocumentView"; -import {TextField} from "../../fields/TextField"; -import {ListField} from "../../fields/ListField"; -import {Field} from "../../fields/Field"; -import { SelectionManager } from "../../util/SelectionManager"; - -interface IProps { - store: NodeCollectionStore; -} - -@observer -export class FreeFormCanvas extends React.Component { - - private _isPointerDown: boolean = false; - - constructor(props:IProps) { - super(props); - } - - @action - onPointerDown = (e: React.PointerEvent): void => { - e.stopPropagation(); - if (e.button === 2) { - this._isPointerDown = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } - - SelectionManager.DeselectAll() - } - - @action - onPointerUp = (e: PointerEvent): void => { - e.stopPropagation(); - if (e.button === 2) { - this._isPointerDown = false; - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - } - - // let doc = this.props.store.Docs[0]; - // let dataField = doc.GetFieldT(KeyStore.Data, TextField); - // let data = dataField ? dataField.Data : ""; - // this.props.store.Docs[0].SetFieldValue(KeyStore.Data, data + " hello", TextField); - } - - @action - onPointerMove = (e: PointerEvent): void => { - e.stopPropagation(); - if (!this._isPointerDown) { - return; - } - - this.props.store.X += e.movementX; - this.props.store.Y += e.movementY; - } - - @action - onPointerWheel = (e: React.WheelEvent): void => { - e.stopPropagation(); - - let scaleAmount = 1 - (e.deltaY / 1000); - this.props.store.Scale *= scaleAmount; - } - - render() { - let store = this.props.store; - return ( -
e.preventDefault()}> -
-
- {/* {this.props.store.Docs.map(doc => { - return (); - })} */} -
-
-
- ); - } -} \ No newline at end of file diff --git a/src/views/nodes/DocumentView.tsx b/src/views/nodes/DocumentView.tsx index ee6269430..f7d4aa838 100644 --- a/src/views/nodes/DocumentView.tsx +++ b/src/views/nodes/DocumentView.tsx @@ -7,7 +7,7 @@ import { TextField } from "../../fields/TextField"; import { DocumentViewModel } from "../../viewmodels/DocumentViewModel"; import { ListField } from "../../fields/ListField"; import { FieldTextBox } from "../nodes/FieldTextBox" -import { FreeFormCanvas } from "../freeformcanvas/FreeFormCanvas" +import { Document } from "../../fields/Document"; import { CollectionFreeFormView } from "../freeformcanvas/CollectionFreeFormView" import "./NodeView.scss" import { SelectionManager } from "../../util/SelectionManager"; @@ -17,14 +17,19 @@ import { Opt } from "../../fields/Field"; const JsxParser = require('react-jsx-parser').default;//TODO Why does this need to be imported like this? interface IProps { - dvm: DocumentViewModel; - parent: Opt; + Document: Document; + ContainingCollectionView: Opt; + ContainingDocumentView: Opt } @observer export class DocumentView extends React.Component { private _mainCont = React.createRef(); private _contextMenuCanOpen = false; + private _downX:number = 0; + private _downY:number = 0; + private _lastX:number = 0; + private _lastY:number = 0; get mainCont(): React.RefObject { return this._mainCont @@ -32,20 +37,20 @@ export class DocumentView extends React.Component { @computed get x(): number { - return this.props.dvm.Doc.GetFieldValue(KeyStore.X, NumberField, Number(0)); + return this.props.Document.GetFieldValue(KeyStore.X, NumberField, Number(0)); } @computed get y(): number { - return this.props.dvm.Doc.GetFieldValue(KeyStore.Y, NumberField, Number(0)); + return this.props.Document.GetFieldValue(KeyStore.Y, NumberField, Number(0)); } set x(x: number) { - this.props.dvm.Doc.SetFieldValue(KeyStore.X, x, NumberField) + this.props.Document.SetFieldValue(KeyStore.X, x, NumberField) } set y(y: number) { - this.props.dvm.Doc.SetFieldValue(KeyStore.Y, y, NumberField) + this.props.Document.SetFieldValue(KeyStore.Y, y, NumberField) } @computed @@ -55,35 +60,35 @@ export class DocumentView extends React.Component { @computed get width(): number { - return this.props.dvm.Doc.GetFieldValue(KeyStore.Width, NumberField, Number(0)); + return this.props.Document.GetFieldValue(KeyStore.Width, NumberField, Number(0)); } set width(w: number) { - this.props.dvm.Doc.SetFieldValue(KeyStore.Width, w, NumberField) + this.props.Document.SetFieldValue(KeyStore.Width, w, NumberField) } @computed get height(): number { - return this.props.dvm.Doc.GetFieldValue(KeyStore.Height, NumberField, Number(0)); + return this.props.Document.GetFieldValue(KeyStore.Height, NumberField, Number(0)); } set height(h: number) { - this.props.dvm.Doc.SetFieldValue(KeyStore.Height, h, NumberField) + this.props.Document.SetFieldValue(KeyStore.Height, h, NumberField) } @computed get layout(): string { - return this.props.dvm.Doc.GetFieldValue(KeyStore.Layout, TextField, String("

Error loading layout data

")); + return this.props.Document.GetFieldValue(KeyStore.Layout, TextField, String("

Error loading layout data

")); } @computed get layoutKeys(): Key[] { - return this.props.dvm.Doc.GetFieldValue(KeyStore.LayoutKeys, ListField, new Array()); + return this.props.Document.GetFieldValue(KeyStore.LayoutKeys, ListField, new Array()); } @computed get layoutFields(): Key[] { - return this.props.dvm.Doc.GetFieldValue(KeyStore.LayoutFields, ListField, new Array()); + return this.props.Document.GetFieldValue(KeyStore.LayoutFields, ListField, new Array()); } @computed @@ -91,45 +96,59 @@ export class DocumentView extends React.Component { return SelectionManager.IsSelected(this) } - private _isPointerDown = false; + @computed + get active() : boolean { + return SelectionManager.IsSelected(this) || (this.props.ContainingCollectionView instanceof CollectionFreeFormView && this.props.ContainingCollectionView.active); + } onPointerDown = (e: React.PointerEvent): void => { - e.stopPropagation(); - - if (e.button === 2) { - this._isPointerDown = true; - this._contextMenuCanOpen = true; - document.removeEventListener("pointermove", this.onPointerMove); - document.addEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - document.addEventListener("pointerup", this.onPointerUp); - } - SelectionManager.SelectDoc(this, e.ctrlKey) + this._downX = e.pageX; + this._downY = e.pageY; + this._lastX = e.pageX; + this._lastY = e.pageY; + this._contextMenuCanOpen = e.button == 2; + document.removeEventListener("pointermove", this.onPointerMove); + document.addEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + document.addEventListener("pointerup", this.onPointerUp); } onPointerUp = (e: PointerEvent): void => { - e.stopPropagation(); - if (e.button === 2) { + document.removeEventListener("pointermove", this.onPointerMove); + document.removeEventListener("pointerup", this.onPointerUp); + if (!e.cancelBubble) { + e.stopPropagation(); e.preventDefault(); - this._isPointerDown = false; - document.removeEventListener("pointermove", this.onPointerMove); - document.removeEventListener("pointerup", this.onPointerUp); - console.log(this.x); - console.log(this.y) - DocumentDecorations.Instance.opacity = 1 + DocumentDecorations.Instance.opacity = 1; + if (this._downX == e.pageX && this._downY == e.pageY) { + SelectionManager.SelectDoc(this, e.ctrlKey) + } } } onPointerMove = (e: PointerEvent): void => { - e.stopPropagation(); - e.preventDefault(); - if (!this._isPointerDown) { - return; + if (this.active && !e.cancelBubble) { + e.stopPropagation(); + e.preventDefault(); + this._contextMenuCanOpen = false + let me = this; + var dx = e.pageX - this._lastX; + var dy = e.pageY - this._lastY; + this._lastX = e.pageX; + this._lastY = e.pageY; + let currScale:number = 1; + if (me.props.ContainingDocumentView != undefined) { + let pme = me.props.ContainingDocumentView!.props.Document; + currScale = pme.GetFieldValue(KeyStore.Scale, NumberField, Number(0)); + if (me.props.ContainingDocumentView!.props.ContainingDocumentView != undefined) { + let pme = me.props.ContainingDocumentView!.props.ContainingDocumentView!.props.Document; + currScale *= pme.GetFieldValue(KeyStore.Scale, NumberField, Number(0)); + } + } + this.x += dx/currScale; + this.y += dy/currScale; + DocumentDecorations.Instance.opacity = 0; } - this._contextMenuCanOpen = false - this.x += e.movementX; - this.y += e.movementY; - DocumentDecorations.Instance.opacity = 0 } onDragStart = (e: React.DragEvent): void => { @@ -142,8 +161,8 @@ export class DocumentView extends React.Component { onClick = (e: React.MouseEvent): void => { } deleteClicked = (e: React.MouseEvent): void => { - if (this.props.parent) { - this.props.parent.removeDocument(this.props.dvm.Doc) + if (this.props.ContainingCollectionView instanceof CollectionFreeFormView) { + this.props.ContainingCollectionView.removeDocument(this.props.Document) } } @@ -155,7 +174,8 @@ export class DocumentView extends React.Component { return; } - if (this.props.dvm.IsMainDoc) { + var topMost = this.props.ContainingCollectionView == undefined; + if (topMost) { ContextMenu.Instance.clearItems() } else { @@ -169,10 +189,10 @@ export class DocumentView extends React.Component { } render() { - let doc = this.props.dvm.Doc; + let doc = this.props.Document; let bindings: any = { - dvm: this.props.dvm, - isSelected: this.selected + Document: this.props.Document, + ContainingDocumentView: this }; for (const key of this.layoutKeys) { bindings[key.Name + "Key"] = key; @@ -194,7 +214,7 @@ export class DocumentView extends React.Component { onPointerDown={this.onPointerDown} onClick={this.onClick}> -- cgit v1.2.3-70-g09d2