VaKeR CYBER ARMY
Logo of a company Server : Apache/2.4.41 (Ubuntu)
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 :  /var/www/html/libs/absol-form/js/ciruiteditor/diagrameditor/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : //var/www/html/libs/absol-form/js/ciruiteditor/diagrameditor/CircuitDiagramEditor.js
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;

VaKeR 2022