diff --git a/gui/README.md b/gui/README.md deleted file mode 100644 index 45c410a62..000000000 --- a/gui/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# TensorNetwork GUI - -⚠️ **UNDER CONSTRUCTION** 🏗️ - -A graphical interface for defining tensor networks. Compiles to TensorNetwork Python code. diff --git a/gui/css/index.css b/gui/css/index.css deleted file mode 100644 index 1dcce637d..000000000 --- a/gui/css/index.css +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright 2019 The TensorNetwork Authors -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.app { - display: flex; - flex-direction: row; - font: normal 15px sans-serif; -} - -svg.workspace { - float: left; - background-color: #f9f9f9; -} - -svg.workspace .drag-selector { - stroke: #fff; - stroke-width: 2; - fill: rgba(200, 200, 200, 0.5); -} - -a.export { - position: absolute; -} - -svg text { - user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -webkit-user-select: none; -} - -.toolbar { - width: 300px; - background-color: #fff; - box-shadow: 0 1px 3px rgba(0,0,0,0.1), 0 1px 2px rgba(0,0,0,0.2); -} - -section { - padding: 10px 20px; - border-bottom: 1px solid #ddd; -} - -.tensor-creator .svg-container { - height: 200px; -} - -.delete { - text-align: right; - float: right; - color: darkred; -} - -.button-holder { - padding: 20px 0; -} - -.code-output { - position: absolute; - top: 600px; - width: 900px; - padding: 10px; -} - -label { - padding: 10px; -} \ No newline at end of file diff --git a/gui/index.html b/gui/index.html deleted file mode 100644 index f235bcc6a..000000000 --- a/gui/index.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - TensorNetwork GUI - - - - -
- - - - - - - - - - - - - - diff --git a/gui/js/app.js b/gui/js/app.js deleted file mode 100644 index 71c8dc85b..000000000 --- a/gui/js/app.js +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2019 The TensorNetwork Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -let app = new Vue({ - el: '#app', - data: { - state: initialState // now state object is reactive, whereas initialState is not - }, - methods: { - exportSVG: function(event) { - event.preventDefault(); - let serializer = new XMLSerializer(); - let workspace = document.getElementById('workspace'); - let blob = new Blob([serializer.serializeToString(workspace)], {type:"image/svg+xml;charset=utf-8"}); - let url = URL.createObjectURL(blob); - let link = document.createElement('a'); - link.href = url; - link.download = "export.svg"; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - } - }, - template: ` -
-
- - Export SVG - -
- -
- - ` -}); diff --git a/gui/js/edge.js b/gui/js/edge.js deleted file mode 100644 index 1e41f6189..000000000 --- a/gui/js/edge.js +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2019 The TensorNetwork Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -Vue.component( - 'edge', - { - mixins: [mixinGet, mixinGeometry], - props: { - edge: Array, - state: Object - }, - computed: { - node1: function() { - return this.getNode(this.edge[0][0]); - }, - node2: function() { - return this.getNode(this.edge[1][0]); - }, - angle1: function() { - return this.node1.axes[this.edge[0][1]].angle; - }, - angle2: function() { - return this.node2.axes[this.edge[1][1]].angle; - }, - x1: function() { - return this.node1.position.x + this.getAxisPoints(this.node1.axes[this.edge[0][1]].position, this.angle1, this.node1.rotation).x2; - }, - y1: function() { - return this.node1.position.y + this.getAxisPoints(this.node1.axes[this.edge[0][1]].position, this.angle1, this.node1.rotation).y2; - }, - x2: function() { - return this.node2.position.x + this.getAxisPoints(this.node2.axes[this.edge[1][1]].position, this.angle2, this.node2.rotation).x2; - }, - y2: function() { - return this.node2.position.y + this.getAxisPoints(this.node2.axes[this.edge[1][1]].position, this.angle2, this.node2.rotation).y2; - } - }, - template: ` - - - - {{edge[2]}} - - - ` - } -); - -Vue.component( - 'proto-edge', - { - mixins: [mixinGeometry], - props: { - x: Number, - y: Number, - node: Object, - axis: Number, - }, - computed: { - angle: function() { - return this.node.axes[this.axis].angle; - }, - x0: function() { - return this.node.position.x + this.getAxisPoints(this.node.axes[this.axis].position, this.angle, this.node.rotation).x2; - }, - y0: function() { - return this.node.position.y + this.getAxisPoints(this.node.axes[this.axis].position, this.angle, this.node.rotation).y2; - } - }, - template: ` - - ` - } -); diff --git a/gui/js/initialState.js b/gui/js/initialState.js deleted file mode 100644 index 1bca1533b..000000000 --- a/gui/js/initialState.js +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 The TensorNetwork Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -let initialState = { - renderLaTeX: true, - selectedNodes: [], - draggingNode: false, - nodes: [ - { - name: 't1', - displayName: 't_1', - size: [1, 1], - axes: [ - {name: null, angle: 0, position: [0, 0]}, - {name: null, angle: Math.PI / 2, position: [0, 0]}, - {name: null, angle: Math.PI, position: [0, 0]}, - ], - position: {x: 200, y: 300}, - rotation: 0, - hue: 30 - }, - { - name: 't2', - displayName: 't_2', - size: [1, 1], - axes: [ - {name: null, angle: 0, position: [0, 0]}, - {name: null, angle: Math.PI / 2, position: [0, 0]}, - {name: null, angle: Math.PI, position: [0, 0]}, - ], - position: {x: 367, y: 300}, - rotation: 0, - hue: 30 - }, - { - name: 't3', - displayName: 't_3', - size: [1, 1], - axes: [ - {name: null, angle: 0, position: [0, 0]}, - {name: null, angle: Math.PI / 2, position: [0, 0]}, - {name: null, angle: Math.PI, position: [0, 0]}, - ], - position: {x: 533, y: 300}, - rotation: 0, - hue: 30 - }, - { - name: 't4', - displayName: 't_4', - size: [1, 1], - axes: [ - {name: null, angle: 0, position: [0, 0]}, - {name: null, angle: Math.PI / 2, position: [0, 0]}, - {name: null, angle: Math.PI, position: [0, 0]}, - ], - position: {x: 700, y: 300}, - rotation: 0, - hue: 30 - } - ], - edges: [ - [['t1', 0], ['t2', 2], null], - [['t2', 0], ['t3', 2], null], - [['t3', 0], ['t4', 2], null], - ] -}; diff --git a/gui/js/mixins.js b/gui/js/mixins.js deleted file mode 100644 index 8bf36ecd0..000000000 --- a/gui/js/mixins.js +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2019 The TensorNetwork Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -let mixinGet = { - methods: { - getNeighborsOf: function(name) { - let neighbors = []; - let edges = this.state.edges; - for (let i = 0; i < edges.length; i++) { - let edge = edges[i]; - if (edge[0][0] === name) { - neighbors.push({ - axis: edge[0][1], - neighbor: edge[1], - edgeName: edge[2] - }); - } - if (edge[1][0] === name) { - neighbors.push({ - axis: edge[1][1], - neighbor: edge[0], - edgeName: edge[2] - }); - } - } - return neighbors; - }, - getNode: function(name) { - for (let i = 0; i < this.state.nodes.length; i++) { - if (this.state.nodes[i].name === name) { - return this.state.nodes[i]; - } - } - return null; - }, - getAxis: function(address) { - let [nodeName, axisIndex] = address; - let node = this.getNode(nodeName); - return node.axes[axisIndex]; - }, - } -}; - -let mixinGeometry = { - data: function() { - return { - axisLength: 50, - baseNodeWidth: 50, - nodeCornerRadius: 10, - axisLabelRadius: 1.2 - } - }, - methods: { - getAxisPoints: function (position, angle, rotation) { - let x0 = position[0] * this.baseNodeWidth; - let y0 = position[1] * this.baseNodeWidth; - let x1 = Math.cos(rotation) * x0 - Math.sin(rotation) * y0; - let y1 = Math.sin(rotation) * x0 + Math.cos(rotation) * y0; - let x2 = x1 + this.axisLength * Math.cos(angle + rotation); - let y2 = y1 + this.axisLength * Math.sin(angle + rotation); - return { - x1: x1, - y1: y1, - x2: x2, - y2: y2 - } - }, - } -}; \ No newline at end of file diff --git a/gui/js/node.js b/gui/js/node.js deleted file mode 100644 index 588eae7a6..000000000 --- a/gui/js/node.js +++ /dev/null @@ -1,344 +0,0 @@ -// Copyright 2019 The TensorNetwork Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -let mixinNode = { - props: { - node: Object, - state: Object, - }, - methods: { - neighborAt: function(axis) { - for (let i = 0; i < this.neighbors.length; i++) { - if (this.neighbors[i].axis === axis) { - return this.neighbors[i].neighbor; - } - } - return null; - }, - edgeNameAt: function(axis) { - for (let i = 0; i < this.neighbors.length; i++) { - if (this.neighbors[i].axis === axis) { - return this.neighbors[i].edgeName; - } - } - return null; - } - }, - computed: { - neighbors: function() { - return this.getNeighborsOf(this.node.name); - } - }, -}; - -Vue.component( - 'node', - { - mixins: [mixinGet, mixinGeometry, mixinNode], - props: { - disableDragging: { - type: Boolean, - default: false - }, - shadow: { - type: Boolean, - default: false - } - }, - data: function() { - return { - mouse: { - x: null, - y: null - }, - render: true, - labelOpacity: 1 - } - }, - mounted: function() { - window.MathJax.typeset(); - }, - watch: { - 'node.displayName': function() { - if (!this.renderLaTeX) { - return; - } - // Ugly race condition to make sure MathJax renders, and old renders are discarded - this.render = false; - this.labelOpacity = 0; - if (this.renderTimeout) { - clearTimeout(this.renderTimeout); - } - let t = this; - this.renderTimeout = setTimeout(function() { - t.render = true; - }, 50); - this.renderTimeout = setTimeout(function() { - window.MathJax.typeset(); - t.labelOpacity = 1; - }, 100); - } - }, - methods: { - onMouseDown: function(event) { - event.stopPropagation(); - if (this.disableDragging) { - return; - } - - if (!this.state.selectedNodes.includes(this.node)) { - if (event.shiftKey) { - this.state.selectedNodes.push(this.node); - } - else { - this.state.selectedNodes = [this.node]; - } - } - else { - if (event.shiftKey) { - let t = this; - this.state.selectedNodes = this.state.selectedNodes.filter(function(node) { - return node !== t.node; - }); - } - } - - document.addEventListener('mousemove', this.onMouseMove); - document.addEventListener('mouseup', this.onMouseUp); - this.state.draggingNode = true; - - this.mouse.x = event.pageX; - this.mouse.y = event.pageY; - }, - onMouseMove: function(event) { - let dx = event.pageX - this.mouse.x; - let dy = event.pageY - this.mouse.y; - this.mouse.x = event.pageX; - this.mouse.y = event.pageY; - this.state.selectedNodes.forEach(function(node) { - node.position.x += dx; - node.position.y += dy; - }); - }, - onMouseUp: function() { - document.removeEventListener('mousemove', this.onMouseMove); - document.removeEventListener('mouseup', this.onMouseUp); - - this.state.draggingNode = false; - - let workspace = document.getElementById('workspace').getBoundingClientRect(); - let t = this; - this.state.selectedNodes.forEach(function(node) { - if (node.position.x < t.baseNodeWidth / 2) { - node.position.x = t.baseNodeWidth / 2; - } - if (node.position.y < t.baseNodeWidth / 2) { - node.position.y = t.baseNodeWidth / 2; - } - if (node.position.x > workspace.width - t.baseNodeWidth / 2) { - node.position.x = workspace.width - t.baseNodeWidth / 2; - } - if (node.position.y > workspace.height - t.baseNodeWidth / 2) { - node.position.y = workspace.height - t.baseNodeWidth / 2; - } - }); - }, - onAxisMouseDown: function(axis) { - this.$emit('axismousedown', axis); - }, - onAxisMouseUp: function(axis) { - this.$emit('axismouseup', axis); - } - }, - computed: { - nodeWidth: function() { - return this.baseNodeWidth * Math.min(this.node.size[0], 3); - }, - nodeHeight: function() { - return this.baseNodeWidth * Math.min(this.node.size[1], 3); - }, - translation: function() { - return 'translate(' + this.node.position.x + ' ' + this.node.position.y + ')'; - }, - rotation: function() { - return 'rotate(' + (this.node.rotation * 180 / Math.PI) + ')'; - }, - brightness: function() { - if (this.state.selectedNodes.includes(this.node)) { - return 50; - } - else { - return 80; - } - }, - style: function() { - if (this.shadow) { - return 'fill: #ddd'; - } - else { - return 'fill: hsl(' + this.node.hue + ', 80%, ' + this.brightness + '%);'; - } - }, - renderLaTeX: function() { - return this.state.renderLaTeX && window.MathJax; - }, - label: function() { - return '\\(\\displaystyle{' + this.node.displayName + '}\\)'; - }, - labelStyle: function() { - return 'opacity: ' + this.labelOpacity + ';'; - } - }, - created: function() { - if (this.node.hue == null) { - this.node.hue = Math.random() * 360; - } - }, - template: ` - - - - - {{node.name}} - - -
- {{label}} -
-
-
- ` - } -); - -Vue.component( - 'axis', - { - mixins: [mixinGet, mixinGeometry, mixinNode], - props: { - node: Object, - index: Number, - state: Object, - shadow: { - type: Boolean, - default: false - }, - }, - data: function() { - return { - dragging: false, - highlighted: false - } - }, - methods: { - onMouseDown: function(event) { - event.stopPropagation(); - this.$emit('axismousedown'); - this.dragging = true; - document.addEventListener('mouseup', this.onDragEnd); - }, - onMouseUp: function() { - this.$emit('axismouseup'); - }, - onDragEnd: function() { - this.dragging = false; - document.removeEventListener('mouseup', this.onDragEnd); - }, - onMouseEnter: function() { - if (this.state.draggingNode) { - return; - } - if (this.neighborAt(this.index) != null) { - return; // don't highlight an axis that is occupied - } - if (this.dragging) { - return; // don't highlight self if self is being dragged - } - this.highlighted = true; - }, - onMouseLeave: function() { - this.highlighted = false; - }, - }, - computed: { - axisPoints: function() { - return this.getAxisPoints(this.node.axes[this.index].position, this.node.axes[this.index].angle, - this.node.rotation) - }, - x1: function() { - return this.axisPoints.x1; - }, - y1: function() { - return this.axisPoints.y1; - }, - x2: function() { - return this.axisPoints.x2; - }, - y2: function() { - return this.axisPoints.y2; - }, - brightness: function() { - return this.highlighted ? 50 : 80; - }, - stroke: function() { - if (this.shadow) { - return this.highlighted ? '#bbb' : '#ddd'; - } - else { - return 'hsl(' + this.node.hue + ', 80%, ' + this.brightness + '%)'; - } - }, - }, - template: ` - - - - {{index}} - - {{node.axes[index].name}} - - - ` - } -); - -Vue.component( - 'node-description', - { - mixins: [mixinGet, mixinNode], - template: ` -

Node {{node.name}} has {{node.axes.length}} axes: -

-

- ` - } -); diff --git a/gui/js/output.js b/gui/js/output.js deleted file mode 100644 index 6347db6d1..000000000 --- a/gui/js/output.js +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2019 The TensorNetwork Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -Vue.component( - 'code-output', - { - props: { - state: Object - }, - computed: { - outputCode: function() { - let code = `import numpy as np\nimport tensornetwork as tn\n`; - - code += `\n# Node definitions\n`; - code += `# TODO: replace np.zeros with actual values\n\n`; - - for (let i = 0; i < this.state.nodes.length; i++) { - let node = this.state.nodes[i]; - let values = this.placeholderValues(node); - let axes = this.axisNames(node); - code += `${node.name} = tn.Node(${values}, name="${node.name}"${axes})\n`; - } - - code += `\n# Edge definitions\n\n`; - - for (let i = 0; i < this.state.edges.length; i++) { - let edge = this.state.edges[i]; - let name = this.edgeName(edge); - code += `tn.connect(${edge[0][0]}[${edge[0][1]}], ${edge[1][0]}[${edge[1][1]}]${name})\n`; - } - - return code; - } - }, - methods: { - placeholderValues: function(node) { - let code = `np.zeros((`; - for (let i = 0; i < node.axes.length; i++) { - code += `0, `; - } - code += `))`; - return code; - }, - axisNames: function(node) { - let code = `, axis_names=[`; - let willOutput = false; - for (let i = 0; i < node.axes.length; i++) { - let axis = node.axes[i].name; - if (axis) { - willOutput = true; - code += `"${axis}", ` - } - else { - code += `None, ` - } - } - code += `]`; - return willOutput ? code : ``; - }, - edgeName: function(edge) { - let name = edge[2]; - return name ? `, name="${name}"` : ``; - } - }, - template: ` -
-

TensorNetwork Output

-
{{outputCode}}
-
- ` - } -); - diff --git a/gui/js/toolbar.js b/gui/js/toolbar.js deleted file mode 100644 index 823ffe150..000000000 --- a/gui/js/toolbar.js +++ /dev/null @@ -1,519 +0,0 @@ -// Copyright 2019 The TensorNetwork Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -Vue.component( - 'toolbar', - { - props: { - state: Object - }, - data: function() { - return { - copyNodeName: '', - } - }, - methods: { - deselectNode: function() { - this.state.selectedNodes = []; - }, - deleteNode: function(event) { - event.preventDefault(); - let selectedName = this.state.selectedNodes[0].name; - - this.state.edges = this.state.edges.filter(function(edge) { - if (edge[0][0] === selectedName || edge[1][0] === selectedName) { - return false; - } - else { - return true; - } - }); - this.state.nodes = this.state.nodes.filter(function(node) { - return node.name !== selectedName; - }); - this.selectedNodes = []; - }, - copyNode: function(event) { - event.preventDefault(); - let workspace = document.getElementById('workspace').getBoundingClientRect(); - - let node = JSON.parse(JSON.stringify(this.node)); - node.name = this.copyNodeName; - node.position = {x: workspace.width / 2, y: workspace.height / 2}; - - this.state.nodes.push(node); - this.state.selectedNodes = [node]; - this.copyNodeName = ''; - }, - rotate: function(angle) { - this.node.rotation += angle; - } - }, - computed: { - node: function() { - return this.state.selectedNodes[0]; - }, - copyNodeDisabled: function() { - return this.nameTaken || this.copyNodeName == null || this.copyNodeName === ''; - }, - nameTaken: function() { - for (let i = 0; i < this.state.nodes.length; i++) { - if (this.copyNodeName === this.state.nodes[i].name) { - return true; - } - } - return false; - } - }, - template: ` -
-
- -
-

Selecting nodes

-

Click a node to select it for editing.

-

Drag-select or shift-click multiple nodes to drag as a group and adjust alignment and - spacing.

-
-
-
-
-
- -
-
-
-
- delete -

Node: {{node.name}}

-
-

Set LaTeX Label

- -

Copy Node

-
- - -
-

Rotate

- - -
- - -
-
- -
-
- ` - } -); - -Vue.component( - 'tensor-creator', - { - mixins: [mixinGeometry], - props: { - state: Object - }, - data: function() { - return { - size1: 1, - size2: 1, - hue: 0, - node: {}, - width: 250, - height: 250, - dragSelector: { - dragging: false, - startX: null, - startY: null, - endX: null, - endY: null - }, - }; - }, - created: function() { - this.reset(); - }, - watch: { - size1: function() { - this.reset(); - }, - size2: function() { - this.reset(); - }, - hue: function() { - this.node.hue = parseFloat(this.hue); - } - }, - methods: { - reset: function () { - this.node = JSON.parse(JSON.stringify(this.nodeInitial)); - }, - createNode: function (event) { - event.preventDefault(); - let workspace = document.getElementById('workspace').getBoundingClientRect(); - - this.node.position = {x: workspace.width / 2, y: workspace.height / 2}; - - this.state.nodes.push(this.node); - this.reset(); - }, - onShadowAxisMouseDown: function (node, axis) { - let candidateAxis = this.nodeShadow.axes[axis]; - for (let j = 0; j < this.node.axes.length; j++) { - let existingAxis = this.node.axes[j]; - if (candidateAxis.angle === existingAxis.angle - && candidateAxis.position[0] === existingAxis.position[0] - && candidateAxis.position[1] === existingAxis.position[1]) { - return; - } - } - this.node.axes.push(JSON.parse(JSON.stringify(candidateAxis))); - }, - onNodeAxisMouseDown: function (node, axis) { - this.node.axes.splice(axis, 1); - }, - axes: function (size1, size2) { - let makeAxis = function (direction, position) { - return {name: null, angle: direction * Math.PI / 4, position: position}; - }; - let output = []; - - let x = function(n) { - let x_end = Math.min((size1 - 1) / 2, 1); - return size1 !== 1 ? (-x_end * (size1 - 1 - n) + x_end * n) / (size1 - 1) : 0; // Avoid div by 0 - }; - let y = function(m) { - let y_end = Math.min((size2 - 1) / 2, 1); - return size2 !== 1 ? (-y_end * (size2 - 1 - m) + y_end * m) / (size2 - 1) : 0; - }; - - let n = 0; - let m = 0; - output.push(makeAxis(5, [x(n), y(m)])); - - for (n = 0; n < size1; n++) { - output.push(makeAxis(6, [x(n), y(m)])); - } - n = size1 - 1; - - output.push(makeAxis(7, [x(n), y(m)])); - - for (m = 0; m < size2; m++) { - output.push(makeAxis(0, [x(n), y(m)])); - } - m = size2 - 1; - - output.push(makeAxis(1, [x(n), y(m)])); - - for (n = size1 - 1; n >= 0; n--) { - output.push(makeAxis(2, [x(n), y(m)])) - } - n = 0; - - output.push(makeAxis(3, [x(n), y(m)])); - - for (m = size2 - 1; m >= 0; m--) { - output.push(makeAxis(4, [x(n), y(m)])); - } - - return output; - }, - onMouseDown: function (event) { - document.addEventListener('mousemove', this.onMouseMove); - document.addEventListener('mouseup', this.onMouseUp); - - let workspace = document.getElementById('tensor-creator-workspace').getBoundingClientRect(); - - this.dragSelector.dragging = true; - this.dragSelector.startX = event.pageX - workspace.left; - this.dragSelector.startY = event.pageY - workspace.top; - this.dragSelector.endX = event.pageX - workspace.left; - this.dragSelector.endY = event.pageY - workspace.top; - }, - onMouseMove: function (event) { - let workspace = document.getElementById('tensor-creator-workspace').getBoundingClientRect(); - - this.dragSelector.endX = event.pageX - workspace.left; - this.dragSelector.endY = event.pageY - workspace.top; - }, - onMouseUp: function () { - document.removeEventListener('mousemove', this.onMouseMove); - document.removeEventListener('mouseup', this.onMouseUp); - - this.dragSelector.dragging = false; - - let x1 = this.dragSelector.startX; - let x2 = this.dragSelector.endX; - let y1 = this.dragSelector.startY; - let y2 = this.dragSelector.endY; - - for (let i = 0; i < this.nodeShadow.axes.length; i++) { - let axis = this.nodeShadow.axes[i]; - let duplicate = false; - for (let j = 0; j < this.node.axes.length; j++) { - let existingAxis = this.node.axes[j]; - if (axis.angle === existingAxis.angle && axis.position[0] === existingAxis.position[0] - && axis.position[1] === existingAxis.position[1]) { - duplicate = true; - break - } - } - if (duplicate) { - continue; - } - let axisPoints = this.getAxisPoints(axis.position, axis.angle, 0); - let axisX = this.nodeShadow.position.x + axisPoints.x2; - let axisY = this.nodeShadow.position.y + axisPoints.y2; - if ((x1 <= axisX && axisX <= x2) || (x2 <= axisX && axisX <= x1)) { - if ((y1 <= axisY && axisY <= y2) || (y2 <= axisY && axisY <= y1)) { - this.node.axes.push(JSON.parse(JSON.stringify(axis))); - } - } - } - } - }, - computed: { - createNodeDisabled: function() { - return this.nameTaken || this.node.name == null || this.node.name === ''; - }, - nameTaken: function() { - for (let i = 0; i < this.state.nodes.length; i++) { - if (this.node.name === this.state.nodes[i].name) { - return true; - } - } - return false; - }, - nodeInitial: function() { - return { - name: "", - size: [parseFloat(this.size1), parseFloat(this.size2)], - axes: [], - position: {x: 125, y: 125}, - rotation: 0, - hue: parseFloat(this.hue) - }; - }, - nodeShadow: function() { - return { - name: "", - size: [parseFloat(this.size1), parseFloat(this.size2)], - axes: this.axes(parseFloat(this.size1), parseFloat(this.size2)), - position: {x: 125, y: 125}, - rotation: 0, - hue: null - }; - }, - renderLaTeX: function() { - return this.state.renderLaTeX && window.MathJax; - - } - }, - template: ` -
-

Create New Node

-

Click on an axis to add or remove it.

-
- - - - - -
- - - - - - - -
- - -
-
-
- - - -
-
-
- - ` - } -); - -Vue.component( - 'toolbar-edge-section', - { - props: { - state: Object - }, - methods: { - deleteEdge: function(event, edge) { - event.preventDefault(); - this.state.edges = this.state.edges.filter(function(candidate) { - return candidate !== edge; - }); - } - }, - computed: { - node: function() { - return this.state.selectedNodes[0]; - } - }, - template: ` -
-

Edges

-
-
-
- delete -

{{edge[0][0]}}[{{edge[0][1]}}] to {{edge[1][0]}}[{{edge[1][1]}}]

-
- - -
-
-
- ` - } -); - -Vue.component( - 'toolbar-axis-section', - { - props: { - state: Object - }, - computed: { - node: function() { - return this.state.selectedNodes[0]; - } - }, - template: ` -
-

Axes

-
-
-

{{node.name}}[{{index}}]

-
- - -
-
- ` - } -); - -Vue.component( - 'toolbar-multinode-section', - { - props: { - state: Object - }, - data: function() { - return { - alignmentY: null, - alignmentX: null, - spacingY: null, - spacingX: null - } - }, - created: function() { - this.alignmentY = this.state.selectedNodes[0].position.y; - this.alignmentX = this.state.selectedNodes[0].position.x; - this.spacingY = this.state.selectedNodes[1].position.y - this.state.selectedNodes[0].position.y; - this.spacingX = this.state.selectedNodes[1].position.x - this.state.selectedNodes[0].position.x; - }, - methods: { - alignVertically: function(event) { - event.preventDefault(); - for (let i = 0; i < this.state.selectedNodes.length; i++) { - this.state.selectedNodes[i].position.y = parseFloat(this.alignmentY); - } - }, - alignHorizontally: function(event) { - event.preventDefault(); - for (let i = 0; i < this.state.selectedNodes.length; i++) { - this.state.selectedNodes[i].position.x = parseFloat(this.alignmentX); - } - }, - spaceVertically: function(event) { - event.preventDefault(); - let baseline = this.state.selectedNodes[0].position.y; - for (let i = 1; i < this.state.selectedNodes.length; i++) { - this.state.selectedNodes[i].position.y = baseline + i * parseFloat(this.spacingY); - } - }, - spaceHorizontally: function(event) { - event.preventDefault(); - let baseline = this.state.selectedNodes[0].position.x; - for (let i = 1; i < this.state.selectedNodes.length; i++) { - this.state.selectedNodes[i].position.x = baseline + i * parseFloat(this.spacingX); - } - }, - disabledFor: function(length) { - return length == null || length == "" || isNaN(parseFloat(length)); - } - }, - template: ` -
-
-

Multiple Nodes

-
-

{{node.name}} - x: {{node.position.x}}, y: {{node.position.y}}

-
- Shift-click a node in the workspace to deselect it. -
-
-

Align Vertically

-
- - -
-
-
-

Align Horizontally

-
- - -
-
-
-

Space Vertically

-
- - -
-
-
-

Space Horizontally

-
- - -
-
-
- ` - } -); diff --git a/gui/js/workspace.js b/gui/js/workspace.js deleted file mode 100644 index dea17bbca..000000000 --- a/gui/js/workspace.js +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2019 The TensorNetwork Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -Vue.component( - 'workspace', - { - props: { - state: Object - }, - data: function() { - return { - width: 900, - height: 600, - dragSelector: { - dragging: false, - startX: null, - startY: null, - endX: null, - endY: null - }, - protoEdge: { - x: null, - y: null, - node: null, - axis: null, - dragging: false - } - }; - }, - methods: { - onMouseDown: function(event) { - this.state.selectedNodes = []; - - document.addEventListener('mousemove', this.onMouseMove); - document.addEventListener('mouseup', this.onMouseUp); - - let workspace = document.getElementById('workspace').getBoundingClientRect(); - - this.dragSelector.dragging = true; - this.dragSelector.startX = event.pageX - workspace.left; - this.dragSelector.startY = event.pageY - workspace.top; - this.dragSelector.endX = event.pageX - workspace.left; - this.dragSelector.endY = event.pageY - workspace.top; - }, - onMouseMove: function(event) { - let workspace = document.getElementById('workspace').getBoundingClientRect(); - - this.dragSelector.endX = event.pageX - workspace.left; - this.dragSelector.endY = event.pageY - workspace.top; - }, - onMouseUp: function() { - document.removeEventListener('mousemove', this.onMouseMove); - document.removeEventListener('mouseup', this.onMouseUp); - - this.dragSelector.dragging = false; - - let x1 = this.dragSelector.startX; - let x2 = this.dragSelector.endX; - let y1 = this.dragSelector.startY; - let y2 = this.dragSelector.endY; - - this.state.selectedNodes = []; - let selected = this.state.selectedNodes; - this.state.nodes.forEach(function(node) { - let x = node.position.x; - let y = node.position.y; - if ((x1 <= x && x <= x2) || (x2 <= x && x <= x1)) { - if ((y1 <= y && y <= y2) || (y2 <= y && y <= y1)) { - selected.push(node); - } - } - }); - this.state.selectedNodes.sort(function(node1, node2) { - let distance1 = (node1.position.x - x1) ** 2 + (node1.position.y - y1) ** 2; - let distance2 = (node2.position.x - x1) ** 2 + (node2.position.y - y1) ** 2; - return distance1 - distance2; - }) - }, - onAxisMouseDown: function(node, axis) { - if (this.axisOccupied(node, axis)) { - return; - } - document.addEventListener('mousemove', this.dragAxis); - document.addEventListener('mouseup', this.releaseAxisDrag); - this.protoEdge.node = node; - this.protoEdge.axis = axis; - }, - dragAxis: function(event) { - let workspace = document.getElementById('workspace').getBoundingClientRect(); - this.protoEdge.dragging = true; - this.protoEdge.x = event.clientX - workspace.left; - this.protoEdge.y = event.clientY - workspace.top; - }, - releaseAxisDrag: function() { - document.removeEventListener('mousemove', this.dragAxis); - document.removeEventListener('mouseup', this.releaseAxisDrag); - this.protoEdge.dragging = false; - this.protoEdge.node = null; - this.protoEdge.axis = null; - }, - onAxisMouseUp: function(node, axis) { - if (this.protoEdge.dragging) { - if (this.axisOccupied(node, axis)) { - return; - } - if (this.protoEdge.node.name === node.name - && this.protoEdge.axis === axis) { - return; // don't allow connection of an axis to itself - } - this.state.edges.push([ - [this.protoEdge.node.name, this.protoEdge.axis], - [node.name, axis], - null - ]) - } - }, - axisOccupied: function(node, axis) { - for (let i = 0; i < this.state.edges.length; i++) { - let edge = this.state.edges[i]; - if ((node.name === edge[0][0] && axis === edge[0][1]) - || (node.name === edge[1][0] && axis === edge[1][1])) { - return true; - } - } - return false; - } - }, - template: ` - - - - - - - ` - } -); - -Vue.component( - 'drag-selector', - { - props: { - startX: Number, - startY: Number, - endX: Number, - endY: Number, - }, - computed: { - x: function() { - return Math.min(this.startX, this.endX); - }, - y: function() { - return Math.min(this.startY, this.endY); - }, - width: function() { - return Math.abs(this.startX - this.endX); - }, - height: function() { - return Math.abs(this.startY - this.endY); - } - }, - template: ` - - ` - } -);