![]() System : Linux absol.cf 5.4.0-198-generic #218-Ubuntu SMP Fri Sep 27 20:18:53 UTC 2024 x86_64 User : www-data ( 33) PHP Version : 7.4.33 Disable Function : pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare, Directory : /proc/self/root/var/www/html/libs/absol-form/js/ciruiteditor/diagrameditor/ |
Upload File : |
import OOP from "absol/src/HTML5/OOP"; import BaseEditor from "../../core/BaseEditor"; import FCore, {_, $} from "../../core/FCore"; import '../../../css/circuitdiagram.css'; import SvgViewBox from "absol-svg/js/svg/SvgViewBox"; import GCore from "../../core/GCore"; import {AssemblerInstance} from "../../core/Assembler"; import CDENode from "../../dom/circuit/CDENode"; import IndexedPropertyNames from "../../core/IndexedPropertyNames"; import R from "../../R"; import LineEditor from "../lineeditor/LineEditor"; import {traversal} from "../../core/FNode"; import BaseBlock from "../../core/BaseBlock"; import Vec2 from "absol/src/Math/Vec2"; import Color from "absol/src/Color/Color"; import Thread from "absol/src/Network/Thread"; import GraphOptimizerFactor from "./GraphOptimizerFactor"; import NodePositionController from "./controller/NodePositionController"; import ViewBoxController from "./controller/ViewBoxController"; import Hanger from "absol-acomp/js/Hanger"; import NodeSelectController from "./controller/NodeSelectController"; import CMDTool from "../../fragment/CMDTool"; import CircuitDiagramEditorCmd, { CircuitDiagramEditorCmdDescriptors, CircuitDiagramEditorCmdTree } from "./CircuitDiagramEditorCmd"; import ClipboardManager from "../../ClipboardManager"; import LoadingCubeModal from "absol-acomp/js/LoadingCubeModal"; import NewLineController from "./controller/NewLineController"; import LineSelectController from "./controller/LineSelectController"; import IncludedBlockManager from "./IncludedBlockManager"; /*** * @extends BaseEditor * @constructor */ function CircuitDiagramEditor() { BaseEditor.call(this); this.viewBoxCtroller = new ViewBoxController(this); this.nodeController = new NodePositionController(this); this.nodeSelectController = new NodeSelectController(this); this.lineSelectController = new LineSelectController(this); this.newLineController = new NewLineController(this); this.cmdTool = new CMDTool(); this.includedBlockManager = new IncludedBlockManager(this); for (var i in this) { if (i.startsWith('ev_')) { this[i] = this[i].bind(this); } } this.$nodes = {}; this.$lines = {}; this.lines = []; this.diagram = {}; if (!CircuitDiagramEditor.optimizer) { CircuitDiagramEditor.optimizer = new Thread({ methods: { GraphOptimizerFactor: GraphOptimizerFactor }, extendCode: 'GraphOptimizerFactor(self);' }); CircuitDiagramEditor.optimizer.findBeautyGrid = function () { return this.invoke.apply(this, ['findBeautyGrid'].concat(Array.prototype.slice.call(arguments))) }; } this.optimizer = CircuitDiagramEditor.optimizer; this.cmdTool.attach(this); this.cmdTool.bindWithEditor(this); this.cmdRunner.assign(CircuitDiagramEditorCmd); } OOP.mixClass(CircuitDiagramEditor, BaseEditor); CircuitDiagramEditor.prototype.onStart = function () { this.selfHolder = this.formEditor.getEditorHolderByEditor(this); this.cmdTool.start(); }; CircuitDiagramEditor.prototype.onResume = function () { this.cmdTool.resume(); }; CircuitDiagramEditor.prototype.onPause = function () { this.cmdTool.pause(); }; CircuitDiagramEditor.prototype.notifySaved = function () { this.selfHolder.tabframe.modified = false; }; CircuitDiagramEditor.prototype.notifyUnsaved = function () { this.selfHolder.tabframe.modified = true; }; CircuitDiagramEditor.prototype.createView = function () { this.$view = _({ class: ['as-cde', 'as-choose-remove-line'], attr: { tabindex: 1 }, child: [ { class: 'as-cde-header', child: [ this.cmdTool.getView() ] }, { class: 'as-cde-body', child: [ GCore._({ tag: SvgViewBox.tag, class: 'as-cde-line-layer' }), { class: 'as-cde-node-layer', style: { left: '10px', top: '10px' } }, { class: 'as-cde-loading-modal', child: { class: 'as-cde-loading', child: 'cube-loading-ico' } } ] } ] }); this.$body = $('.as-cde-body', this.$view); this.$lineLayer = _({ tag: Hanger.tag, elt: $('.as-cde-line-layer', this.$view) }); this.$lineLayer.box.origin = new Vec2(10, 10); this.$nodeLayer = $('.as-cde-node-layer', this.$view); this.viewBoxCtroller.onCreateView(); }; CircuitDiagramEditor.prototype.setData = function (lines, diagram) { var self = this; this.lines = lines; this.diagram = diagram; this._updateNodes(); this._updateLines(); if (!diagram || !diagram.positions) setTimeout(this.autoAlignPosition.bind(this), 100); }; CircuitDiagramEditor.prototype.implicitLines = function (lines) { return lines; }; CircuitDiagramEditor.prototype.explicitLines = function (lines) { return lines; }; CircuitDiagramEditor.prototype.getLineData = function () { return this.explicitLines(this.lines); }; CircuitDiagramEditor.prototype.getDiagramData = function () { var positions = {}; var nodeElt; for (var nodeId in this.$nodes) { nodeElt = this.$nodes[nodeId]; positions[nodeId] = {x: nodeElt.x, y: nodeElt.y}; } return { includedBlocks: Object.keys(this.$nodes), positions: positions } }; CircuitDiagramEditor.prototype._makeNodeElt = function (props) { /*** * @type {CDENode} */ var nodeElt = _({ tag: CDENode.tag, props: Object.assign({ lines: [] }, props) }); nodeElt.$header.on('dblclick', function () { console.log('dblclick', this); //todo: edit node in other editor }) this.nodeController.addEventControl(nodeElt); this.newLineController.addNodeEventControl(nodeElt); return nodeElt; }; CircuitDiagramEditor.prototype.onAttached = function () { /*** * * @type {LayoutEditor} */ this.layoutEditor = this.getContext(R.LAYOUT_EDITOR); /*** * * @type {FormEditor} */ this.formEditor = this.getContext(R.FORM_EDITOR); }; CircuitDiagramEditor.prototype.onResume = function () { this._updateNodes(); this._updateLines(); }; CircuitDiagramEditor.prototype._updateNodes = function () { var nodeSheet = this.getNodeSheet(); var displayedBlockDict = this.lines.reduce(function (ac, cr) { var uNode = nodeSheet.byName[cr.u] || nodeSheet.byId[cr.u]; var vNode = nodeSheet.byName[cr.v] || nodeSheet.byId[cr.v]; if (uNode) ac[uNode.id] = uNode; if (vNode) ac[vNode.id] = vNode; return ac; }, {}); if (this.diagram && this.diagram.includedBlocks) { this.diagram.includedBlocks.reduce(function (ac, cr) { var node = nodeSheet.byId[cr]; if (node) { ac[node.id] = node; } return ac; }, displayedBlockDict); } var nodeId; for (nodeId in this.$nodes) { if (!displayedBlockDict[nodeId]) { this.$nodes[nodeId].remove(); delete this.$nodes[nodeId]; } } var nodeElt; var nodeInf; for (nodeId in displayedBlockDict) { nodeElt = this.$nodes[nodeId]; nodeInf = displayedBlockDict[nodeId]; if (!nodeElt) { nodeElt = this._makeNodeElt({ typeIcon: nodeInf.clazz.prototype.menuIcon, name: nodeInf.name || nodeInf.id, displayName: nodeInf.displayName, inputPins: nodeInf.inputPins, outputPins: nodeInf.outputPins, inputLines: {}, outputLines: {}, title: nodeId, nodeId: nodeId }); if (this.diagram && this.diagram && this.diagram.positions && this.diagram.positions[nodeId]) { nodeElt.x = this.diagram.positions[nodeId].x; nodeElt.y = this.diagram.positions[nodeId].y; } this.$nodes[nodeId] = nodeElt; this.$nodeLayer.addChild(nodeElt); nodeElt.reloadPinPosition(); } } }; CircuitDiagramEditor.prototype._updateLines = function () { var line; var lineElt; var startNode, endNode; var nodeSheet = this.getNodeSheet(); var u, v; var uId, vId; var invalidLines = []; for (var i = 0; i < this.lines.length; ++i) { line = this.lines[i]; u = nodeSheet.byName[line.u] || nodeSheet.byId[line.u]; v = nodeSheet.byName[line.v] || nodeSheet.byId[line.v]; if (!u || !v) continue; uId = u.id; vId = v.id; startNode = this.$nodes[uId]; endNode = this.$nodes[vId]; lineElt = this.$lines[line.id]; if (!lineElt) { lineElt = GCore._({ tag: 'g', class: 'as-cde-line-group', style: { '--line-color': new Color([Math.random(), Math.random(), Math.random(), 1]).toString() }, attr: { 'data-id': line.id }, child: [ { tag: 'path', class: 'as-cde-hit-line', }, { tag: 'path', class: 'as-cde-line' } ], props: { uId: uId, vId: vId, uPin: line.uPin, vPin: line.vPin, lineId: line.id } }); this.lineSelectController.addLineControlEvent(lineElt); this.$lines[line.id] = lineElt; this.$lineLayer.addChild(lineElt); startNode.lines[line.id] = line; endNode.lines[line.id] = line; } if (!this.updateLinePosition(line.id)) { invalidLines.push(line.id); } } if (invalidLines.length > 0) { console.error("Invalid lines: ", invalidLines.map(function (id) { return this.lines.find(function (line) { return line.id === id; }) }.bind(this))); } invalidLines.forEach(function (id) { this.deleteLine(id); }.bind(this)); }; CircuitDiagramEditor.prototype.updateLinePosition = function (id) { var lineElt = this.$lines[id]; if (!lineElt) return true; var uId = lineElt.uId; var vId = lineElt.vId; var startNode = this.$nodes[uId]; var endNode = this.$nodes[vId]; if (!startNode || !endNode) { return false; } var startPinHolder = startNode.pinHolders.out[lineElt.uPin]; var endPinHolder = endNode.pinHolders.in[lineElt.vPin]; if (!startPinHolder || !endPinHolder) { return false; } var startPos = startNode.position.add(startPinHolder.pos); var endPos = endNode.position.add(endPinHolder.pos); var dx = 50; if (startPos.x > endPos.x) dx += Math.min(200, startPos.x - endPos.x) / 2; var path = ['M', startPos.x, startPos.y, 'C', startPos.x + dx, startPos.y, ',', endPos.x - dx, endPos.y, ',', endPos.x, endPos.y].join(' '); lineElt.lastChild.attr('d', path); lineElt.firstChild.attr('d', path); return true; }; CircuitDiagramEditor.prototype.focusNode = function (node) { node = node || null; this.nodeSelectController.select(node, false); }; /*** * * @param {string} id */ CircuitDiagramEditor.prototype.deleteLine = function (id) { var lineElt = this.$lines[id]; if (!lineElt) return; lineElt.remove(); var uNodeElt = this.$nodes[lineElt.uId]; var vNodeElt = this.$nodes[lineElt.vId]; delete uNodeElt.lines[lineElt.lineId]; delete vNodeElt.lines[lineElt.lineId]; delete this.$lines[lineElt.lineId]; var lineIdx = this.lines.findIndex(function (it) { return it.id === lineElt.lineId; }); if (lineIdx >= 0) { this.lines.splice(lineIdx, 1); } else { console.error("Editor error: Could not find line id: " + lineElt.lineId); } }; CircuitDiagramEditor.prototype.getNodeSheet = function () { if (this._pointListCache && !this._pointListCache.expire) { return this._pointListCache; } this._pointListCache = {}; setTimeout(function () { this.expire = true; }.bind(this._pointListCache), 300); var list = []; var rootLayout = this.layoutEditor.rootLayout; var rootFragment = this.layoutEditor.rootFragment; traversal(rootLayout, function (path) { var node = path.node; var item; var pinCmp; if (node.fragment === rootFragment) { var clazz = AssemblerInstance.classes['COMPONENT'][node.tag]; item = { type: 'COMPONENT', id: node.attributes.id, name: node.attributes.name, displayName: node.attributes.displayName, text: '[' + node.tag + '] ' + node.attributes.name, value: node.attributes.id, order: 'z_' + node.tag + '_' + node.attributes.name, bTag: node.tag, pinList: Object.keys(node.pinHandlers).map(function (name) { return {text: name, value: name}; }), clazz: clazz } pinCmp = function (a, b) { var av = (IndexedPropertyNames[a.name] || 100); if (clazz.prototype.pinHandlers[a.name].get && clazz.prototype.pinHandlers[a.name].receives) { av /= 1000; } var bv = (IndexedPropertyNames[b.name] || 100); if (clazz.prototype.pinHandlers[b.name].get && clazz.prototype.pinHandlers[b.name].receives) { bv /= 1000; } return av - bv; } item.inputPins = Object.keys(clazz.prototype.pinHandlers).map(function (pinName) { if (clazz.prototype.pinHandlers[pinName].receives) return { name: pinName } else return null; }).filter(function (it) { return !!it; }); item.inputPins.sort(pinCmp); item.outputPins = Object.keys(clazz.prototype.pinHandlers).map(function (pinName) { if (clazz.prototype.pinHandlers[pinName].get) return { name: pinName } else return null; }).filter(function (it) { return !!it; }); item.outputPins.sort(pinCmp); if (node.tag.toLowerCase().match(/input|radio|checkbox|track|combo/)) { item.order = 'a_' + node.tag + '_' + node.attributes.name; } else if (node.tag.toLowerCase().match(/button|label|text/)) { item.order = 'c_' + node.tag + '_' + node.attributes.name; } list.push(item); } else { path.skipChildren(); } }); var blocks = this.layoutEditor.getBlockData(); blocks.forEach(function (block) { var id = block.attributes && block.attributes.id; var name = block.attributes && block.attributes.name; var clazz = AssemblerInstance.classes['BLOCK'][block.tag] || BaseBlock; var pinCmp; if (!id) return; var item = { type: 'BLOCK', id: id, name: name, displayName: block.attributes.displayName, text: '[' + block.tag + '] ' + id, value: id, order: 'b_' + block.tag + '_' + id, bTag: block.tag, pinList: Object.keys(clazz.prototype.pinHandlers).map(function (name) { return {text: name, value: name}; }), clazz: AssemblerInstance.classes['BLOCK'][block.tag] } pinCmp = function (a, b) { var av = (IndexedPropertyNames[a.name] || 100); if (clazz.prototype.pinHandlers[a.name] && clazz.prototype.pinHandlers[a.name].get && clazz.prototype.pinHandlers[a.name].receives) { av /= 1000; } var bv = (IndexedPropertyNames[b.name] || 100); if (clazz.prototype.pinHandlers[b.name] && clazz.prototype.pinHandlers[b.name].get && clazz.prototype.pinHandlers[b.name].receives) { bv /= 1000; } return av - bv; } item.inputPins = Object.keys(clazz.prototype.pinHandlers).map(function (pinName) { if (clazz.prototype.pinHandlers[pinName].receives) return { name: pinName } else return null; }).filter(function (it) { return !!it; }); if (block.tag === 'function' && block.attributes && block.attributes.args) { item.inputPins.unshift.apply(item.inputPins, block.attributes.args.map(function (it) { return {name: it}; })); } item.inputPins.sort(pinCmp); item.outputPins = Object.keys(clazz.prototype.pinHandlers).map(function (pinName) { if (clazz.prototype.pinHandlers[pinName].get) return { name: pinName } else return null; }).filter(function (it) { return !!it; }); item.outputPins.sort(pinCmp); list.push(item); }); list.sort(function (a, b) { a = a.order; b = b.order; if (a === b) return 0; if (a < b) return -1; return 1; }); this._pointListCache.list = list; this._pointListCache.dict = list.reduce(function (ac, cr) { ac[cr.value] = cr; return ac; }, {}); this._pointListCache.byId = list.reduce(function (ac, cr) { ac[cr.id] = cr; return ac; }, {}); this._pointListCache.byName = list.reduce(function (ac, cr) { ac[cr.name] = cr; return ac; }, {}); return this._pointListCache; }; CircuitDiagramEditor.prototype.getGridData = function () { var res = { nodes: {}, lines: {} }; var nodeElt; var nodeData; for (var i in this.$nodes) { nodeElt = this.$nodes[i]; nodeData = { x: nodeElt.x / 25, y: nodeElt.y / 25, width: Math.ceil(nodeElt.rect.width / 25), height: Math.ceil(nodeElt.rect.height / 25), inputPos: nodeElt.inputPins.reduce(function (ac, cr, idx) { var pos = nodeElt.pinHolders.in[cr.name].pos; ac[cr.name] = {x: pos.x / 25, y: pos.y / 25}; return ac; }, {}), outputPos: nodeElt.outputPins.reduce(function (ac, cr, idx) { var pos = nodeElt.pinHolders.out[cr.name].pos; ac[cr.name] = {x: pos.x / 25, y: pos.y / 25}; return ac; }, {}), } res.nodes[i] = nodeData; } var lineElt; for (var j in this.$lines) { lineElt = this.$lines[j]; res.lines[j] = { uId: lineElt.uId, vId: lineElt.vId, uPin: lineElt.uPin, vPin: lineElt.vPin }; } return res; }; CircuitDiagramEditor.prototype.autoAlignPosition = function () { var self = this; var token = LoadingCubeModal.show(); this.optimizer.findBeautyGrid(this.getGridData(), 3000) .then(function (res) { LoadingCubeModal.close(token); if (res.noChange) return; var positions = res.positions; var nodeElt; var pos; for (var i in positions) { nodeElt = self.$nodes[i]; if (!nodeElt) continue; pos = positions[i]; if (!pos) continue; nodeElt.x = pos.x * 25; nodeElt.y = pos.y * 25; } for (var j in self.$lines) { self.updateLinePosition(j); } self.notifyUnsaved(); }).catch(function () { LoadingCubeModal.close(token); }); }; CircuitDiagramEditor.prototype.getCmdDescriptor = function (name) { var descriptor = CircuitDiagramEditorCmdDescriptors[name]; var res = Object.assign({ type: 'trigger', desc: 'command: ' + name, icon: 'span.mdi.mdi-apple-keyboard-command' }, descriptor); return res; }; CircuitDiagramEditor.prototype.getCmdGroupTree = function () { var tree = CircuitDiagramEditorCmdTree; return tree; }; export default CircuitDiagramEditor;