From 3f984edddad266b4415f118bf33c3037310a9836 Mon Sep 17 00:00:00 2001 From: halfblood Date: Fri, 13 Oct 2023 21:17:00 +0330 Subject: [PATCH] add meta --- .gitignore | 1 - build.py | 31 -- icon.ico | Bin 0 -> 270398 bytes index.html | 6 +- src/_license.js | 27 -- src/elements/link.js | 170 --------- src/elements/node.js | 76 ---- src/elements/self_link.js | 72 ---- src/elements/start_link.js | 65 ---- src/elements/temporary_link.js | 16 - src/export_as/json.js | 41 --- src/export_as/latex.js | 106 ------ src/export_as/svg.js | 94 ----- src/main/fsm.js | 643 --------------------------------- src/main/math.js | 19 - src/main/save.js | 98 ----- 16 files changed, 5 insertions(+), 1460 deletions(-) delete mode 100644 .gitignore delete mode 100755 build.py create mode 100644 icon.ico delete mode 100644 src/_license.js delete mode 100644 src/elements/link.js delete mode 100644 src/elements/node.js delete mode 100644 src/elements/self_link.js delete mode 100644 src/elements/start_link.js delete mode 100644 src/elements/temporary_link.js delete mode 100644 src/export_as/json.js delete mode 100644 src/export_as/latex.js delete mode 100644 src/export_as/svg.js delete mode 100644 src/main/fsm.js delete mode 100644 src/main/math.js delete mode 100644 src/main/save.js diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 1b3145e..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/www/fsm.js diff --git a/build.py b/build.py deleted file mode 100755 index 204813b..0000000 --- a/build.py +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/python - -import os, time, sys - -def sources(): - path = './src/' - return [os.path.join(base, f) for base, folders, files in os.walk(path) for f in files if f.endswith('.js')] - -def build(): - path = './www/fsm.js' - data = '\n'.join(open(file, 'r').read() for file in sources()) - with open(path, 'w') as f: - f.write(data) - print ('built %s (%u bytes)' % (path, len(data))) - -def stat(): - return [os.stat(file).st_mtime for file in sources()] - -def monitor(): - a = stat() - while True: - time.sleep(0.5) - b = stat() - if a != b: - a = b - build() - -if __name__ == '__main__': - build() - if '--watch' in sys.argv: - monitor() diff --git a/icon.ico b/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..34835693b6e4350012a5c64f82d17901de68786c GIT binary patch literal 270398 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 c&OkT=;S7W`5Y9k21K|vWGZ4AKIny?*IS* literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 3f2f13f..fa7e18f 100755 --- a/index.html +++ b/index.html @@ -1,10 +1,14 @@ - Finite State Machine Designer - by Evan Wallace + FSM Ninja + + + + diff --git a/src/_license.js b/src/_license.js deleted file mode 100644 index 320b1d2..0000000 --- a/src/_license.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - Finite State Machine Designer - License: MIT License (see below) - - Copyright (c) 2023 Evan Wallace, Halfblood - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/src/elements/link.js b/src/elements/link.js deleted file mode 100644 index aebdf20..0000000 --- a/src/elements/link.js +++ /dev/null @@ -1,170 +0,0 @@ -function Link(a, b) { - this.nodeA = a; - this.nodeB = b; - this.text = ''; - this.lineAngleAdjust = 0; // value to add to textAngle when link is straight line - - // make anchor point relative to the locations of nodeA and nodeB - this.parallelPart = 0.5; // percentage from nodeA to nodeB - this.perpendicularPart = 0; // pixels from line between nodeA and nodeB - - this.json_model = {}; -} - -Link.prototype.getJson = function () { - // return json obj based on this.txt and this.output - return {...this.json_model, "name": this.text} -} - -Link.prototype.setJsonModel = function (json) { - if (json.hasOwnProperty('name')) { - this.text = json.name - } - - this.json_model = json -} - - -/** - * @returns {{x: number, y: *}} - */ -Link.prototype.getAnchorPoint = function () { - - // compute distance between two nodes - const dx = this.nodeB.x - this.nodeA.x; - const dy = this.nodeB.y - this.nodeA.y; - const scale = Math.sqrt(dx * dx + dy * dy); - - return { - 'x': this.nodeA.x + dx * this.parallelPart - dy * this.perpendicularPart / scale, - 'y': this.nodeA.y + dy * this.parallelPart + dx * this.perpendicularPart / scale - }; -}; - -Link.prototype.setAnchorPoint = function (x, y) { - const dx = this.nodeB.x - this.nodeA.x; - const dy = this.nodeB.y - this.nodeA.y; - const scale = Math.sqrt(dx * dx + dy * dy); - this.parallelPart = (dx * (x - this.nodeA.x) + dy * (y - this.nodeA.y)) / (scale * scale); - this.perpendicularPart = (dx * (y - this.nodeA.y) - dy * (x - this.nodeA.x)) / scale; - // snap to a straight line - if (this.parallelPart > 0 && this.parallelPart < 1 && Math.abs(this.perpendicularPart) < snapToPadding) { - this.lineAngleAdjust = (this.perpendicularPart < 0) * Math.PI; - this.perpendicularPart = 0; - } -}; - -Link.prototype.getEndPointsAndCircle = function () { - if (this.perpendicularPart === 0) { - const midX = (this.nodeA.x + this.nodeB.x) / 2; - const midY = (this.nodeA.y + this.nodeB.y) / 2; - const start = this.nodeA.closestPointOnCircle(midX, midY); - const end = this.nodeB.closestPointOnCircle(midX, midY); - return { - 'hasCircle': false, - 'startX': start.x, - 'startY': start.y, - 'endX': end.x, - 'endY': end.y, - }; - } - const anchor = this.getAnchorPoint(); - const circle = circleFromThreePoints(this.nodeA.x, this.nodeA.y, this.nodeB.x, this.nodeB.y, anchor.x, anchor.y); - const isReversed = (this.perpendicularPart > 0); - const reverseScale = isReversed ? 1 : -1; - const startAngle = Math.atan2(this.nodeA.y - circle.y, this.nodeA.x - circle.x) - reverseScale * nodeRadius / circle.radius; - const endAngle = Math.atan2(this.nodeB.y - circle.y, this.nodeB.x - circle.x) + reverseScale * nodeRadius / circle.radius; - const startX = circle.x + circle.radius * Math.cos(startAngle); - const startY = circle.y + circle.radius * Math.sin(startAngle); - const endX = circle.x + circle.radius * Math.cos(endAngle); - const endY = circle.y + circle.radius * Math.sin(endAngle); - return { - 'hasCircle': true, - 'startX': startX, - 'startY': startY, - 'endX': endX, - 'endY': endY, - 'startAngle': startAngle, - 'endAngle': endAngle, - 'circleX': circle.x, - 'circleY': circle.y, - 'circleRadius': circle.radius, - 'reverseScale': reverseScale, - 'isReversed': isReversed, - }; -}; - -Link.prototype.draw = function (c, color) { - const stuff = this.getEndPointsAndCircle(); - // draw arc - c.beginPath(); - if (stuff.hasCircle) { - c.arc(stuff.circleX, stuff.circleY, stuff.circleRadius, stuff.startAngle, stuff.endAngle, stuff.isReversed); - } else { - c.moveTo(stuff.startX, stuff.startY); - c.lineTo(stuff.endX, stuff.endY); - } - - // set color of stroke to white - stroke_theme_based(c, color); - - // draw the head of the arrow - if (stuff.hasCircle) { - drawArrow(c, stuff.endX, stuff.endY, stuff.endAngle - stuff.reverseScale * (Math.PI / 2)); - } else { - drawArrow(c, stuff.endX, stuff.endY, Math.atan2(stuff.endY - stuff.startY, stuff.endX - stuff.startX)); - } - // draw the text - if (stuff.hasCircle) { - const startAngle = stuff.startAngle; - let endAngle = stuff.endAngle; - if (endAngle < startAngle) { - endAngle += Math.PI * 2; - } - const textAngle = (startAngle + endAngle) / 2 + stuff.isReversed * Math.PI; - const textX = stuff.circleX + stuff.circleRadius * Math.cos(textAngle); - const textY = stuff.circleY + stuff.circleRadius * Math.sin(textAngle); - drawText(c, this.text, textX, textY, textAngle, selectedObject == this); - } else { - const textX = (stuff.startX + stuff.endX) / 2; - const textY = (stuff.startY + stuff.endY) / 2; - const textAngle = Math.atan2(stuff.endX - stuff.startX, stuff.startY - stuff.endY); - drawText(c, this.text, textX, textY, textAngle + this.lineAngleAdjust, selectedObject == this); - } -}; - -Link.prototype.containsPoint = function (x, y) { - var stuff = this.getEndPointsAndCircle(); - if (stuff.hasCircle) { - var dx = x - stuff.circleX; - var dy = y - stuff.circleY; - var distance = Math.sqrt(dx * dx + dy * dy) - stuff.circleRadius; - if (Math.abs(distance) < hitTargetPadding) { - var angle = Math.atan2(dy, dx); - var startAngle = stuff.startAngle; - var endAngle = stuff.endAngle; - if (stuff.isReversed) { - var temp = startAngle; - startAngle = endAngle; - endAngle = temp; - } - if (endAngle < startAngle) { - endAngle += Math.PI * 2; - } - if (angle < startAngle) { - angle += Math.PI * 2; - } else if (angle > endAngle) { - angle -= Math.PI * 2; - } - return (angle > startAngle && angle < endAngle); - } - } else { - var dx = stuff.endX - stuff.startX; - var dy = stuff.endY - stuff.startY; - var length = Math.sqrt(dx * dx + dy * dy); - var percent = (dx * (x - stuff.startX) + dy * (y - stuff.startY)) / (length * length); - var distance = (dx * (y - stuff.startY) - dy * (x - stuff.startX)) / length; - return (percent > 0 && percent < 1 && Math.abs(distance) < hitTargetPadding); - } - return false; -}; diff --git a/src/elements/node.js b/src/elements/node.js deleted file mode 100644 index e7c5399..0000000 --- a/src/elements/node.js +++ /dev/null @@ -1,76 +0,0 @@ -function Node(x, y) { - this.x = x; - this.y = y; - this.mouseOffsetX = 0; - this.mouseOffsetY = 0; - this.isAcceptState = false; - this.text = ''; - this.outputs = {} - - this.json_model = {}; - -} - -Node.prototype.getJson = function () { - if (!this.isAcceptState) - return {...this.json_model, "name": this.text, "outputs": this.outputs, "isAcceptState": false,} - else - return {...this.json_model, "name": this.text, "outputs": this.outputs, "isAcceptState": true} -} - - -Node.prototype.setJsonModel = function (json) { - if (json.hasOwnProperty('outputs')) { - this.outputs = json.outputs; - } - if (json.hasOwnProperty('name')) { - this.text = json.name - } - if (json.hasOwnProperty('acceptState')) { - this.isAcceptState = json.acceptState - } - - this.json_model = json -} - - -Node.prototype.setMouseStart = function (x, y) { - this.mouseOffsetX = this.x - x; - this.mouseOffsetY = this.y - y; -}; - -Node.prototype.setAnchorPoint = function (x, y) { - this.x = x + this.mouseOffsetX; - this.y = y + this.mouseOffsetY; -}; - -Node.prototype.draw = function (c, mode) { - // draw the circle - c.beginPath(); - c.arc(this.x, this.y, nodeRadius, 0, 2 * Math.PI, false); - stroke_theme_based(c, mode) - - // draw the text - drawText(c, this.text, this.x, this.y, null, selectedObject === this); - - // draw a double circle for an accept state - if (this.isAcceptState) { - c.beginPath(); - c.arc(this.x, this.y, nodeRadius - 6, 0, 2 * Math.PI, false); - stroke_theme_based(c, mode) - } -}; - -Node.prototype.closestPointOnCircle = function (x, y) { - var dx = x - this.x; - var dy = y - this.y; - var scale = Math.sqrt(dx * dx + dy * dy); - return { - 'x': this.x + dx * nodeRadius / scale, - 'y': this.y + dy * nodeRadius / scale, - }; -}; - -Node.prototype.containsPoint = function (x, y) { - return (x - this.x) * (x - this.x) + (y - this.y) * (y - this.y) < nodeRadius * nodeRadius; -}; diff --git a/src/elements/self_link.js b/src/elements/self_link.js deleted file mode 100644 index 671e8d4..0000000 --- a/src/elements/self_link.js +++ /dev/null @@ -1,72 +0,0 @@ -function SelfLink(node, mouse) { - this.node = node; - this.anchorAngle = 0; - this.mouseOffsetAngle = 0; - this.text = ''; - - - if (mouse) { - this.setAnchorPoint(mouse.x, mouse.y); - } -} - -SelfLink.prototype.setMouseStart = function (x, y) { - this.mouseOffsetAngle = this.anchorAngle - Math.atan2(y - this.node.y, x - this.node.x); -}; - -SelfLink.prototype.setAnchorPoint = function (x, y) { - this.anchorAngle = Math.atan2(y - this.node.y, x - this.node.x) + this.mouseOffsetAngle; - // snap to 90 degrees - var snap = Math.round(this.anchorAngle / (Math.PI / 2)) * (Math.PI / 2); - if (Math.abs(this.anchorAngle - snap) < 0.1) this.anchorAngle = snap; - // keep in the range -pi to pi so our containsPoint() function always works - if (this.anchorAngle < -Math.PI) this.anchorAngle += 2 * Math.PI; - if (this.anchorAngle > Math.PI) this.anchorAngle -= 2 * Math.PI; -}; - -SelfLink.prototype.getEndPointsAndCircle = function () { - var circleX = this.node.x + 1.5 * nodeRadius * Math.cos(this.anchorAngle); - var circleY = this.node.y + 1.5 * nodeRadius * Math.sin(this.anchorAngle); - var circleRadius = 0.75 * nodeRadius; - var startAngle = this.anchorAngle - Math.PI * 0.8; - var endAngle = this.anchorAngle + Math.PI * 0.8; - var startX = circleX + circleRadius * Math.cos(startAngle); - var startY = circleY + circleRadius * Math.sin(startAngle); - var endX = circleX + circleRadius * Math.cos(endAngle); - var endY = circleY + circleRadius * Math.sin(endAngle); - return { - 'hasCircle': true, - 'startX': startX, - 'startY': startY, - 'endX': endX, - 'endY': endY, - 'startAngle': startAngle, - 'endAngle': endAngle, - 'circleX': circleX, - 'circleY': circleY, - 'circleRadius': circleRadius - }; -}; - -SelfLink.prototype.draw = function (c) { - var stuff = this.getEndPointsAndCircle(); - // draw arc - c.beginPath(); - c.arc(stuff.circleX, stuff.circleY, stuff.circleRadius, stuff.startAngle, stuff.endAngle, false); - stroke_theme_based(c) - - // draw the text on the loop farthest from the node - var textX = stuff.circleX + stuff.circleRadius * Math.cos(this.anchorAngle); - var textY = stuff.circleY + stuff.circleRadius * Math.sin(this.anchorAngle); - drawText(c, this.text, textX, textY, this.anchorAngle, selectedObject == this); - // draw the head of the arrow - drawArrow(c, stuff.endX, stuff.endY, stuff.endAngle + Math.PI * 0.4); -}; - -SelfLink.prototype.containsPoint = function (x, y) { - var stuff = this.getEndPointsAndCircle(); - var dx = x - stuff.circleX; - var dy = y - stuff.circleY; - var distance = Math.sqrt(dx * dx + dy * dy) - stuff.circleRadius; - return (Math.abs(distance) < hitTargetPadding); -}; diff --git a/src/elements/start_link.js b/src/elements/start_link.js deleted file mode 100644 index 92aadbc..0000000 --- a/src/elements/start_link.js +++ /dev/null @@ -1,65 +0,0 @@ -function StartLink(node, start) { - this.node = node; - this.deltaX = 0; - this.deltaY = 0; - this.text = ''; - - this.outputs = {}; - - if (start) { - this.setAnchorPoint(start.x, start.y); - } -} - -StartLink.prototype.setAnchorPoint = function (x, y) { - this.deltaX = x - this.node.x; - this.deltaY = y - this.node.y; - - if (Math.abs(this.deltaX) < snapToPadding) { - this.deltaX = 0; - } - - if (Math.abs(this.deltaY) < snapToPadding) { - this.deltaY = 0; - } -}; - -StartLink.prototype.getEndPoints = function () { - var startX = this.node.x + this.deltaX; - var startY = this.node.y + this.deltaY; - var end = this.node.closestPointOnCircle(startX, startY); - return { - 'startX': startX, - 'startY': startY, - 'endX': end.x, - 'endY': end.y, - }; -}; - -StartLink.prototype.draw = function (c) { - var stuff = this.getEndPoints(); - - // draw the line - c.beginPath(); - c.moveTo(stuff.startX, stuff.startY); - c.lineTo(stuff.endX, stuff.endY); - stroke_theme_based(c) - - - // draw the text at the end without the arrow - var textAngle = Math.atan2(stuff.startY - stuff.endY, stuff.startX - stuff.endX); - drawText(c, this.text, stuff.startX, stuff.startY, textAngle, selectedObject == this); - - // draw the head of the arrow - drawArrow(c, stuff.endX, stuff.endY, Math.atan2(-this.deltaY, -this.deltaX)); -}; - -StartLink.prototype.containsPoint = function (x, y) { - var stuff = this.getEndPoints(); - var dx = stuff.endX - stuff.startX; - var dy = stuff.endY - stuff.startY; - var length = Math.sqrt(dx * dx + dy * dy); - var percent = (dx * (x - stuff.startX) + dy * (y - stuff.startY)) / (length * length); - var distance = (dx * (y - stuff.startY) - dy * (x - stuff.startX)) / length; - return (percent > 0 && percent < 1 && Math.abs(distance) < hitTargetPadding); -}; diff --git a/src/elements/temporary_link.js b/src/elements/temporary_link.js deleted file mode 100644 index 064bf77..0000000 --- a/src/elements/temporary_link.js +++ /dev/null @@ -1,16 +0,0 @@ -function TemporaryLink(from, to) { - this.from = from; - this.to = to; -} - -TemporaryLink.prototype.draw = function (c) { - // draw the line - c.beginPath(); - c.moveTo(this.to.x, this.to.y); - c.lineTo(this.from.x, this.from.y); - stroke_theme_based(c) - - - // draw the head of the arrow - drawArrow(c, this.to.x, this.to.y, Math.atan2(this.to.y - this.from.y, this.to.x - this.from.x)); -}; diff --git a/src/export_as/json.js b/src/export_as/json.js deleted file mode 100644 index ef56149..0000000 --- a/src/export_as/json.js +++ /dev/null @@ -1,41 +0,0 @@ -function ExportAsJson() { - - - const obj = {"nodes": [], "links": []} - - for (let i = 0; i < nodes.length; i++) { - const node = nodes[i] - obj.nodes.push({ - name: node.text, - outputs: node.outputs, - isAcceptState: node.isAcceptState, - ...node.json_model - }) - } - - - for (let i = 0; i < links.length; i++) { - const link = links[i] - - if (link.node !== undefined) { - obj.links.push({ - name: link.text, - source: link.node.text, - dest: link.node.text, - ...link.json_model - } - ) - } else { - obj.links.push({ - name: link.text, - source: link.nodeA.text, - dest: link.nodeB.text, - ...link.json_model - }) - } - } - - return JSON.stringify(obj) -} - - diff --git a/src/export_as/latex.js b/src/export_as/latex.js deleted file mode 100644 index aff7150..0000000 --- a/src/export_as/latex.js +++ /dev/null @@ -1,106 +0,0 @@ -// draw using this instead of a canvas and call toLaTeX() afterward -function ExportAsLaTeX() { - this._points = []; - this._texData = ''; - this._scale = 0.1; // to convert pixels to document space (TikZ breaks if the numbers get too big, above 500?) - - this.toLaTeX = function () { - return '\\documentclass[12pt]{article}\n' + - '\\usepackage{tikz}\n' + - '\n' + - '\\begin{document}\n' + - '\n' + - '\\begin{center}\n' + - '\\begin{tikzpicture}[scale=0.2]\n' + - '\\tikzstyle{every node}+=[inner sep=0pt]\n' + - this._texData + - '\\end{tikzpicture}\n' + - '\\end{center}\n' + - '\n' + - '\\end{document}\n'; - }; - - this.beginPath = function () { - this._points = []; - }; - this.arc = function (x, y, radius, startAngle, endAngle, isReversed) { - x *= this._scale; - y *= this._scale; - radius *= this._scale; - if (endAngle - startAngle == Math.PI * 2) { - this._texData += '\\draw [' + this.strokeStyle + '] (' + fixed(x, 3) + ',' + fixed(-y, 3) + ') circle (' + fixed(radius, 3) + ');\n'; - } else { - if (isReversed) { - var temp = startAngle; - startAngle = endAngle; - endAngle = temp; - } - if (endAngle < startAngle) { - endAngle += Math.PI * 2; - } - // TikZ needs the angles to be in between -2pi and 2pi or it breaks - if (Math.min(startAngle, endAngle) < -2 * Math.PI) { - startAngle += 2 * Math.PI; - endAngle += 2 * Math.PI; - } else if (Math.max(startAngle, endAngle) > 2 * Math.PI) { - startAngle -= 2 * Math.PI; - endAngle -= 2 * Math.PI; - } - startAngle = -startAngle; - endAngle = -endAngle; - this._texData += '\\draw [' + this.strokeStyle + '] (' + fixed(x + radius * Math.cos(startAngle), 3) + ',' + fixed(-y + radius * Math.sin(startAngle), 3) + ') arc (' + fixed(startAngle * 180 / Math.PI, 5) + ':' + fixed(endAngle * 180 / Math.PI, 5) + ':' + fixed(radius, 3) + ');\n'; - } - }; - this.moveTo = this.lineTo = function (x, y) { - x *= this._scale; - y *= this._scale; - this._points.push({'x': x, 'y': y}); - }; - this.stroke = function () { - if (this._points.length == 0) return; - this._texData += '\\draw [' + this.strokeStyle + ']'; - for (var i = 0; i < this._points.length; i++) { - var p = this._points[i]; - this._texData += (i > 0 ? ' --' : '') + ' (' + fixed(p.x, 2) + ',' + fixed(-p.y, 2) + ')'; - } - this._texData += ';\n'; - }; - this.fill = function () { - if (this._points.length == 0) return; - this._texData += '\\fill [' + this.strokeStyle + ']'; - for (var i = 0; i < this._points.length; i++) { - var p = this._points[i]; - this._texData += (i > 0 ? ' --' : '') + ' (' + fixed(p.x, 2) + ',' + fixed(-p.y, 2) + ')'; - } - this._texData += ';\n'; - }; - this.measureText = function (text) { - var c = canvas.getContext('2d'); - c.font = '20px "Times New Romain", serif'; - return c.measureText(text); - }; - this.advancedFillText = function (text, originalText, x, y, angleOrNull) { - if (text.replace(' ', '').length > 0) { - var nodeParams = ''; - // x and y start off as the center of the text, but will be moved to one side of the box when angleOrNull != null - if (angleOrNull != null) { - var width = this.measureText(text).width; - var dx = Math.cos(angleOrNull); - var dy = Math.sin(angleOrNull); - if (Math.abs(dx) > Math.abs(dy)) { - if (dx > 0) nodeParams = '[right] ', x -= width / 2; - else nodeParams = '[left] ', x += width / 2; - } else { - if (dy > 0) nodeParams = '[below] ', y -= 10; - else nodeParams = '[above] ', y += 10; - } - } - x *= this._scale; - y *= this._scale; - this._texData += '\\draw (' + fixed(x, 2) + ',' + fixed(-y, 2) + ') node ' + nodeParams + '{$' + originalText.replace(/ /g, '\\mbox{ }') + '$};\n'; - } - }; - - this.translate = this.save = this.restore = this.clearRect = function () { - }; -} diff --git a/src/export_as/svg.js b/src/export_as/svg.js deleted file mode 100644 index 07eee16..0000000 --- a/src/export_as/svg.js +++ /dev/null @@ -1,94 +0,0 @@ -// draw using this instead of a canvas and call toSVG() afterward -function ExportAsSVG() { - this.fillStyle = 'black'; - this.strokeStyle = 'black'; - this.lineWidth = 1; - this.font = '12px Arial, sans-serif'; - this._points = []; - this._svgData = ''; - this._transX = 0; - this._transY = 0; - - this.toSVG = function () { - return '\n\n\n\n' + this._svgData + '\n'; - }; - - this.beginPath = function () { - this._points = []; - }; - this.arc = function (x, y, radius, startAngle, endAngle, isReversed) { - x += this._transX; - y += this._transY; - var style = 'stroke="' + this.strokeStyle + '" stroke-width="' + this.lineWidth + '" fill="none"'; - - if (endAngle - startAngle === Math.PI * 2) { - this._svgData += '\t\n'; - } else { - if (isReversed) { - var temp = startAngle; - startAngle = endAngle; - endAngle = temp; - } - - if (endAngle < startAngle) { - endAngle += Math.PI * 2; - } - - var startX = x + radius * Math.cos(startAngle); - var startY = y + radius * Math.sin(startAngle); - var endX = x + radius * Math.cos(endAngle); - var endY = y + radius * Math.sin(endAngle); - var useGreaterThan180 = (Math.abs(endAngle - startAngle) > Math.PI); - var goInPositiveDirection = 1; - - this._svgData += '\t\n'; - } - }; - this.moveTo = this.lineTo = function (x, y) { - x += this._transX; - y += this._transY; - this._points.push({'x': x, 'y': y}); - }; - this.stroke = function () { - if (this._points.length === 0) return; - this._svgData += '\t\n'; - }; - this.fill = function () { - if (this._points.length === 0) return; - this._svgData += '\t\n'; - }; - this.measureText = function (text) { - var c = canvas.getContext('2d'); - c.font = '20px "Times New Romain", serif'; - return c.measureText(text); - }; - this.fillText = function (text, x, y) { - x += this._transX; - y += this._transY; - if (text.replace(' ', '').length > 0) { - this._svgData += '\t' + textToXML(text) + '\n'; - } - }; - this.translate = function (x, y) { - this._transX = x; - this._transY = y; - }; - - this.save = this.restore = this.clearRect = function () { - }; -} diff --git a/src/main/fsm.js b/src/main/fsm.js deleted file mode 100644 index bd3d317..0000000 --- a/src/main/fsm.js +++ /dev/null @@ -1,643 +0,0 @@ -/* ADDED VARS */ -let container; -let editor; -let options; - - -let in_panel = false; -let in_canvas = false; - -let body_saved; - - -/* MODIFIED FUNCTIONS */ -function drawUsing(c) { - c.clearRect(0, 0, canvas.width, canvas.height); - c.save(); - c.translate(0.5, 0.5); - let mode; - - for (let i = 0; i < nodes.length; i++) { - c.lineWidth = 1; - mode = (nodes[i] === selectedObject) ? 'focus' : 'normal'; - nodes[i].draw(c, mode); - } - for (let i = 0; i < links.length; i++) { - c.lineWidth = 1; - mode = (links[i] === selectedObject) ? 'focus' : 'normal'; - links[i].draw(c, mode); - } - if (currentLink != null) { - c.lineWidth = 1; - c.fillStyle = c.strokeStyle = 'black'; - currentLink.draw(c, mode); - } - - c.restore(); -} - - -function stroke_theme_based(c, mode) { - if (theme === "dark") { - if (mode === "normal") { - c.strokeStyle = "white" - c.fillStyle = "white" - } else { - c.strokeStyle = "#e59c24" - c.fillStyle = "#e59c24" - } - } else { - if (mode === "normal") { - c.strokeStyle = "black" - c.fillStyle = "black" - } else { - c.strokeStyle = "#1fc493" - c.fillStyle = "#1fc493" - } - } - c.stroke(); -} - - -/*EDITOR PROPS*/ - -function create_json_editor() { - // create the editor - container = document.getElementById("jsoneditor") - options = { - mode: "tree", mainMenuBar: false, statusBar: false, enableSort: false, enableTransform: false - } - - editor = new JSONEditor(container, options) - -// set json - const initialJson = { - "name": "exampleName", - "outputs": { - "output1": "string_val1", - "output2": 2 - }, - "isAcceptState": false, - - } - editor.set(initialJson) - -// get json - editor.expandAll() -} - - -function set_editor_content(json_content) { - editor.set(json_content) - editor.expandAll() -} - - -function get_editor_content() { - return editor.get() -} - -/* NEW FUNCTIONS */ -function check_if_mobile_small() { - if (window.innerWidth <= 1600) { - - const styleTag = document.createElement('style'); - styleTag.textContent = "\n" + - "/*======================\n" + - " 404 page\n" + - "=======================*/\n" + - "\n" + - "\n" + - ".page_404{ padding:40px 0; background:#fff; font-family: 'Arvo', serif;\n" + - "}\n" + - "\n" + - ".page_404 img{ width:100%;}\n" + - "\n" + - ".four_zero_four_bg{\n" + - " \n" + - " background-image: url(https://cdn.dribbble.com/users/285475/screenshots/2083086/dribbble_1.gif);\n" + - " height: 400px;\n" + - " background-position: center;\n" + - " }\n" + - " \n" + - " \n" + - " .four_zero_four_bg h1{\n" + - " font-size:80px;\n" + - " }\n" + - " \n" + - " .four_zero_four_bg h3{\n" + - "\t\t\t font-size:80px;\n" + - "\t\t\t }\n" + - "\t\t\t \n" + - "\t\t\t .link_404{\t\t\t \n" + - "\tcolor: #fff!important;\n" + - " padding: 10px 20px;\n" + - " background: #39ac31;\n" + - " margin: 20px 0;\n" + - " display: inline-block;}\n" + - "\t.contant_box_404{ margin-top:-50px;}"; - - document.head.appendChild(styleTag); - - if (body_saved === undefined) - body_saved = document.body.innerHTML - - - document.body.innerHTML = "
\n" + - "\t
\n" + - "\t\t
\t\n" + - "\t\t
\n" + - "\t\t
\n" + - "\t\t
\n" + - "\t\t\t

\n" + - "\t\t\n" + - "\t\t\n" + - "\t\t
\n" + - "\t\t\n" + - "\t\t
\n" + - "\t\t

\n" + - "\t\tYour Device Is To Small For displaying Contets\n" + - "\t\t

\n" + - "\t\t\n" + - "\t\t\n" + - "\t
\n" + - "\t\t
\n" + - "\t\t
\n" + - "\t\t
\n" + - "\t
\n" + - "
" - - return true - } else { - if (body_saved !== undefined) { - document.body.innerHTML = body_saved; - body_saved = undefined; - } - return false - } -} - -window.addEventListener("resize", check_if_mobile_small); - - -/*-------------------------------------------------------------*/ - - -let greekLetterNames = ['Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon', 'Zeta', 'Eta', 'Theta', 'Iota', 'Kappa', 'Lambda', 'Mu', 'Nu', 'Xi', 'Omicron', 'Pi', 'Rho', 'Sigma', 'Tau', 'Upsilon', 'Phi', 'Chi', 'Psi', 'Omega']; - -function convertLatexShortcuts(text) { - // html greek characters - for (let i = 0; i < greekLetterNames.length; i++) { - let name = greekLetterNames[i]; - text = text.replace(new RegExp('\\\\' + name, 'g'), String.fromCharCode(913 + i + (i > 16))); - text = text.replace(new RegExp('\\\\' + name.toLowerCase(), 'g'), String.fromCharCode(945 + i + (i > 16))); - } - - // subscripts - for (let i = 0; i < 10; i++) { - text = text.replace(new RegExp('_' + i, 'g'), String.fromCharCode(8320 + i)); - } - - return text; -} - -function textToXML(text) { - text = text.replace(/&/g, '&').replace(//g, '>'); - let result = ''; - for (let i = 0; i < text.length; i++) { - let c = text.charCodeAt(i); - if (c >= 0x20 && c <= 0x7E) { - result += text[i]; - } else { - result += '&#' + c + ';'; - } - } - return result; -} - -function drawArrow(c, x, y, angle) { - let dx = Math.cos(angle); - let dy = Math.sin(angle); - c.beginPath(); - c.moveTo(x, y); - c.lineTo(x - 8 * dx + 5 * dy, y - 8 * dy - 5 * dx); - c.lineTo(x - 8 * dx - 5 * dy, y - 8 * dy + 5 * dx); - c.fill(); -} - - -function canvasHasFocus() { - return in_canvas; -} - -function drawText(c, originalText, x, y, angleOrNull, isSelected) { - let text = convertLatexShortcuts(originalText); - c.font = '20px "Times New Roman", serif'; - let width = c.measureText(text).width; - - // center the text - x -= width / 2; - - // position the text intelligently if given an angle - if (angleOrNull != null) { - let cos = Math.cos(angleOrNull); - let sin = Math.sin(angleOrNull); - let cornerPointX = (width / 2 + 5) * (cos > 0 ? 1 : -1); - let cornerPointY = (10 + 5) * (sin > 0 ? 1 : -1); - let slide = sin * Math.pow(Math.abs(sin), 40) * cornerPointX - cos * Math.pow(Math.abs(cos), 10) * cornerPointY; - x += cornerPointX - sin * slide; - y += cornerPointY + cos * slide; - } - - // draw text and caret (round the coordinates so the caret falls on a pixel) - if ('advancedFillText' in c) { - c.advancedFillText(text, originalText, x + width / 2, y, angleOrNull); - } else { - x = Math.round(x); - y = Math.round(y); - c.fillText(text, x, y + 6); - if (isSelected && caretVisible && canvasHasFocus() && document.hasFocus()) { - x += width; - c.beginPath(); - c.moveTo(x, y - 10); - c.lineTo(x, y + 10); - c.stroke(); - } - } -} - -let caretTimer; -let caretVisible = true; - -function resetCaret() { - clearInterval(caretTimer); - caretTimer = setInterval('caretVisible = !caretVisible; draw()', 500); - caretVisible = true; -} - -let theme = "light" -let canvas; -let panel; -let nodeRadius = 45; -let nodes = []; -let links = []; -let snapToPadding = 6; // pixels -let hitTargetPadding = 6; // pixels -let selectedObject = null; // either a Link or a Node -let currentLink = null; // a Link -let movingObject = false; -let originalClick; - -function draw() { - - - if (in_canvas && (selectedObject instanceof Node || selectedObject instanceof Link)) - set_editor_content(selectedObject.getJson()) - - - drawUsing(canvas.getContext('2d')); - saveBackup(); -} - -function selectObject(x, y) { - for (let i = 0; i < nodes.length; i++) { - if (nodes[i].containsPoint(x, y)) { - return nodes[i]; - } - } - for (let i = 0; i < links.length; i++) { - if (links[i].containsPoint(x, y)) { - return links[i]; - } - } - return null; -} - -function snapNode(node) { - for (let i = 0; i < nodes.length; i++) { - if (nodes[i] === node) continue; - - if (Math.abs(node.x - nodes[i].x) < snapToPadding) { - node.x = nodes[i].x; - } - - if (Math.abs(node.y - nodes[i].y) < snapToPadding) { - node.y = nodes[i].y; - } - } -} - -window.onload = function () { - - if (check_if_mobile_small()) return; - - canvas = document.getElementById('canvas'); - panel = document.getElementById('panel'); - - create_json_editor() - // restoreBackup(); - // draw(); - - canvas.onmousedown = function (e) { - - const mouse = crossBrowserRelativeMousePos(e); - in_canvas = true; - - // if selectedObject is not null than save the json of the editor into the node - const json = get_editor_content() - if (selectedObject != null && selectedObject instanceof Node) { - selectedObject.setJsonModel(json) - } - - - movingObject = false; - originalClick = mouse; - - selectedObject = selectObject(mouse.x, mouse.y); - if (selectedObject != null) { - - if (shift && selectedObject instanceof Node) { - currentLink = new SelfLink(selectedObject, mouse); - } else { - movingObject = true; - deltaMouseX = deltaMouseY = 0; - if (selectedObject.setMouseStart) { - selectedObject.setMouseStart(mouse.x, mouse.y); - } - } - resetCaret(); - } else if (shift) { - currentLink = new TemporaryLink(mouse, mouse); - } - - draw(); - - if (canvasHasFocus()) { - // disable drag-and-drop only if the canvas is already focused - return false; - } else { - // otherwise, let the browser switch the focus away from wherever it was - resetCaret(); - return true; - } - }; - - canvas.ondblclick = function (e) { - - const mouse = crossBrowserRelativeMousePos(e); - selectedObject = selectObject(mouse.x, mouse.y); - - if (selectedObject == null) { - selectedObject = new Node(mouse.x, mouse.y); - nodes.push(selectedObject); - resetCaret(); - draw(); - } else if (selectedObject instanceof Node) { - selectedObject.isAcceptState = !selectedObject.isAcceptState; - if (selectedObject.isAcceptState) - draw(); - } - }; - - canvas.onmousemove = function (e) { - const mouse = crossBrowserRelativeMousePos(e); - - if (currentLink != null) { - let targetNode = selectObject(mouse.x, mouse.y); - if (!(targetNode instanceof Node)) { - targetNode = null; - } - - if (selectedObject == null) { - if (targetNode != null) { - currentLink = new StartLink(targetNode, originalClick); - } else { - currentLink = new TemporaryLink(originalClick, mouse); - } - } else { - if (targetNode === selectedObject) { - currentLink = new SelfLink(selectedObject, mouse); - } else if (targetNode != null) { - currentLink = new Link(selectedObject, targetNode); - } else { - currentLink = new TemporaryLink(selectedObject.closestPointOnCircle(mouse.x, mouse.y), mouse); - } - } - draw(); - } - - if (movingObject) { - selectedObject.setAnchorPoint(mouse.x, mouse.y); - if (selectedObject instanceof Node) { - snapNode(selectedObject); - } - draw(); - } - }; - - canvas.onmouseup = function (e) { - movingObject = false; - - if (currentLink != null) { - if (!(currentLink instanceof TemporaryLink)) { - selectedObject = currentLink; - links.push(currentLink); - resetCaret(); - } - currentLink = null; - draw(); - } - }; - - panel.onmousedown = function (e) { - in_canvas = false; - in_panel = true; - } -} - -let shift = false; - -document.onkeydown = function (e) { - let key = crossBrowserKey(e); - - if (key === 16) { - shift = true; - } else if (!canvasHasFocus()) { - // don't read keystrokes when other things have focus - return true; - } else if (key === 8) { // backspace key - if (selectedObject != null && 'text' in selectedObject) { - selectedObject.text = selectedObject.text.substr(0, selectedObject.text.length - 1); - resetCaret(); - draw(); - } - - // backspace is a shortcut for the back button, but do NOT want to change pages - return false; - } else if (key === 46) { // delete key - if (selectedObject != null) { - for (let i = 0; i < nodes.length; i++) { - if (nodes[i] === selectedObject) { - nodes.splice(i--, 1); - } - } - for (let i = 0; i < links.length; i++) { - if (links[i] === selectedObject || links[i].node === selectedObject || links[i].nodeA === selectedObject || links[i].nodeB === selectedObject) { - links.splice(i--, 1); - } - } - selectedObject = null; - draw(); - } - } -}; - -document.onkeyup = function (e) { - let key = crossBrowserKey(e); - - if (key === 16) { - shift = false; - } -}; - -document.onkeypress = function (e) { - // don't read keystrokes when other things have focus - const key = crossBrowserKey(e); - if (!canvasHasFocus()) { - // don't read keystrokes when other things have focus - return true; - } else if (key >= 0x20 && key <= 0x7E && !e.metaKey && !e.altKey && !e.ctrlKey && selectedObject != null) { - selectedObject.text += String.fromCharCode(key); - resetCaret(); - draw(); - - // don't let keys do their actions (like space scrolls down the page) - return false; - } else if (key === 8) { - // backspace is a shortcut for the back button, but do NOT want to change pages - return false; - } -}; - -function crossBrowserKey(e) { - return e.which || e.keyCode; -} - -function crossBrowserElementPos(e) { - let obj = e.target || e.srcElement; - let x = 0, y = 0; - while (obj.offsetParent) { - x += obj.offsetLeft; - y += obj.offsetTop; - obj = obj.offsetParent; - } - return {'x': x, 'y': y}; -} - -function crossBrowserMousePos(e) { - return { - 'x': e.pageX || e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft, - 'y': e.pageY || e.clientY + document.body.scrollTop + document.documentElement.scrollTop, - }; -} - -function crossBrowserRelativeMousePos(e) { - const element = crossBrowserElementPos(e); - const mouse = crossBrowserMousePos(e); - return { - 'x': mouse.x - element.x, - 'y': mouse.y - element.y - }; -} - -function output(text) { - const element = document.getElementById('output'); - element.style.display = 'block'; - element.value = text; -} - -function saveAsPNG() { - canvas.toBlob(blob => { - navigator.clipboard.write([new ClipboardItem({'image/png': blob})]) - }) - - successToast() -} - -function saveAsSVG() { - let exporter = new ExportAsSVG(); - let oldSelectedObject = selectedObject; - selectedObject = null; - drawUsing(exporter); - selectedObject = oldSelectedObject; - let svgData = exporter.toSVG(); - output(svgData); - // Chrome isn't ready for this yet, the 'Save As' menu item is disabled - // document.location.href = 'data:image/svg+xml;base64,' + btoa(svgData); -} - -function saveAsLaTeX() { - let exporter = new ExportAsLaTeX(); - let oldSelectedObject = selectedObject; - selectedObject = null; - drawUsing(exporter); - selectedObject = oldSelectedObject; - let texData = exporter.toLaTeX(); - copyToClipboard(texData); -} - -function saveAsJson() { - return copyToClipboard(ExportAsJson()) -} - - -function successToast() { - Toastify({ - text: "Copied to clipboard \t\t🤪", - classname: "info", - duration: 3000, - offset: 50, - gravity: "top", // `top` or `bottom` - position: "left", // `left`, `center` or `right` - stopOnFocus: true, // Prevents dismissing of toast on hover - style: { - background: "linear-gradient(to right, #00b09b, #96c93d)", - height: "45px", - width: "240px" - }, - onClick: function () { - } // Callback after click - }).showToast(); -} - - -async function copyToClipboard(textToCopy) { - - - try { - if (navigator.clipboard && window.isSecureContext) { - await navigator.clipboard.writeText(textToCopy); - successToast() - - } else { - // Use the 'out of viewport hidden text area' trick - const textArea = document.createElement("textarea"); - textArea.value = textToCopy; - - // Move textarea out of the viewport so it's not visible - textArea.style.position = "absolute"; - textArea.style.left = "-999999px"; - - document.body.appendChild(textArea); - textArea.select(); - - // Execute the copy command - document.execCommand('copy'); - - // Clean up - document.body.removeChild(textArea); - } - } catch (error) { - console.error(error); - } -} diff --git a/src/main/math.js b/src/main/math.js deleted file mode 100644 index b9ce219..0000000 --- a/src/main/math.js +++ /dev/null @@ -1,19 +0,0 @@ -function det(a, b, c, d, e, f, g, h, i) { - return a * e * i + b * f * g + c * d * h - a * f * h - b * d * i - c * e * g; -} - -function circleFromThreePoints(x1, y1, x2, y2, x3, y3) { - var a = det(x1, y1, 1, x2, y2, 1, x3, y3, 1); - var bx = -det(x1 * x1 + y1 * y1, y1, 1, x2 * x2 + y2 * y2, y2, 1, x3 * x3 + y3 * y3, y3, 1); - var by = det(x1 * x1 + y1 * y1, x1, 1, x2 * x2 + y2 * y2, x2, 1, x3 * x3 + y3 * y3, x3, 1); - var c = -det(x1 * x1 + y1 * y1, x1, y1, x2 * x2 + y2 * y2, x2, y2, x3 * x3 + y3 * y3, x3, y3); - return { - 'x': -bx / (2 * a), - 'y': -by / (2 * a), - 'radius': Math.sqrt(bx * bx + by * by - 4 * a * c) / (2 * Math.abs(a)) - }; -} - -function fixed(number, digits) { - return number.toFixed(digits).replace(/0+$/, '').replace(/\.$/, ''); -} diff --git a/src/main/save.js b/src/main/save.js deleted file mode 100644 index b28d203..0000000 --- a/src/main/save.js +++ /dev/null @@ -1,98 +0,0 @@ -function restoreBackup() { - if (!localStorage || !JSON) { - return; - } - - try { - var backup = JSON.parse(localStorage['fsm']); - - for (var i = 0; i < backup.nodes.length; i++) { - var backupNode = backup.nodes[i]; - var node = new Node(backupNode.x, backupNode.y); - node.isAcceptState = backupNode.isAcceptState; - node.text = backupNode.text; - nodes.push(node); - } - for (var i = 0; i < backup.links.length; i++) { - var backupLink = backup.links[i]; - var link = null; - if (backupLink.type == 'SelfLink') { - link = new SelfLink(nodes[backupLink.node]); - link.anchorAngle = backupLink.anchorAngle; - link.text = backupLink.text; - } else if (backupLink.type == 'StartLink') { - link = new StartLink(nodes[backupLink.node]); - link.deltaX = backupLink.deltaX; - link.deltaY = backupLink.deltaY; - link.text = backupLink.text; - } else if (backupLink.type == 'Link') { - link = new Link(nodes[backupLink.nodeA], nodes[backupLink.nodeB]); - link.parallelPart = backupLink.parallelPart; - link.perpendicularPart = backupLink.perpendicularPart; - link.text = backupLink.text; - link.lineAngleAdjust = backupLink.lineAngleAdjust; - } - if (link != null) { - links.push(link); - } - } - } catch (e) { - localStorage['fsm'] = ''; - } -} - -function saveBackup() { - if (!localStorage || !JSON) { - return; - } - - var backup = { - 'nodes': [], - 'links': [], - }; - for (var i = 0; i < nodes.length; i++) { - var node = nodes[i]; - var backupNode = { - 'x': node.x, - 'y': node.y, - 'text': node.text, - 'isAcceptState': node.isAcceptState, - }; - backup.nodes.push(backupNode); - } - for (var i = 0; i < links.length; i++) { - var link = links[i]; - var backupLink = null; - if (link instanceof SelfLink) { - backupLink = { - 'type': 'SelfLink', - 'node': nodes.indexOf(link.node), - 'text': link.text, - 'anchorAngle': link.anchorAngle, - }; - } else if (link instanceof StartLink) { - backupLink = { - 'type': 'StartLink', - 'node': nodes.indexOf(link.node), - 'text': link.text, - 'deltaX': link.deltaX, - 'deltaY': link.deltaY, - }; - } else if (link instanceof Link) { - backupLink = { - 'type': 'Link', - 'nodeA': nodes.indexOf(link.nodeA), - 'nodeB': nodes.indexOf(link.nodeB), - 'text': link.text, - 'lineAngleAdjust': link.lineAngleAdjust, - 'parallelPart': link.parallelPart, - 'perpendicularPart': link.perpendicularPart, - }; - } - if (backupLink != null) { - backup.links.push(backupLink); - } - } - - localStorage['fsm'] = JSON.stringify(backup); -}