diff options
Diffstat (limited to 'index.html')
-rw-r--r-- | index.html | 3391 |
1 files changed, 3391 insertions, 0 deletions
diff --git a/index.html b/index.html new file mode 100644 index 0000000..f61f726 --- /dev/null +++ b/index.html @@ -0,0 +1,3391 @@ +<html> + +<head> + <meta content="text/html;charset=utf-8" http-equiv="Content-Type"> + <meta content="utf-8" http-equiv="encoding"> + <title>Xcos</title> + + <!-- Loads and initializes the library --> + <script type="text/javascript" src="jquery/jquery-1.8.2.js"></script> + <script type="text/javascript" src="mxClient.min.js"></script> + <script type="text/javascript" src="jquery/farbtastic.js"></script> + + <link rel="stylesheet" href="jquery/farbtastic.css" type="text/css" /> + <link rel="stylesheet" href="jquery/jquery-ui.css"> + + <script type="text/javascript" src="details.js"></script> + <script type="text/javascript" src="setup.js"></script> + <script type="text/javascript" src="combined.js"></script> + <script type="text/javascript" src="orientation.js"></script> + <script type="text/javascript" src="highcharts/highcharts.js"></script> + <script type="text/javascript" src="Queue.js"></script> + <script type="text/javascript" src="chart.js"></script> + + <script type="text/javascript"> + // Stores edgeState for every recently created edge in updateFixedTerminalPoint() function + var edgeState = {}; + + function main(container, outline, toolbar, sidebar, status) { + // Checks if the browser is supported + if (!mxClient.isBrowserSupported()) { + // Displays an error message if the browser is not supported. + mxUtils.error('Browser is not supported!', 200, false); + } else { + // If connect preview is not moved away then getCellAt is used to detect the cell under + // the mouse if the mouse is over the preview shape in IE (no event transparency), ie. + // the built-in hit-detection of the HTML document will not be used in this case. + mxConnectionHandler.prototype.movePreviewAway = false; + mxConnectionHandler.prototype.waypointsEnabled = true; + mxGraph.prototype.resetEdgesOnConnect = false; + + // Enables guides + mxGraphHandler.prototype.guidesEnabled = true; + + // Alt disables guides + mxGuide.prototype.isEnabledForEvent = function(evt) { + return !mxEvent.isAltDown(evt); + }; + + // Enables snapping waypoints to terminals + mxEdgeHandler.prototype.snapToTerminals = true; + + // Assigns some global constants for general behaviour, eg. minimum + // size (in pixels) of the active region for triggering creation of + // new connections, the portion (100%) of the cell area to be used + // for triggering new connections, as well as some fading options for + // windows and the rubberband selection. + mxConstants.MIN_HOTSPOT_SIZE = 16; + mxConstants.DEFAULT_HOTSPOT = 1; + + // Workaround for Internet Explorer ignoring certain CSS directives + if (mxClient.IS_QUIRKS) { + document.body.style.overflow = 'hidden'; + new mxDivResizer(container); + new mxDivResizer(outline); + new mxDivResizer(toolbar); + new mxDivResizer(sidebar); + new mxDivResizer(status); + } + + // Creates a wrapper editor with a graph inside the given container. + // The editor is used to create certain functionality for the + // graph, such as the rubberband selection, but most parts + // of the UI are custom in this example. + var editor = new mxEditor(); + var graph = editor.graph; + var model = graph.getModel(); + + /* + Maverick + The following variable 'diagRoot' serves as the root element for the entire + diagram. + */ + var diagRoot = new XcosDiagram(null, model, null); + graph.setPanning(true); + graph.setConnectable(true); + graph.setConnectableEdges(true); + graph.setDisconnectOnMove(false); + graph.foldingEnabled = false; + + // Disable highlight of cells when dragging from toolbar + graph.setDropEnabled(false); + + // Centers the port icon on the target port + graph.connectionHandler.targetConnectImage = true; + + // Does not allow dangling edges + graph.setAllowDanglingEdges(false); + + // Sets the graph container and configures the editor + editor.setGraphContainer(container); + + // Disables built-in context menu + mxEvent.disableContextMenu(document.body); + + // Configures automatic expand on mouseover + graph.panningHandler.autoExpand = true; + + /* + @jiteshjha, @pooja + Overrides mxGraphModel.getStyle to return a specific style + for edges that reflects their target terminal. + */ + + graph.model.getStyle = function(cell) { + var style = null; + if (cell != null) { + // Get style for the recently created mxCell. + style = mxGraphModel.prototype.getStyle.apply(this, arguments); + // If the mxCell is an edge and if it's a fully formed edge + if (this.isEdge(cell) && cell.source != null) { + var target = this.getTerminal(cell, false); + if (target != null) { + /* cell.name attribute defines the link name + so that it can be parsed in the XML during + XSLT transformation. + */ + var cellSource = cell.source; + while (cellSource.isEdge() == true) { + cellSource = cellSource.source; + } + if (cellSource.value == "ExplicitOutputPort" || cellSource.value == "ExplicitInputPort") { + if (style == null) { + style = 'ExplicitLink' + ';'; + } + cell.name = "ExplicitLink"; + } else if (cellSource.value == "ImplicitOutputPort" || cellSource.value == "ImplicitInputPort") { + if (style == null) { + style = 'ImplicitLink' + ';'; + } + cell.name = "ImplicitLink"; + } else if (cellSource.value == "CommandPort" || cellSource.value == "ControlPort") { + if (style == null) { + style = 'CommandControlLink' + ';'; + } + cell.name = "CommandControlLink"; + } + } + } + } + return style; + }; + + + // Creates a right-click menu + graph.panningHandler.factoryMethod = function(menu, cell, evt) { + + if (cell != null) { + + if (cell.value == "ExplicitInputPort" || cell.value == "ExplicitOutputPort" || cell.value == "CommandPort" || cell.value == "ControlPort") { + + } else if (cell.isEdge() == true) // @ToDo: Pooja: Different edge value cases. + { + + menu.addItem('Delete', 'images/delete2.png', function() { + editor.execute('deleteBlock'); + }); + var edgeformat = menu.addItem('Format', null, null); + + menu.addItem('Border Color', 'images/draw-brush.png', function() { + showColorWheel(graph, cell, 'edgeStrokeColor'); + + }, edgeformat); + menu.addItem('Text and Text Font', 'images/edit.png', function() { + showTextEditWindow(graph, cell); + }, edgeformat); + menu.addItem('Text Color', 'images/edit.png', function() { + showColorWheel(graph, cell, 'edgeTextColor'); + }, edgeformat); + + } else { + menu.addItem('Block Parameters...', 'images/gear.gif', function() { + showPropertiesWindow(graph, cell); + }); + + menu.addItem('Cut', 'images/cut.png', function() { + editor.execute('cut'); + }); + menu.addItem('Copy', 'images/copy.png', function() { + editor.execute('copy'); + }); + menu.addItem('Delete', 'images/delete2.png', function() { + editor.execute('delete'); + }); + + menu.addItem('Selection to superblock', 'images/superblock.png', function() { + // @ToDo: Functionality to be put. + }); + var formatMenu = menu.addItem('Format', null, null); + menu.addItem('Rotate', 'images/rotate.png', function() { + editor.execute('rotateCustom'); + }, formatMenu); + menu.addItem('Flip', 'images/flip.png', function() { + editor.execute('flipCustom'); + }, formatMenu); + menu.addItem('Mirror', 'images/mirror.png', function() { + editor.execute('mirrorCustom'); + }, formatMenu); + menu.addItem('Border Color', 'images/draw-brush.png', function() { + showColorWheel(graph, cell, 'vertexStrokeColor'); + }, formatMenu); + menu.addItem('Fill Color', 'images/edit.png', function() { + showColorWheel(graph, cell, 'vertexFillColor'); + }, formatMenu); + menu.addItem('Details', null, function() { + // @ToDo: Functionality to be put. + }); + } + } else { + menu.addItem('Undo', 'images/undo.png', function() { + editor.execute('undo'); + }); + menu.addItem('Redo', 'images/redo.png', function() { + editor.execute('redo'); + }); + menu.addItem('Paste', 'images/paste.png', function() { + editor.execute('paste'); + }); + + menu.addItem('Select all', 'images/selectall.png', function() { + editor.execute('selectAll'); + }); + + /* + Maverick + Added one more parameter to the setContext function. + */ + menu.addItem('Set Context', null, function() { + showSetContext(graph, diagRoot); + }); + + /* + Maverick + Added one more parameter to the setContext function. + */ + menu.addItem('Setup', 'images/setup.png', function() { + showSetupWindow(graph, diagRoot); + }); + + + menu.addItem('Zoom In', 'images/zoom_in.png', function() { + editor.execute('zoomIn'); + }); + menu.addItem('Zoom Out', 'images/zoom_out.png', function() { + editor.execute('zoomOut'); + }); + menu.addItem('Diagram background...', null, function() { + showColorWheel(graph, cell, 'bgColor'); + }); + } + + }; + + //var config = mxUtils.load('config/editor-commons.xml').getDocumentElement(); + var config = mxUtils.load('config/keyhandler-commons.xml').getDocumentElement(); + editor.configure(config); + + graph.isCellSelectable = function(cell) { + if (cell.isConnectable() == true && cell.isEdge() == false) { + return false; + } + return true; + }; + + graph.resizeCell = function(cell, bounds, recurse) { + if (cell.getStyle() == 'Split') { + return null; + } else { + return mxGraph.prototype.resizeCell.apply(this, arguments); + } + } + + /* + For a new edge on the graph, check if that edge satisfies one of the port constraints. + Possible edge cases with source & target : + 1) Source : Port, Target : Port + 2) Source : Edge, Target : Port + 3) Source : Port, Target : Edge + 4) Source : Edge, Target : Edge + */ + graph.addEdge = function(edge, parent, source, target, index) { + + if (source.isEdge() == true && target.isEdge() == true) { + alert("Illegal connection! - Link to link connection"); + return null; + } + + // If the edge is legit, return the edge. + if (source.isEdge() == true) { + graph.getModel().beginUpdate(); + try { + var edgeSource = source; + + // While the source of the edge is an edge, find the final port + while (edgeSource.isEdge() == true) { + edgeSource = edgeSource.source; + } + + // If the edge violates any of the port constraints, don't create the edge + if (edgeSource.value == "ExplicitOutputPort" && target.value != "ExplicitInputPort") { + alert("Explicit data output port must be connected to explicit data input port"); + return null; + } else if (edgeSource.value == "ExplicitInputPort" && target.value != "ExplicitOutputPort") { + alert("Explicit data input port must be connected to explicit data output port"); + return null; + } else if (edgeSource.value == "ImplicitOutputPort" && target.value != "ImplicitInputPort") { + alert("Implicit data output port must be connected to implicit data input port"); + return null; + } else if (edgeSource.value == "ImplicitInputPort" && target.value != "ImplicitOutputPort") { + alert("Implicit data input port must be connected to implicit data output port"); + return null; + } else if (edgeSource.value == "CommandPort" && target.value != "ControlPort") { + alert("Command port must be connected to control port"); + return null; + } else if (edgeSource.value == "ControlPort" && target.value != "CommandPort") { + alert("Control port must be connected to command port"); + return null; + } + + // Create the splitBlock + // (x-5, y-5.5) is the offset to correct the position of split-block + var cell = graph.insertVertex(graph.getDefaultParent(), null, '', source.sourcePoint.x - 5, source.sourcePoint.y - 5.5, 10, 10, 'Split', false); + + + + // Get the source state + var sourceState = graph.view.getState(source); + var waypoints = source.waypoints; + var waypoints1 = []; + + // Add the absolute points for source edge to waypoints variable + for (i in sourceState.absolutePoints) { + waypoints1.push(sourceState.absolutePoints[i]); + } + + // Remove source and target points + waypoints1.shift(); + waypoints1.pop(); + + // Store the waypoints to the source edge + waypoints = waypoints1; + + // Find the index in the waypoints nearest to the split-block + var seg = mxUtils.findNearestSegment(sourceState, source.sourcePoint.x, source.sourcePoint.y); + var sourceTarget = source.target; + + // Set the type of ports for split-block according to type of source edge + if (edgeSource.value == 'ExplicitOutputPort') { + createPorts(graph, cell, ['E'], [], ['E'], ['E']); + } else if (edgeSource.value == 'ImplicitOutputPort') { + createPorts(graph, cell, ['I'], [], ['I', 'I'], []); + } else { + createPorts(graph, cell, ['CONTROL'], [], ['COMMAND', 'COMMAND'], []); + } + + // Source edge is replaced with first edge and futureSource edges + cell.name = 'SPLIT_f'; + + // Hide all the ports of a split-block + cell.getChildAt(0).setVisible(false); + cell.getChildAt(1).setVisible(false); + cell.getChildAt(2).setVisible(false); + + // Remove the current source + graph.removeCells([source], true); + + /* + * If there are any waypoints, divide them for the two newly created edges. + * The two newly created edges are inherited from the source edge + */ + if (waypoints != null) { + var waypoints1 = []; + for (var i = 0; i < seg; i++) { + waypoints1.push(waypoints[i]); + } + + var waypoints2 = []; + for (var i = seg; i < waypoints.length; i++) { + waypoints2.push(waypoints[i]); + } + } + + // Find the waypoints of the current edge, and set the waypoints for the new thirdEdge + var waypoints3 = edgeState.absolutePoints; + if (waypoints3 != null && waypoints3.length > 1) { + // Remove last absolute point + waypoints3.pop(); + } + + // Create three edges associated with the split-block + var firstEdge = createEdgeObject(graph, cell.getChildAt(1), sourceTarget, waypoints2); + var thirdEdge = createEdgeObject(graph, cell.getChildAt(2), target, waypoints3); + var futureSource = createEdgeObject(graph, source.source, cell.getChildAt(0), waypoints1); + + // Set the newly made futureSource as the source + source = futureSource; + + // Connectable for the ports and the split-block should be false + cell.getChildAt(0).setConnectable(false); + cell.getChildAt(1).setConnectable(false); + cell.getChildAt(2).setConnectable(false); + cell.setConnectable(false); + + // Get the parent of the splitBlock + var parent = graph.model.getParent(cell); + + graph.model.beginUpdate(); + try { + /* + * Adds the split-block to the parent at the last index + * Enables split-block to appear over it's associated edges + */ + graph.model.add(parent, cell, graph.model.getChildCount(parent) - 1); + } finally { + graph.model.endUpdate(); + } + + graph.refresh(); + } finally { + graph.getModel().endUpdate(); + } + + /* + * Remove the current edge, as we have already created + * thirdEdge as it's replacement, to enable waypoints. + */ + return null; + } + + // If the edge is legit, return the edge. + if (target.isEdge() == true) { + graph.getModel().beginUpdate(); + try { + var edgeSource = target; + + // While the source of the edge is an edge, find the final port + while (edgeSource.isEdge() == true) { + edgeSource = edgeSource.source; + } + + // If the edge violates any of the port constraints, don't create the edge + if (source.value == "ExplicitOutputPort" && edgeSource.value != "ExplicitInputPort") { + alert("Explicit data output port must be connected to explicit data input port"); + return null; + } else if (source.value == "ExplicitInputPort" && edgeSource.value != "ExplicitOutputPort") { + alert("Explicit data input port must be connected to explicit data output port"); + return null; + } else if (source.value == "ImplicitOutputPort" && edgeSource.value != "ImplicitInputPort") { + alert("Implicit data output port must be connected to implicit data input port"); + return null; + } else if (source.value == "ImplicitInputPort" && edgeSource.value != "ImplicitOutputPort") { + alert("Implicit data input port must be connected to implicit data output port"); + return null; + } else if (source.value == "CommandPort" && edgeSource.value != "ControlPort") { + alert("Command port must be connected to control port"); + return null; + } else if (source.value == "ControlPort" && edgeSource.value != "CommandPort") { + alert("Control port must be connected to command port"); + return null; + } + + // Create the splitBlock + // (x-5, y-5.5) is the offset to correct the position of split-block + var cell = graph.insertVertex(graph.getDefaultParent(), null, '', target.sourcePoint.x - 5, target.sourcePoint.y - 5, 10, 10, 'Split', false); + + // Get the source state + var sourceState = graph.view.getState(target); + var waypoints = target.waypoints; + var waypoints1 = []; + + // Add the absolute points for source edge to waypoints variable + for (i in sourceState.absolutePoints) { + waypoints1.push(sourceState.absolutePoints[i]); + } + waypoints1.shift(); + waypoints1.pop(); + waypoints = waypoints1; + + // Find the index in the waypoints nearest to the split-block + var seg = mxUtils.findNearestSegment(sourceState, target.sourcePoint.x, target.sourcePoint.y); + var sourceTarget = target.target; + + if (edgeSource.value == 'ExplicitOutputPort') { + createPorts(graph, cell, ['E'], [], ['E'], ['E']); + + } else if (edgeSource.value == 'ImplicitOutputPort') { + createPorts(graph, cell, ['I'], [], ['I', 'I'], []); + } else { + createPorts(graph, cell, ['CONTROL'], [], ['COMMAND', 'COMMAND'], []); + } + + // Source edge is replaced with first edge and futureSource edges + cell.name = 'SPLIT_f'; + + // Hide all the ports of a split-block + cell.getChildAt(0).setVisible(false); + cell.getChildAt(1).setVisible(false); + cell.getChildAt(2).setVisible(false); + + // Remove the current source + graph.removeCells([target], true); + + /* + * If there are any waypoints, divide them for the two newly created edges. + * The two newly created edges are inherited from the source edge + */ + if (waypoints != null) { + var waypoints1 = []; + for (var i = 0; i < seg; i++) { + waypoints1.push(waypoints[i]); + } + + var waypoints2 = []; + for (var i = seg; i < waypoints.length; i++) { + waypoints2.push(waypoints[i]); + } + } + + // Find the waypoints of the current edge, and set the waypoints for the new thirdEdge + var waypoints3 = edgeState.absolutePoints; + if (waypoints3 != null && waypoints3.length > 1) { + waypoints3.pop(); + } + waypoints3.reverse(); + + // Create three edges associated with the split-block + var firstEdge = createEdgeObject(graph, cell.getChildAt(1), sourceTarget, waypoints2); + var thirdEdge = createEdgeObject(graph, cell.getChildAt(2), source, waypoints3); + var futureSource = createEdgeObject(graph, target.source, cell.getChildAt(0), waypoints1); + + // Set the newly made futureSource as the source + target = futureSource; + + // Connectable for the ports and the split-block should be false + cell.getChildAt(0).setConnectable(false); + cell.getChildAt(1).setConnectable(false); + cell.getChildAt(2).setConnectable(false); + cell.setConnectable(false); + + // Get the parent of the splitBlock + var parent = graph.model.getParent(cell); + + graph.model.beginUpdate(); + try { + /* + * Adds the split-block to the parent at the last index + * Enables split-block to appear over it's associated edges + */ + graph.model.add(parent, cell, graph.model.getChildCount(parent) - 1); + } finally { + graph.model.endUpdate(); + } + + graph.refresh(); + } finally { + graph.getModel().endUpdate(); + } + + /* + * Remove the current edge, as we have already created + * thirdEdge as it's replacement, to enable waypoints. + */ + return null; + } + + // If the newly created edge is related to a splitBlock, make the edge. + if (source.parent.name == 'SPLIT_f' || target.parent.name == 'SPLIT_f') { + return mxGraph.prototype.addEdge.apply(this, arguments); + } + + var edgeSource = source; + + // If the source of the edge is also an edge, find the port. + while (edgeSource.isEdge() == true) { + edgeSource = edgeSource.source; + } + + // For port-to-port edges with port constraint violations, don't create that edge + if (source.getEdgeCount() > 0 || target.getEdgeCount() > 0) { + alert("Port is already connected, please select an please select an unconnected port or a valid link"); + } else if (edgeSource.value == "ExplicitOutputPort" && target.value != "ExplicitInputPort") { + alert("Explicit data output port must be connected to explicit data input port"); + } else if (edgeSource.value == "ExplicitInputPort" && target.value != "ExplicitOutputPort") { + alert("Explicit data input port must be connected to explicit data output port"); + } else if (edgeSource.value == "ImplicitOutputPort" && target.value != "ImplicitInputPort") { + alert("Implicit data output port must be connected to implicit data input port"); + } else if (edgeSource.value == "ImplicitInputPort" && target.value != "ImplicitOutputPort") { + alert("Implicit data input port must be connected to implicit data output port"); + } else if (edgeSource.value == "CommandPort" && target.value != "ControlPort") { + alert("Command port must be connected to control port"); + } else if (edgeSource.value == "ControlPort" && target.value != "CommandPort") { + alert("Control port must be connected to command port"); + } else { + + /* + * For reverse edges, (that is, edges from input port to outport) : + * If the source is input port, and target is an output port + * NOTE: Manipulation of source object and target object + * with respect to current edge is not possible, + * as mxGraph.prototype.addEdge(@parameters) function is + * called just before the creation of the edge. + * Hence, the following code creates a identical new edge + * to replace the current edge. + */ + + if ((source.value.indexOf('Input') != -1 && target.value.indexOf('Output') != -1) || + (target.value == 'CommandPort' && source.value == 'ControlPort')) { + + // Get points for the current edge from the global edgeState object + var waypoints = edgeState.absolutePoints; + + // Reverse waypoint array + waypoints.reverse(); + + // Create a new edge + var newEdge = createEdgeObject(graph, target, source, waypoints); + + // Return null for the current edge, + + /* + * Return null for the current edge, + * since we have created a new edge above to replace it + */ + return null; + } + // If the edge is legit, return the edge. + return mxGraph.prototype.addEdge.apply(this, arguments); + } + return null; + } + + // Shows a "modal" window when double clicking a vertex. + graph.dblClick = function(evt, cell) { + // Do not fire a DOUBLE_CLICK event here as mxEditor will + // consume the event and start the in-place editor. + if (this.isEnabled() && + !mxEvent.isConsumed(evt) && + cell != null && + this.isCellEditable(cell)) { + if (!this.isHtmlLabel(cell)) { + this.startEditingAtCell(cell); + } else { + /* + var content = document.createElement('div'); + content.innerHTML = this.convertValueToString(cell); + showModalWindow(this, 'Properties', content, 400, 300); + */ + if (cell.isVertex() == true) { + showPropertiesWindow(graph, cell); + } + } + } + + // Disables any default behaviour for the double click + mxEvent.consume(evt); + }; + + // Returns a shorter label if the cell is collapsed and no + // label for expanded groups + graph.getLabel = function(cell) { + var tmp = mxGraph.prototype.getLabel.apply(this, arguments); // "supercall" + if (this.isCellLocked(cell)) { + // Returns an empty label but makes sure an HTML + // element is created for the label (for event + // processing wrt the parent label) + return ''; + } else if (this.isCellCollapsed(cell)) { + var index = tmp.indexOf('</h1>'); + if (index > 0) { + tmp = tmp.substring(0, index + 5); + } + } + return tmp; + } + + // Disables HTML labels for swimlanes to avoid conflict + // for the event processing on the child cells. HTML + // labels consume events before underlying cells get the + // chance to process those events. + // + // NOTE: Use of HTML labels is only recommended if the specific + // features of such labels are required, such as special label + // styles or interactive form fields. Otherwise non-HTML labels + // should be used by not overidding the following function. + // See also: configureStylesheet. + graph.isHtmlLabel = function(cell) { + return !this.isSwimlane(cell); + } + + graph.getTooltipForCell = function(cell) { + var text = null; + if (cell.isVertex() == true && cell.isConnectable() == false) { + var name = cell.value.getAttribute('blockElementName'); + var cellvar = cell.blockInstance.instance.details(); + + // If cell is a block or ports + if (cell.source == null && cell.target == null) { + if (cell.connectable) { // Cell is a Port + // @ToDo: Port Number + text = 'Style : ' + cell.style + "\n"; + } else { //Cell is a block + // @ToDo: Block Name, Simulation, Flip, Mirror + // @ToDo: Number of Input, Output, Control, Command Ports + var inputPort, outputPort, controlPort, commandPort; + if (cellvar.model.in.height == null) { + inputPort = 0; + } else { + inputPort = cellvar.model.in.height; + } + if (cellvar.model.out.height == null) { + outputPort = 0; + } else { + outputPort = cellvar.model.out.height; + } + if (cellvar.model.evtin.height == null) { + controlPort = 0; + } else { + controlPort = cellvar.model.evtin.height; + } + if (cellvar.model.evtout.height == null) { + commandPort = 0; + } else { + commandPort = cellvar.model.evtout.height; + } + + var flip = false, + mirror = false; + var style = cell.style; + var styleObject = styleToObject(style); + if (styleObject['stencilFlipV'] == null) { + flip = false; + } else { + + if (styleObject['stencilFlipV'] == 0) { + flip = false; + } else { + flip = true; + } + + } + if (styleObject['stencilFlipH'] == null) { + mirror = false; + } else { + + if (styleObject['stencilFlipH'] == 0) { + mirror = false; + } else { + mirror = true; + } + + } + style = objectToStyle(styleObject); + var geometry = cell.getGeometry(); + text = 'Block Name : ' + cell.value.getAttribute('blockElementName') + "\n" + + 'Simulation : ' + cell.value.getAttribute('simulationFunctionName') + "\n" + + 'UID : ' + cell.id + "\n" + + 'Style : ' + cell.style + "\n" + + 'Flip : ' + flip + "\n" + + 'Mirror : ' + mirror + "\n" + + 'Input Ports : ' + inputPort + "\n" + + 'Output Ports : ' + outputPort + "\n" + + 'Control Ports : ' + controlPort + "\n" + + 'Command Ports : ' + commandPort + "\n" + + 'x : ' + geometry.x + "\n" + + 'y : ' + geometry.y + "\n" + + 'w : ' + geometry.width + "\n" + + 'h : ' + geometry.height + "\n"; + } + } + } + return text; + }; + + // Create XML tags! + // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + // https://jgraph.github.io/mxgraph/docs/js-api/files/model/mxCell-js.html + // Uncomment this block to see XML tags work + graph.convertValueToString = function(cell) { + + if (mxUtils.isNode(cell.value)) { + var stylesheet = graph.getStylesheet(); + var attribute = cell.value.getAttribute('style'); + if (attribute == null) { + attribute = cell.value.getAttribute('interfaceFunctionName'); + } + var style = stylesheet.styles[attribute]; + var displayedLabel = style['displayedLabel']; + if (displayedLabel != null) { + var displayParameter = cell.blockInstance.instance.displayParameter; + for (i in displayParameter) { + displayedLabel = displayedLabel.replace("%s", displayParameter[i].toString()); + } + return displayedLabel; + } else { + return cell.getAttribute('label', ''); + } + } + }; + + var cellLabelChanged = graph.cellLabelChanged; + graph.cellLabelChanged = function(cell, newValue, autoSize) { + if (mxUtils.isNode(cell.value)) { + // Clones the value for correct undo/redo + var elt = cell.value.cloneNode(true); + elt.setAttribute('label', newValue); + newValue = elt; + } + + cellLabelChanged.apply(this, arguments); + }; + + // Enables new connections + graph.setConnectable(true); + + // Adds all required styles to the graph (see below) + configureStylesheet(graph); + + // Adds sidebar icons. + addIcons(graph, sidebar); + + // Creates a new DIV that is used as a toolbar and adds + // toolbar buttons. + var spacer = document.createElement('div'); + spacer.style.display = 'inline'; + spacer.style.padding = '8px'; + + // Defines a new export action + editor.addAction('toggle', function(editor, cell) { + var toggle = document.getElementById("toggleBlocks"); + var button = document.getElementById("toggle"); + toggle.click(); + button.innerHTML = ''; + if (toggle.innerHTML == 'Expand All') { + createButtonImage(button, 'images/navigate_plus.png'); + } else if (toggle.innerHTML == 'Collapse All') { + createButtonImage(button, 'images/navigate_minus.png'); + } + var titleName = document.createTextNode(toggle.innerHTML); + button.appendChild(titleName); + }); + + /* + * @jiteshjha, @pooja + * rotateCustom(@parameters) is defined in 'orientation.js' + */ + editor.addAction('rotateCustom', function(editor, cell) { + rotateCustom(editor, graph, cell); + }); + + /* + * @jiteshjha, @pooja + * flipCustom(@parameters) is defined in 'orientation.js' + */ + editor.addAction('flipCustom', function(editor, cell) { + flipCustom(editor, graph, cell); + }); + + /* + * @jiteshjha, @pooja + * mirrorCustom(@parameters) is defined in 'orientation.js' + */ + editor.addAction('mirrorCustom', function(editor, cell) { + mirrorCustom(editor, graph, cell); + }); + + // @jiteshjha, @pooja + /* + On selection and deletion of any block, 'deleteBlock' + function deletes all the associated edges with that block. + Used Preorder traversal for edges. + */ + editor.addAction('deleteBlock', function(editor, cell) { + graph.getModel().beginUpdate(); + try { + // getEdgeId(@edgeObject) finds all the associated edges and split-block, and deletes them + function getEdgeId(edgeObject) { + + var cellStack = []; + if (edgeObject != null && edgeObject.isEdge() == true) { + cellStack.push(edgeObject); + while (cellStack.length != 0) { + var tempEdgeObject = cellStack.pop(); + if (tempEdgeObject.edge == true && (cells.indexOf(tempEdgeObject) == -1)) { + cells.push(tempEdgeObject); + } + + // If the edge is associated with a split-block(source is a split-block) + if (tempEdgeObject.source.parent.name == "SPLIT_f") { + if (tempEdgeObject.source == tempEdgeObject.source.parent.getChildAt(1)) { + + var sourceEdge = tempEdgeObject.source.parent.getChildAt(0).getEdgeAt(0); + var target = tempEdgeObject.source.parent.getChildAt(2).getEdgeAt(0).target; + + // If the state of the edge is not null + if (graph.view.getState(sourceEdge) != null) { + + // Find waypoints for the first edge related to split-block + var waypoints1 = graph.view.getState(sourceEdge).absolutePoints; + + // Find the waypoints for the second edge related to split-block + var waypoints2 = graph.view.getState(tempEdgeObject.source.parent.getChildAt(2).getEdgeAt(0)).absolutePoints; + waypoints2.shift(); + for (i in waypoints2) { + waypoints1.push(waypoints2[i]); + } + var geometry = graph.getModel().getGeometry(sourceEdge); + var cloneGeometry = geometry.clone(); + + cloneGeometry.points = waypoints1; + graph.getModel().setGeometry(sourceEdge, cloneGeometry); + graph.refresh(); + + // Shift the target for the first edge related to splitBlock + graph.getModel().setTerminal(sourceEdge, target, false); + } + cells.push(tempEdgeObject.source.parent); + } else { + var sourceEdge = tempEdgeObject.source.parent.getChildAt(0).getEdgeAt(0); + var target = tempEdgeObject.source.parent.getChildAt(1).getEdgeAt(0).target; + + // If the state of the edge is not null + if (graph.view.getState(sourceEdge) != null) { + + // Find waypoints for the first edge related to split-block + var waypoints1 = graph.view.getState(sourceEdge).absolutePoints; + + // Find the waypoints for the second edge related to split-block + var waypoints2 = graph.view.getState(tempEdgeObject.source.parent.getChildAt(1).getEdgeAt(0)).absolutePoints; + waypoints1.pop(); + waypoints2.shift(); + for (i in waypoints2) { + waypoints1.push(waypoints2[i]); + } + var geometry = graph.getModel().getGeometry(sourceEdge); + var cloneGeometry = geometry.clone(); + + cloneGeometry.points = waypoints1; + graph.getModel().setGeometry(sourceEdge, cloneGeometry); + graph.refresh(); + + // Shift the target for the first edge related to splitBlock + graph.getModel().setTerminal(sourceEdge, target, false); + } + cells.push(tempEdgeObject.source.parent); + } + + } + + // If the edge is associated with a split-block(target is a split-block) + if (tempEdgeObject.target.parent.name == "SPLIT_f") { + if (cells.indexOf(tempEdgeObject.target.parent) == -1) { + cells.push(tempEdgeObject.target.parent); + } + cellStack.push(tempEdgeObject.target.parent.getChildAt(1).getEdgeAt(0)); + cellStack.push(tempEdgeObject.target.parent.getChildAt(2).getEdgeAt(0)); + } + } + } + } + + var cells = []; + + // Get all selected cells + var selectionCells = graph.getSelectionCells(); + + // For each cell in the selection + for (var k = 0; k < selectionCells.length; k++) { + + // If the cell is an edge, directly call getEdgeId(@parameter) for deletion + if (selectionCells[k].isEdge() == true) { + getEdgeId(selectionCells[k]); + } + + // If the cell is a vertex, select the cell + else { + var portCount = selectionCells[k].getChildCount(); + /* + Maverick, Adhitya + switch-case statements to handle the ordering of following blocks. + The variables window.inBitMap and window.outBitMap are defined in + the file 'dependencies.js'. + */ + switch(selectionCells[k].value.nodeName){ + case 'ImplicitInBlock': + case 'ExplicitInBlock': + window.inBitMap = window.inBitMap.replaceAt(parseInt(selectionCells[k].value.getAttribute('ordering'))-1,'0') ; + break; + case 'ImplicitOutBlock': + case 'ExplicitOutBlock': + window.outBitMap = window.outBitMap.replaceAt(parseInt(selectionCells[k].value.getAttribute('ordering'))-1,'0') ; + break; + } + cells.push(selectionCells[k]); + for (var i = 0; i < portCount; i++) { + var edgeCount = selectionCells[k].getChildAt(i).getEdgeCount(); + if (edgeCount != 0) { + + /* + * For every edge associated with the current selected cell, + * call the getEdgeId(@parameter), parameter is an edgeObject for deletion + */ + + for (var j = 0; j < edgeCount; j++) { + var edgeObject = selectionCells[k].getChildAt(i).getEdgeAt(j); + getEdgeId(edgeObject); + } + } + } + } + } + graph.removeCells(cells, true); + } finally { + graph.getModel().endUpdate(); + } + + }); + + addToolbarButton(editor, toolbar, 'toggle', 'Expand All', 'images/navigate_plus.png'); + toolbar.appendChild(spacer.cloneNode(true)); + + addToolbarButton(editor, toolbar, 'cut', 'Cut', 'images/cut.png'); + addToolbarButton(editor, toolbar, 'copy', 'Copy', 'images/copy.png'); + addToolbarButton(editor, toolbar, 'paste', 'Paste', 'images/paste.png'); + + toolbar.appendChild(spacer.cloneNode(true)); + + addToolbarButton(editor, toolbar, 'deleteBlock', 'Delete', 'images/delete2.png'); + addToolbarButton(editor, toolbar, 'undo', '', 'images/undo.png'); + addToolbarButton(editor, toolbar, 'redo', '', 'images/redo.png'); + toolbar.appendChild(spacer.cloneNode(true)); + + addToolbarButton(editor, toolbar, 'show', 'Show', 'images/camera.png'); + addToolbarButton(editor, toolbar, 'print', 'Print', 'images/printer.png'); + + toolbar.appendChild(spacer.cloneNode(true)); + + + /* + Maverick + This method is used for loading the stylesheet from the file. + Reference: http://www.w3schools.com/xsl/xsl_client.asp + */ + + function loadXMLDoc(filename) { + if (window.ActiveXObject) { + xhttp = new ActiveXObject("Msxml2.XMLHTTP"); + } else { + xhttp = new XMLHttpRequest(); + } + xhttp.open("GET", filename, false); + try { + xhttp.responseType = "msxml-document" + } catch (err) {} + xhttp.send(""); + return xhttp.responseXML; + } + + + /* + Maverick + The Export buttons in toolbar call this function with varying + arguments. + The third argument is used to deciFde which button is being + pressed. + exportXML : 2 arguments + exportXcos: 3 arguments + */ + function displayXMLorXcos() { + var textarea = document.createElement('textarea'); + textarea.style.width = '400px'; + textarea.style.height = '400px'; + + var enc = new mxCodec(mxUtils.createXmlDocument()); + var node = enc.encode(diagRoot); + + var str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + mxUtils.getPrettyXml(node); + + textarea.value = str; + + if (arguments[2] == null) { + showModalWindow(graph, 'XML', textarea, 410, 440); + } else { + + return mxUtils.getPrettyXml(node); + } + } + + function getXcosDiagram(editor, cell) { + //Mind the 3 parameters. + var xmlFromExportXML = displayXMLorXcos(editor, cell, true); + if (xmlFromExportXML === null) + alert('First create the XML file.'); + else { + + var xml = mxUtils.parseXml(xmlFromExportXML); + + var xsl = loadXMLDoc("finalmodsheet.xsl"); + + xsltProcessor = new XSLTProcessor(); + xsltProcessor.importStylesheet(xsl); + resultDocument = xsltProcessor.transformToDocument(xml); + /* + Maverick + Using resultDocument.documentElement to remove an additional tag "<#document>" created by the XSLTProcessor. + */ + var str = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" + mxUtils.getPrettyXml(resultDocument.documentElement); + + str = str.replace(/\n\n/g, "\n"); + return str; + } + } + + // Defines a new export action + editor.addAction('exportXML', function(editor, cell) { + //Only two parameters passed here. + displayXMLorXcos(editor, cell); + }); + + /* Maverick + Reference: http://www.w3schools.com/xsl/xsl_client.asp + */ + + editor.addAction('exportXcos', function(editor, cell) { + var textarea = document.createElement('textarea'); + textarea.style.width = '400px'; + textarea.style.height = '400px'; + textarea.value = getXcosDiagram(editor, cell); + showModalWindow(graph, 'Xcos', textarea, 410, 440); + }); + + /* + Maverick + Adding a new button to import an Xcos diagram to our GUI and perform the simulation + on the remote server. + The flow of control is as follows: + The entire XML document is traversed, beginning from the root node. + The document is traversed three times: + 1. All the blocks are appended on the graph. + 2. All the ports are added to the blocks. + 3. All the links are made. + + Old ids are the ones which can be found from the imported file but when the blocks are added + to the graph mxGraph assigns new ids to them. + Careful mapping needs to be done between these two ids. + */ + editor.addAction('importXcos', function(editor, cell) { + var xmlDocument = ''; + var div = document.createElement('div'); + var node = document.createElement('form'); + div.setAttribute("id", "tempdiv"); + div.setAttribute("style", "height:200;width:200"); + + /* + Maverick + Implementing a file picker to choose the Xcos diagram. + */ + var fileNode = document.createElement('input'); + fileNode.type = 'file'; + if (!(window.File && window.FileReader && window.Blob && window.FileList)) { + alert('This browser doesn\'t support this feature.'); + return; + } + + node.id = "tempform"; + node.appendChild(fileNode); + var textArea = document.createElement('textarea'); + textArea.setAttribute("rows", "15"); + textArea.setAttribute("cols", "60"); + textArea.setAttribute("name", "tarea"); + node.appendChild(textArea); + var button = document.createElement('button'); + button.innerHTML = 'Submit'; + button.type = "button"; + button.name = "submit"; + node.appendChild(button); + + /* + Maverick + Reference: www.htmlgoodies.com + */ + fileNode.addEventListener('change', function(evt) { + + var f = evt.target.files[0]; + var r = new FileReader(); + r.onload = function(e) { + var contents = e.target.result; + /* + Maverick + The following regular expressions are used to format the imported Xcos XML + according to the format that is recognized by the mxCodec decoder. + */ + xmlDocument = contents; + //RegEx to replace all the newline characters. + xmlDocument = xmlDocument.replace(/\n*/, ''); + //RegEx to replace all the space characters between any a closing and the next opening tag. + xmlDocument = xmlDocument.replace(/>\s*</g, '><'); + //RegEx to replace all the XML comments. + xmlDocument = xmlDocument.replace(/<!--[\s\S]*?-->/g, ''); + textArea.value = xmlDocument; + + } + + r.readAsText(f); + }, false); + + /* + Maverick + A dictionary is used to perform the mapping between the old ids and the new ids. + See explanation at the beginning of the function!!! + */ + var nodeDataObject = {}; + + button.onclick = function() { + + wind.destroy(); + + graph.model.beginUpdate(); + try { + var parent = graph.getDefaultParent(); + var doc = mxUtils.parseXml(xmlDocument); + var codec = new mxCodec(doc); + var rootNode = doc.documentElement; + /* + Maverick + Extracting 'Setup Window' values from Xcos diagram and setting the same + on the new diagram. + */ + var defaultProperties = setup("get"); + var propertiesObject = {}; + + for (var key in defaultProperties) { + if (defaultProperties.hasOwnProperty(key)) { + propertiesObject[defaultProperties[key][1]] = rootNode.getAttribute(defaultProperties[key][1]); + /* + Maverick + Adding the corresponding attributes to the <XcosDiagram> tag. + */ + diagRoot[defaultProperties[key][1]] = rootNode.getAttribute(defaultProperties[key][1]); + } + } + + setup("set", propertiesObject); + + + + while (rootNode.nodeName != 'root') { + + /* + Maverick + Extracting 'Set Context' values from Xcos diagram and setting the same + on the new diagram. + */ + if (rootNode.nodeName == 'Array') { + + var contextValues = []; + + var contextChild = rootNode.firstChild; + + while (contextChild != null) { + contextValues.push(contextChild.getAttribute('value')); + contextChild = contextChild.nextSibling; + } + + diagRoot.context = contextValues; + diagRoot.context.scilabClass = "String[]"; + handleContext("set", contextValues); + rootNode = rootNode.nextSibling; + } else { + + rootNode = rootNode.firstChild; + } + + } + + var cells = []; + var currentNode = rootNode.firstChild; + while (currentNode != null) { + var curNodeName = currentNode.nodeName; + + var cell = codec.decode(currentNode); + + var curId = currentNode.getAttribute('id'); + + /* + Maverick + Finding the mxGeometry node for all the nodes. + */ + var geometryNode = currentNode.firstChild; + var geometryCell = null; + + if (geometryNode != null) { + while (geometryNode != null && geometryNode.nodeName != 'mxGeometry') { + geometryNode = geometryNode.nextSibling; + } + if (geometryNode != null) { + geometryCell = codec.decode(geometryNode); + } + } + /* + Maverick + Adding the blocks. + Finding out the constructor names for all the blocks which are not a port or a link. + Ports will be automatically handled with the respective constructor calls. + */ + if (!(curNodeName.endsWith('Link') || curNodeName.endsWith('Port'))) { + var ifaceFuncName = null; + + /* + Maverick + The following data structure is used to store the information required for each block + to the subsequent mapping. + */ + var temporaryMapObject = new Object(); + temporaryMapObject.inputArray = []; + temporaryMapObject.outputArray = []; + temporaryMapObject.controlArray = []; + temporaryMapObject.commandArray = []; + temporaryMapObject.inputIds = []; + temporaryMapObject.outputIds = []; + temporaryMapObject.controlIds = []; + temporaryMapObject.commandIds = []; + + switch(curNodeName){ + case 'ExplicitInBlock': ifaceFuncName='IN_f'; break; + case 'ExplicitOutBlock': ifaceFuncName='OUT_f'; break; + case 'ImplicitInBlock': ifaceFuncName='INIMPL_f'; break; + case 'ImplicitOutBlock': ifaceFuncName='OUTIMPL_f'; break; + default: ifaceFuncName=cell.interfaceFunctionName; + } + + var details_instance=null + if (ifaceFuncName != null) { + details_instance = new window[ifaceFuncName](); + } + + + if (details_instance != null) { + var details = details_instance.define(); + var enc = new mxCodec(mxUtils.createXmlDocument()); + var node = enc.encode(details); + var temp = enc.encode(parent); + var stylesheet = graph.getStylesheet(); + var styleName = currentNode.getAttribute('style'); + if(styleName!=null){ + if (styleName.indexOf(';') != -1) { + styleName = styleName.substring(0, styleName.indexOf(';')); + } + } + var style = stylesheet.styles[styleName]; + + + /* + * When a particular block is loaded for the first time, + * the image in the style of the block will be a path to the image. + * Set the label in the style property of the block has a html image, + * and set the image in the style property as null + * + * NOTE: Since the image of any block need not be changed for + * for every movement of that block, the image must be + * set only once. + */ + if (style != null && style['image'] != null) { + + // Make label as a image html element + var label = '<img src="' + style['image'] + '" height="80" width="80">'; + + // Set label + style['label'] = label; + style['imagePath'] = style['image']; + // Set image as null + style['image'] = null; + + // Add the label as a part of node + node.setAttribute('label', label); + } + + /* + * If a particular block with image tag in it's style property + * has been invoked already, the image tag would be null for any + * successive instances of the same block. Hence, set the label + * from the label tag in style which was set when that blockModel + * was invoked on the first time. + */ + if (style != null && style['label'] != null) { + + // Set label from the label field in the style property + node.setAttribute('label', style['label']); + } + node.setAttribute('parent', temp.getAttribute('id')); + + var blockModel = details_instance.x.model; + var graphics = details_instance.x.graphics; + + + var v1 = graph.insertVertex(graph.getDefaultParent(), null, node, geometryCell.x, geometryCell.y, 80, 80, ifaceFuncName); + // @Chhavi: Additional attribute to store the block's instance + v1.blockInstance = createInstanceTag(details_instance); + temporaryMapObject.newId = v1.id; + + nodeDataObject[curId] = temporaryMapObject; + + //findAndCreatePorts(graph,v1,doc,curId,codec); + //createPorts(graph, v1, inputPorts, controlPorts, outputPorts, commandPorts); + + v1.setConnectable(false); + } + + /* + Maverick + Handling SplitBlock in a different manner. + */ + if (curNodeName == 'SplitBlock') { + // (x-5, y-5.5) is the offset to correct the position of split-block + var v1 = graph.insertVertex(graph.getDefaultParent(), null, '', geometryCell.x - 5, geometryCell.y - 5.5, 10, 10, 'Split', false); + temporaryMapObject.newId = v1.id; + nodeDataObject[curId] = temporaryMapObject; + v1.setConnectable(false); + } + } + + if (curNodeName.endsWith('Port')) { + + var oldParentId = currentNode.getAttribute('parent'); + var newParentObj = nodeDataObject[oldParentId]; + var newParentId = newParentObj.newId; + + var newParentCell = graph.getModel().getCell(newParentId); + if (curNodeName == 'ExplicitInputPort') { + newParentObj.inputArray.push('E'); + newParentObj.inputIds.push(curId); + } + if (curNodeName == 'ImplicitInputPort') { + newParentObj.inputArray.push('I'); + newParentObj.inputIds.push(curId); + } + if (curNodeName == 'ExplicitOutputPort') { + newParentObj.outputArray.push('E'); + newParentObj.outputIds.push(curId); + } + if (curNodeName == 'ImplicitOutputPort') { + newParentObj.outputArray.push('I'); + newParentObj.outputIds.push(curId); + } + if (curNodeName == 'CommandPort') { + newParentObj.commandArray.push('COMMAND'); + newParentObj.commandIds.push(curId); + } + if (curNodeName == 'ControlPort') { + newParentObj.controlArray.push('CONTROL'); + newParentObj.controlIds.push(curId); + } + } + + //To continue traversal of all the nodes. + currentNode = currentNode.nextSibling; + } + + /* + Maverick + Adding the ports. + */ + currentNode = rootNode.firstChild; + while (currentNode != null) { + var curNodeName = currentNode.nodeName; + /* + Maverick + Handling all the ports of a given block collectively. + */ + if (!(curNodeName.endsWith('Port') || curNodeName.endsWith('Link'))) { + var curId = currentNode.getAttribute('id'); + var newParentObj = nodeDataObject[curId]; + if (newParentObj != null) { + var newParentId = newParentObj.newId; + + var newParentCell = graph.getModel().getCell(newParentId); + createPorts(graph, newParentCell, newParentObj.inputArray, newParentObj.controlArray, newParentObj.outputArray, newParentObj.commandArray, newParentObj, nodeDataObject); + } + } + currentNode = currentNode.nextSibling; + } + + /* + Maverick + Connecting the links. + */ + + currentNode = rootNode.firstChild; + while (currentNode != null) { + var curNodeName = currentNode.nodeName; + if (curNodeName.endsWith('Link')) { + + var pointsArray = []; + var newSourceObj = nodeDataObject[currentNode.getAttribute('source')]; + var newTargetObj = nodeDataObject[currentNode.getAttribute('target')]; + + var newSourceCell = graph.getModel().getCell(newSourceObj.newId); + var newTargetCell = graph.getModel().getCell(newTargetObj.newId); + + var childNode = currentNode.firstChild; + if (childNode != null) { + if (childNode.nodeName == 'mxGeometry') { + var tempNode = childNode.firstChild; + if (tempNode != null) { + if (tempNode.nodeName == 'mxPoint') { + pointsArray.push(new mxPoint(tempNode.getAttribute('x'), tempNode.getAttribute('y'))); + } else { + if (tempNode.nodeName == 'Array') { + var mxPointNode = tempNode.firstChild; + while (mxPointNode != null) { + pointsArray.push(new mxPoint(mxPointNode.getAttribute('x'), mxPointNode.getAttribute('y'))); + mxPointNode = mxPointNode.nextSibling; + } + } + } + } + } + } + + createEdgeObject(graph, newSourceCell, newTargetCell, null); + } + currentNode = currentNode.nextSibling; + } + + } finally { + graph.model.endUpdate(); + } + + } + + div.appendChild(node); + + node.style.visibility = "visible"; + var wind = showModalWindow(graph, 'Set Context', div, 410, 440); + }); + + + addToolbarButton(editor, toolbar, 'importXcos', 'Import Xcos', 'images/export1.png'); + addToolbarButton(editor, toolbar, 'exportXML', 'Export XML', 'images/export1.png'); + addToolbarButton(editor, toolbar, 'exportXcos', 'Export Xcos', 'images/export1.png'); + + toolbar.appendChild(spacer.cloneNode(true)); + + addToolbarButton(editor, toolbar, 'simulate', 'Simulate', 'images/ScilabExecute.png'); + + editor.addAction('simulate', function(editor, cell) { + var diagram = getXcosDiagram(editor, cell); + var blob = new Blob([diagram], { + type: 'text/plain' + }); + + // Create mxWindow for charts + var win = '<div id="charts" style="text-align: center;"><img id="loader" style="position: absolute; top:50%; transform: translate(-50%, -50%);" src="images/loading.gif"/></div>'; + var content = document.createElement('div'); + content.style.padding="1%"; + content.innerHTML = win; + // Center the mxWindow + var w = document.body.clientWidth; + var h = (document.body.clientHeight || document.documentElement.clientHeight); + wnd = new mxWindow('Simulation', content, (w-600)/2, (h-400)/2, 600, 400, true, true); + wnd.setMaximizable(false); + wnd.setMinimizable(false); + wnd.setScrollable(false); + wnd.setResizable(false); + wnd.setClosable(true); + wnd.setVisible(true); + wnd.addListener(mxEvent.CLOSE, function(e){ + chart_reset(); + }); + + // Send xcos file to server + var form = new FormData() + form.append("file",blob); + var xhr = new XMLHttpRequest(); + xhr.open("POST", "/upload", true); + xhr.onload = function() { + console.log(this.responseText); + if(this.responseText!='error'){ + // If no error in uploading, initialize chart + clientID = this.responseText; + chart_init(wnd); + }else{ + alert("Error"); + } + }; + xhr.onreadystatechange = function() { + console.log("state: " + xhr.readyState); + }; + xhr.upload.onprogress = function() { + console.log("uploading..."); + }; + xhr.send(form); + }); + + // Adds toolbar buttons into the status bar at the bottom + // of the window. + + addToolbarButton(editor, status, 'zoomIn', '', 'images/zoom_in.png', true); + addToolbarButton(editor, status, 'zoomOut', '', 'images/zoom_out.png', true); + addToolbarButton(editor, status, 'actualSize', '', 'images/view_1_1.png', true); + addToolbarButton(editor, status, 'fit', '', 'images/fit_to_size.png', true); + + // Creates the outline (navigator, overview) for moving + // around the graph in the top, right corner of the window. + var outln = new mxOutline(graph, outline); + + // To show the images in the outline, uncomment the following code + //outln.outline.labelsVisible = true; + //outln.outline.setHtmlLabels(true); + + // Fades-out the splash screen after the UI has been loaded. + var splash = document.getElementById('splash'); + if (splash != null) { + try { + mxEvent.release(splash); + mxEffects.fadeOut(splash, 100, true); + } catch (e) { + + // mxUtils is not available (library not loaded) + splash.parentNode.removeChild(splash); + } + } + + // Handles cursor keys - guides.html + var nudge = function(keyCode) { + if (!graph.isSelectionEmpty()) { + var dx = 0; + var dy = 0; + if (keyCode == 37) { + dx = -5; + } else if (keyCode == 38) { + dy = -5; + } else if (keyCode == 39) { + dx = 5; + } else if (keyCode == 40) { + dy = 5; + } + graph.moveCells(graph.getSelectionCells(), dx, dy); + } + }; + // Transfer initial focus to graph container for keystroke handling + // graph.container.focus(); + // Handles keystroke events + var keyHandler = new mxKeyHandler(graph); + keyHandler.bindKey(37, function() { + nudge(37); + }); + keyHandler.bindKey(38, function() { + nudge(38); + }); + keyHandler.bindKey(39, function() { + nudge(39); + }); + keyHandler.bindKey(40, function() { + nudge(40); + }); + + // Starts connections on the background in wire-mode + var connectionHandlerIsStartEvent = graph.connectionHandler.isStartEvent; + graph.connectionHandler.isStartEvent = function(me) { + return connectionHandlerIsStartEvent.apply(this, arguments); + }; + + // Avoids any connections for gestures within tolerance except when in wire-mode + // or when over a port + var connectionHandlerMouseUp = graph.connectionHandler.mouseUp; + graph.connectionHandler.mouseUp = function(sender, me) { + if (this.first != null && this.previous != null) { + var point = mxUtils.convertPoint(this.graph.container, me.getX(), me.getY()); + var dx = Math.abs(point.x - this.first.x); + var dy = Math.abs(point.y - this.first.y); + + if (dx < this.graph.tolerance && dy < this.graph.tolerance) { + // Selects edges in non-wire mode for single clicks, but starts + // connecting for non-edges regardless of wire-mode + if (this.graph.getModel().isEdge(this.previous.cell)) { + this.reset(); + } + + return; + } + } + + connectionHandlerMouseUp.apply(this, arguments); + }; + + mxEvent.disableContextMenu(container); + + // @Adhitya: Add focus to a mxCell + if (mxClient.IS_NS) { + mxEvent.addListener(graph.container, 'mousedown', function(evt) { + if (!graph.isEditing()) { + graph.container.setAttribute('tabindex', '-1'); + graph.container.focus(); + } + }); + } + + } + }; + + /* + @jiteshjha + styleToObject(style) converts style string into an object. + Format : First item in the object will be 'default: linkStyle', + and the rest of items will be of the style 'mxConstants:value' + */ + + function styleToObject(style) { + //To add semicolon at the end if it isn't already present. + if (style[style.length - 1] != ';') { + style = style + ';'; + } + var defaultStyle = style.substring(0, style.indexOf(';')); + var styleObject = { + "default": defaultStyle + }; + var remainingStyle = style.substring(style.indexOf(';') + 1); + + /* + remainingStyle is the string without the default style. + For every key:value pair in the string, + extract the key(string before '=') and the value + (string before ';'), set the key:value pair into styleObject + and remainingStyle is set to a string without the key:value pair. + */ + while (remainingStyle.length > 0) { + var indexOfKey = remainingStyle.indexOf('='); + var key = remainingStyle.substring(0, indexOfKey); + remainingStyle = remainingStyle.substring(indexOfKey + 1); + var indexOfValue = remainingStyle.indexOf(';'); + var value = remainingStyle.substring(0, indexOfValue); + styleObject[key] = value; + remainingStyle = remainingStyle.substring(indexOfValue + 1); + } + + return styleObject; + } + + /* + @jiteshjha + styleToObject(style) converts the object back to the style string. + */ + function objectToStyle(object) { + var style = ""; + for (var key in object) { + if (key.toString() == "default") { + style += object[key] + ';'; + } else { + style += (key + '=' + object[key] + ';'); + } + } + return style; + } + + /* + Maverick + The following function is used to define a tag for entire diagram. + We can set context, model and setup parameters for the entire diagram + using this function. + */ + + + function XcosDiagram(context, model, attributes) { + this.context = context; + this.model = model; + this.finalIntegrationTime = attributes; + } + + + /* + @jiteshjha, @pooja + setContext dialog box + Includes a set context instruction text and input text area. + */ + + /* + Maverick + Added 'diagRoot' parameter. + */ + function showSetContext(graph, diagRoot) { + + // Create basic structure for the form + var content = document.createElement('div'); + content.setAttribute("id", "setContext"); + + // Add Form + var myform = document.createElement("form"); + myform.method = ""; + myform.setAttribute("id", "formProperties"); + + // Add set context string + var descriptionSetContext = document.createElement("div"); + descriptionSetContext.innerHTML = "You may enter here scilab instructions to define symbolic parameters used in block definitions using Scilab instructions. These instructions are evaluated once confirmed(i.e. you click on OK and every time the diagram is loaded)"; + descriptionSetContext.setAttribute("id", "descriptionSetContext"); + myform.appendChild(descriptionSetContext); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // input text area + var textareaSetContext = document.createElement("textarea"); + textareaSetContext.setAttribute("id", "textareaSetContext"); + + myform.appendChild(textareaSetContext); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Button - Submit + var btn = document.createElement("button"); + btn.innerHTML = 'Ok'; + btn.type = "button"; + btn.name = "submit"; + btn.setAttribute("id", "buttonSetContext"); + + var contextValue = handleContext("get"); + + var displayValue = ""; + + /* + Maverick + Modified the for loop because only requirement was to + traverse the array of 'contextValue' and not all the + elements of it. + */ + for (var i = 0; i < contextValue.length; i++) { + displayValue += contextValue[i] + "\n"; + } + if (contextValue != "") { + textareaSetContext.value = displayValue; + } else { + textareaSetContext.value = ""; + + } + + // Executes when button 'btn' is clicked + btn.onclick = function() { + + var input = document.getElementById('textareaSetContext').value; + + /* + Maverick + Code to extract context parameter values from the text area + containing the input. + */ + var contextValues = []; + var i = 0, + temp = ""; + for (i = 0; i < input.length; i++) { + if (input[i] == '\n') { + if (temp != "") { + contextValues.push(temp); + } + temp = ""; + continue; + } + temp += input[i]; + } + if (temp != "") { + contextValues.push(temp); + } + + diagRoot.context = contextValues; + diagRoot.context.scilabClass = "String[]"; + handleContext("set", contextValues); + wind.destroy(); + }; + + myform.appendChild(btn); + content.appendChild(myform); + var wind = showModalWindow(graph, 'Set Context', content, 450, 350); + }; + + function showPropertiesWindow(graph, cell) { + + var name = cell.getAttribute('blockElementName'); + var defaultProperties = cell.blockInstance.instance.get(); //window[name]("get"); + /*{ + nbr_curves: ["Number of curves", 1], + clrs: ["color (>0) or mark (<0)", [1, 2, 3, 4, 5, 6, 7, 13]], + siz: ["line or mark size", [1, 1, 1, 1, 1, 1, 1, 1]], + win: ["Output window number (-1 for automatic)", -1], + wpos: ["Output window position", [-1, -1]], + wdim: ["Output window sizes", [-1, -1]], + vec_x: ["Xmin and Xmax", [-15, 15]], + vec_y: ["Ymin and Ymax", [-15, 15]], + vec_z: ["Zmin and Zmax", [-15, 15]], + param3ds: ["Alpha and Theta", [50, 280]], + N: ["Buffer size", 2] + };*/ + + //var defaultProperties=window["CONST_m"]("get"); + + // Create basic structure for the form + var content = document.createElement('div'); + content.setAttribute("id", "contentProperties"); + + // Heading of content + var heading = document.createElement('h2'); + heading.innerHTML = "Set Scope Parameters"; + heading.id = "headingProperties" + content.appendChild(heading); + + // Add Form + var myform = document.createElement("form"); + myform.method = "post"; + myform.id = "formProperties"; + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + for (var key in defaultProperties) { + if (defaultProperties.hasOwnProperty(key)) { + + // Input Title + var fieldName = defaultProperties[key]; + var namelabel = document.createElement('label'); + namelabel.innerHTML = defaultProperties[key][0]; + myform.appendChild(namelabel); + + // Input + var input = document.createElement("input"); + input.name = key; + input.value = defaultProperties[key][1]; + input.setAttribute("id", key.toString()); + input.setAttribute("class", "fieldInput"); + myform.appendChild(input); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + } + } + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Button - Submit + var btn = document.createElement("button"); + btn.innerHTML = 'Submit'; + btn.type = "button"; + btn.name = "submit"; + + // Executes when button 'btn' is clicked + btn.onclick = function() { + var propertiesObject = { + id: cell.id + }; + + for (var key in defaultProperties) { + if (defaultProperties.hasOwnProperty(key)) { + propertiesObject[key] = document.getElementById(key.toString()).value; + } + } + var details = cell.blockInstance.instance.set(propertiesObject); //window[name]("set",cell.value,propertiesObject); + var enc = new mxCodec(); + var node = enc.encode(details); + cell.value = node; + /* + Maverick + We have changed the value of the cell, but the change won't be reflected + unless the graph is refreshed. + */ + graph.refresh(); + wind.destroy(); + }; + myform.appendChild(btn); + + // Button - Reset + var btn = document.createElement("button"); + btn.innerHTML = 'Reset'; + btn.type = "button"; + btn.name = "submit"; + btn.id = "resetButtonProperties"; + btn.onclick = function() { + // Reset + for (var key in defaultProperties) { + if (defaultProperties.hasOwnProperty(key)) { + var element = document.getElementById(key.toString()); + element.value = defaultProperties[key][1]; + } + } + }; + + myform.appendChild(btn); + // Base height without fields : 135 px + height = 135 + 26 * defaultProperties.length + 15; + + content.appendChild(myform); + var wind = showModalWindow(graph, 'Properties', content, 450, height); + }; + + /* + * @jiteshjha + * createEdgeObject(@parameters) creates an edge on the graph DOM + * @Parameters : + * source -> source object for the edge + * target -> destination object for the edge + * points -> waypoints to be inserted in the geometry + */ + function createEdgeObject(graph, source, target, points) { + + // Start the update on the graph + graph.getModel().beginUpdate(); + + try { + + // Create an edge from the given source object and target object + var edge = graph.insertEdge(graph.getDefaultParent(), null, '', source, target); + + // Get geometry of the edge + var geometry = graph.getModel().getGeometry(edge); + + /* + * Clone the geometry object + * NOTE: Direct manipulation of the geometry object may not be + * registered as an action for some cases, hence we clone the + * geometry, manipulate it and set the geometry. + */ + var cloneGeometry = geometry.clone(); + + // Add points in the cloned geometry + cloneGeometry.points = points; + + // Set the changed geometry for the edge + graph.getModel().setGeometry(edge, cloneGeometry); + + // Refresh to reflect changes made + graph.refresh(); + } finally { + + // End the update + graph.getModel().endUpdate(); + } + + return edge; + } + + /* + @jiteshjha + Creates a dialog box related to the edge label properties. + The properties implemented are : edge label, label fontStyle, + label fontSize, label fontStyle. + */ + + + function showTextEditWindow(graph, cell) { + var fontFamilyList = { + "Arial": 0, + "Dialog": 1, + "Verdana": 2, + "Times New Roman": 3 + } + var defaultProperties = { + text: ["Text", "text"], + fontFamily: ["Font Family", fontFamilyList], + fontSize: ["fontSize", 20] + }; + + var style = graph.getModel().getStyle(cell); + var styleObject = styleToObject(style); + if ('fontSize' in styleObject) { + defaultProperties['fontSize'][1] = styleObject['fontSize']; + } + if (cell.value != "") { + defaultProperties['text'][1] = cell.value; + } + + // Create basic structure for the form + var content = document.createElement('div'); + content.setAttribute("id", "contentProperties"); + + // Heading of content + var heading = document.createElement('h2'); + heading.innerHTML = "Text and Text Font"; + heading.id = "headingProperties" + content.appendChild(heading); + + // Add Form + var myform = document.createElement("form"); + myform.method = "post"; + myform.id = "formProperties"; + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + for (var key in defaultProperties) { + if (defaultProperties.hasOwnProperty(key)) { + + // Input Title + var fieldName = defaultProperties[key]; + var namelabel = document.createElement('label'); + namelabel.innerHTML = defaultProperties[key][0]; + myform.appendChild(namelabel); + + if (key == "fontFamily") { + //Here we create a "select" element (a drop down list). + var newList = document.createElement("select"); + newList.style.cssText = "float:right"; + newList.setAttribute("id", key.toString()); + var dropdownItems = defaultProperties[key][1]; + + for (var item in dropdownItems) { + if (dropdownItems.hasOwnProperty(item)) { + option = document.createElement('option'); + option.value = item; + option.text = item; + option.setAttribute("id", item); + newList.appendChild(option); + } + } + + var selectedFontFamily = 0; + var styleObject = styleToObject(style); + if ('fontFamily' in styleObject) { + selectedFontFamily = styleObject['fontFamily']; + } + newList.selectedIndex = dropdownItems[selectedFontFamily]; + myform.appendChild(newList); + } else { + var input = document.createElement("input"); + input.name = key; + input.value = defaultProperties[key][1]; + input.setAttribute("id", key.toString()); + input.setAttribute("class", "fieldInput"); + myform.appendChild(input); + } + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + } + } + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + /* + changeFontStyle function sets the style for given fontStyle and toggles with the active class + for "set" type, and toggles with the active class for "get" type. + */ + function changeFontStyle(type, graph, cell, button, bit) { + var style = graph.getModel().getStyle(cell); + var trigger = document.getElementById(button); + var styleObject = styleToObject(style); + var previousValue = 1; + if ('fontStyle' in styleObject) { + previousValue = styleObject['fontStyle']; + + // To get a bit mask: + var mask = 1 << bit; // Get the 1st element + + if (type == "get") { + // toggle the bit + previousValue ^= mask; + trigger.classList.toggle(button); + styleObject['fontStyle'] = previousValue; + style = objectToStyle(styleObject); + graph.getModel().setStyle(cell, style); + } else if (type == "set") { + if ((previousValue & mask) != 0) { + trigger.classList.toggle(button); + } + } + } + } + + // Button - Bold + var btn = document.createElement("button"); + btn.innerHTML = 'Bold'; + btn.setAttribute("id", "boldButton"); + btn.type = "button"; + btn.name = "submit"; + btn.onclick = function() { + changeFontStyle("get", graph, cell, 'boldButton', 0); + } + myform.appendChild(btn); + + // Button - Italics + var btn = document.createElement("button"); + btn.innerHTML = 'Italic'; + btn.setAttribute("id", "italicButton"); + btn.type = "button"; + btn.name = "submit"; + btn.onclick = function() { + changeFontStyle("get", graph, cell, 'italicButton', 1); + } + myform.appendChild(btn); + + // Button - Underline + var btn = document.createElement("button"); + btn.innerHTML = 'Underline'; + btn.setAttribute("id", "underlineButton"); + btn.type = "button"; + btn.name = "submit"; + btn.onclick = function() { + changeFontStyle("get", graph, cell, 'underlineButton', 2); + } + myform.appendChild(btn); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Button - Submit + var btn = document.createElement("button"); + btn.innerHTML = 'Submit'; + btn.type = "button"; + btn.name = "submit"; + + // Executes when button 'btn' is clicked + btn.onclick = function() { + var propertiesObject = { + id: cell.id + }; + for (var key in defaultProperties) { + if (defaultProperties.hasOwnProperty(key)) { + propertiesObject[key] = document.getElementById(key.toString()).value; + } + } + var style = graph.getModel().getStyle(cell); + var styleObject = styleToObject(style); + styleObject['fontSize'] = propertiesObject['fontSize']; + styleObject['fontFamily'] = propertiesObject['fontFamily']; + style = objectToStyle(styleObject); + graph.getModel().setStyle(cell, style); + graph.getModel().setValue(cell, propertiesObject['text']); + wind.destroy(); + }; + myform.appendChild(btn); + + // Base heights without fields : 135 px + height = 135 + 26 * defaultProperties.length + 15; + content.appendChild(myform); + var wind = showModalWindow(graph, 'Text and Text font', content, 450, height); + + /* + @jiteshjha + If any fontStyle(Bold, Italic, Underline) has already been implemented + for the selected edge label, add the respective active class to that button. + */ + + if ('fontStyle' in styleObject) { + changeFontStyle("set", graph, cell, 'boldButton', 0); + changeFontStyle("set", graph, cell, 'italicButton', 1); + changeFontStyle("set", graph, cell, 'underlineButton', 2); + } + }; + /* + @jiteshjha, @pooja + showSetupWindow dialog box + */ + + /* + Maverick + Added 'diagRoot' parameter. + */ + function showSetupWindow(graph, diagRoot) { + + /* + Maverick + Added one more element in the list for each key to be used in the <XcosDiagram> + tag. + */ + + var defaultProperties = setup("get"); + + // Create basic structure for the form + var content = document.createElement('div'); + content.setAttribute("id", "contentProperties"); + + // Heading of content + var heading = document.createElement('h2'); + heading.innerHTML = "Setup"; + heading.id = "headingProperties" + content.appendChild(heading); + + // Add Form + var myform = document.createElement("form"); + myform.method = "post"; + myform.id = "formProperties"; + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + for (var key in defaultProperties) { + if (defaultProperties.hasOwnProperty(key)) { + + // Input Title + var fieldName = defaultProperties[key]; + var namelabel = document.createElement('label'); + namelabel.innerHTML = defaultProperties[key][0]; + myform.appendChild(namelabel); + + if (key == "solv_kind") { + + //Here we create a "select" element (a drop down list). + var newList = document.createElement("select"); + newList.style.cssText = "float:right"; + newList.setAttribute("id", key.toString()); + var dropdownItems = setup("getArray"); + + // Iterate over the dropdown options and create html elements + dropdownItems.forEach(function(value, i) { + option = document.createElement('option'); + option.value = i.toFixed(1); + option.text = value; + newList.appendChild(option); + }); + newList.selectedIndex = defaultProperties[key][2]; + myform.appendChild(newList); + + } else { + var input = document.createElement("input"); + input.name = key; + input.value = defaultProperties[key][2]; + input.setAttribute("id", key.toString()); + input.setAttribute("class", "fieldInput"); + myform.appendChild(input); + } + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + } + } + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Button - Set Context + var btn = document.createElement("button"); + btn.innerHTML = 'Set Context'; + btn.style.cssText = 'float: left'; + btn.type = "button"; + btn.name = "submit"; + btn.id = "resetButtonProperties"; + btn.onclick = function() { + // show Set Context + /* + Maverick + Added the parameter here as well. + */ + showSetContext(graph, diagRoot); + }; + myform.appendChild(btn); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + + // Button - Submit + var btn = document.createElement("button"); + btn.innerHTML = 'Submit'; + btn.type = "button"; + btn.name = "submit"; + + // Executes when button 'btn' is clicked + btn.onclick = function() { + var propertiesObject = {}; + + for (var key in defaultProperties) { + if (defaultProperties.hasOwnProperty(key)) { + propertiesObject[defaultProperties[key][1]] = document.getElementById(key.toString()).value; + + /* + Maverick + Adding the corresponding attributes to the <XcosDiagram> tag. + */ + diagRoot[defaultProperties[key][1]] = document.getElementById(key.toString()).value; + } + } + + setup("set", propertiesObject); + wind.destroy(); + }; + + myform.appendChild(btn); + + + // Button - Reset + var btn = document.createElement("button"); + btn.innerHTML = 'Reset'; + btn.type = "button"; + btn.name = "submit"; + btn.id = "resetButtonProperties"; + btn.onclick = function() { + // Reset + for (var key in defaultProperties) { + if (defaultProperties.hasOwnProperty(key)) { + var element = document.getElementById(key.toString()); + if (key != "solv_kind") { + element.value = defaultProperties[key][2]; + } else { + /* + Maverick + Code modified to reset the drop down list. + */ + element.selectedIndex = 0; + } + } + } + }; + + myform.appendChild(btn); + // Base height without fields : 135 px + height = 135 + 26 * defaultProperties.length + 15; + + content.appendChild(myform); + var wind = showModalWindow(graph, 'Set Parameters', content, 450, height); + }; + + function showColorWheel(graph, cell, selectProperty) { + // Create basic structure for the form + var content = document.createElement('div'); + content.setAttribute("id", "colorProperties"); + // Add Form + var myform = document.createElement("form"); + myform.method = ""; + myform.setAttribute("id", "formProperties"); + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + // Input Title + var fieldName = 'Color'; + var namelabel = document.createElement('label'); + namelabel.innerHTML = fieldName; + myform.appendChild(namelabel); + // Input + var input = document.createElement("input"); + input.name = fieldName; + input.value = 0; + input.style.cssText = 'float: right;'; + input.setAttribute("id", "color"); + myform.appendChild(input); + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + var picker = document.createElement('div'); + picker.setAttribute("id", "picker"); + myform.appendChild(picker); + // Line break + var linebreak = document.createElement('br'); + myform.appendChild(linebreak); + // Button - Submit + var btn = document.createElement("button"); + btn.innerHTML = 'Submit'; + btn.type = "button"; + btn.name = "submit"; + btn.style.cssText = 'margin-left: 75px'; + // Executes when button 'btn' is clicked + btn.onclick = function() { + var selectedCells = graph.getSelectionCells(); + graph.getModel().beginUpdate(); + try { + for (var count = 0; count < selectedCells.length; count++) { + var selectedCell = selectedCells[count]; + var input = document.getElementById('color').value; + var style = graph.getModel().getStyle(selectedCell); + + if (style != null) { + var styleObject = styleToObject(style); + } + + if (selectProperty == "edgeStrokeColor") { + styleObject['strokeColor'] = input; + } else if (selectProperty == "bgColor") { + graph.container.style.backgroundColor = input; + } else if (selectProperty == "vertexStrokeColor") { + styleObject['strokeColor'] = input; + } else if (selectProperty == "vertexFillColor") { + styleObject['fillColor'] = input; + } else if (selectProperty == "edgeTextColor") { + styleObject['fontColor'] = input; + } + + if (style != null) { + style = objectToStyle(styleObject); + graph.getModel().setStyle(selectedCell, style); + } + } + } finally { + graph.getModel().endUpdate(); + } + + wind.destroy(); + }; + myform.appendChild(btn); + content.appendChild(myform); + var wind = showModalWindow(graph, 'Diagram background...', content, 285, 340); + // Invokes the farbtastic functionality + $(document).ready(function() { + $('#picker').farbtastic('#color'); + }); + }; + + function createButtonImage(button, image) { + if (image != null) { + var img = document.createElement('img'); + img.setAttribute('src', image); + img.style.width = '16px'; + img.style.height = '16px'; + img.style.verticalAlign = 'middle'; + img.style.marginRight = '2px'; + button.appendChild(img); + } + } + + function addIcons(graph, sidebar) { + var req = mxUtils.load('palettes/palettes.xml'); + var root = req.getDocumentElement(); + var x = root.getElementsByTagName('node')[0]; + var categories = x.getElementsByTagName('node'); + for (var i = 0, nodeLength = categories.length; i < nodeLength; i++) { + var categoryName = categories[i].getAttribute('name'); + var title = document.createElement('h3'); + title.setAttribute('class', 'accordion-header ui-accordion-header ui-helper-reset ui-state-default ui-accordion-icons ui-corner-all'); + var span = document.createElement('span'); + span.setAttribute('class', 'ui-accordion-header-icon ui-icon ui-icon-triangle-1-e'); + var titleName = document.createTextNode(categoryName); + title.appendChild(span); + title.appendChild(titleName); + sidebar.appendChild(title); + var newImages = document.createElement('div'); + newImages.setAttribute('class', 'ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom'); + var blocks = categories[i].getElementsByTagName('block'); + for (var j = 0, blockLength = blocks.length; j < blockLength; j++) { + var name = blocks[j].getAttribute('name'); + var icon = blocks[j].getElementsByTagName('icon')[0]; + var iconPath = icon.getAttribute('path'); + addSidebarIcon(graph, newImages, name, iconPath); + } + sidebar.appendChild(newImages); + } + } + + function addToolbarButton(editor, toolbar, action, label, image, isTransparent) { + var button = document.createElement('button'); + button.style.fontSize = '10'; + createButtonImage(button, image); + if (isTransparent) { + button.style.background = 'transparent'; + button.style.color = '#FFFFFF'; + button.style.border = 'none'; + } + mxEvent.addListener(button, 'click', function(evt) { + editor.execute(action); + }); + mxUtils.write(button, label); + button.setAttribute('id', action); + toolbar.appendChild(button); + }; + + function showModalWindow(graph, title, content, width, height) { + var background = document.createElement('div'); + background.style.position = 'absolute'; + background.style.left = '0px'; + background.style.top = '0px'; + background.style.right = '0px'; + background.style.bottom = '0px'; + background.style.background = 'black'; + mxUtils.setOpacity(background, 50); + document.body.appendChild(background); + + if (mxClient.IS_IE) { + new mxDivResizer(background); + } + + var x = Math.max(0, document.body.scrollWidth / 2 - width / 2); + var y = Math.max(10, (document.body.scrollHeight || document.documentElement.scrollHeight) / 2 - height * 2 / 3); + var wind = new mxWindow(title, content, x, y, width, height, false, true); + wind.setClosable(true); + + // Fades the background out after after the window has been closed + wind.addListener(mxEvent.DESTROY, function(evt) { + graph.setEnabled(true); + mxEffects.fadeOut(background, 50, true, 10, 30, true); + }); + + graph.setEnabled(false); + graph.tooltipHandler.hide(); + wind.setVisible(true); + return wind; + }; + + var flag = 0; + + function addSidebarIcon(graph, sidebar, name, image) { + // Function that is executed when the image is dropped on + // the graph. The cell argument points to the cell under + // the mousepointer if there is one. + var funct = function(graph, evt, cell, x, y) { + var parent = graph.getDefaultParent(); + var model = graph.getModel(); + var v1 = null; + var doc = mxUtils.createXmlDocument(); + model.beginUpdate(); + try { + var details_instance = new window[name](); + var details = details_instance.define(); + var enc = new mxCodec(mxUtils.createXmlDocument()); + var node = enc.encode(details); + var temp = enc.encode(parent); + + // Get the stylesheet for the graph + var stylesheet = graph.getStylesheet(); + // From the stylesheet, get the style of the particular block + var style = stylesheet.styles[name]; + + /* + * When a particular block is loaded for the first time, + * the image in the style of the block will be a path to the image. + * Set the label in the style property of the block has a html image, + * and set the image in the style property as null + * + * NOTE: Since the image of any block need not be changed for + * for every movement of that block, the image must be + * set only once. + */ + if (style != null && style['image'] != null) { + + // Make label as a image html element + var label = '<img src="' + style['image'] + '" height="80" width="80">'; + + // Set label + style['label'] = label; + + style['imagePath'] = style['image']; + + // Set image as null + style['image'] = null; + + // Add the label as a part of node + node.setAttribute('label', label); + } + + /* + * If a particular block with image tag in it's style property + * has been invoked already, the image tag would be null for any + * successive instances of the same block. Hence, set the label + * from the label tag in style which was set when that blockModel + * was invoked on the first time. + */ + if (style != null && style['label'] != null) { + + // Set label from the label field in the style property + node.setAttribute('label', style['label']); + } + + node.setAttribute('parent', temp.getAttribute('id')); + var i, arr = []; + var blockModel = details_instance.x.model; + var graphics = details_instance.x.graphics; + + /* To determine number and type of Port*/ + var inputPorts = [], + outputPorts = [], + controlPorts = [], + commandPorts = []; + if (blockModel.in.height != null) { + arr = getData(graphics.in_implicit); + if (arr.length != 0) { + inputPorts = arr; + } else { + for (i = 0; i < blockModel.in.height; i++) { + inputPorts.push("E"); + } + } + } + if (blockModel.out.height != null) { + arr = getData(graphics.out_implicit); + if (arr.length != 0) { + outputPorts = arr; + } else { + for (i = 0; i < blockModel.out.height; i++) { + outputPorts.push("E"); + } + } + } + if (blockModel.evtin.height != null) { + for (i = 0; i < blockModel.evtin.height; i++) { + controlPorts.push("CONTROL"); + } + } + if (blockModel.evtout.height != null) { + for (i = 0; i < blockModel.evtout.height; i++) { + commandPorts.push("COMMAND"); + } + } + v1 = graph.insertVertex(parent, null, node, x, y, 80, 80, name); + + // @Chhavi: Additional attribute to store the block's instance + v1.blockInstance = createInstanceTag(details_instance); + v1.currentAngle = 0; + v1.flipX = 1; + v1.flipY = 1; + createPorts(graph, v1, inputPorts, controlPorts, outputPorts, commandPorts); + v1.setConnectable(false); + } finally { + model.endUpdate(); + } + graph.setSelectionCell(v1); + } + + var para = document.createElement('p'); + var blockFigure = document.createElement('figure'); + var img = document.createElement('img'); + img.setAttribute('src', image); + var caption = document.createElement('figcaption'); + var blockName = document.createTextNode(name); + caption.appendChild(blockName); + blockFigure.appendChild(img); + blockFigure.appendChild(caption); + para.appendChild(blockFigure); + sidebar.appendChild(para); + + var dragElt = document.createElement('div'); + dragElt.style.border = 'dashed black 1px'; + dragElt.style.width = '80px'; + dragElt.style.height = '80px'; + + // Creates the image which is used as the drag icon (preview) + var ds = mxUtils.makeDraggable(img, graph, funct, dragElt, 0, 0, true, true); + ds.setGuidesEnabled(true); + }; + + // Create ports + /* + Maverick + Modified the createPorts funtion so that it can be used while creating ports from + a given Xcos diagram. + New parameters are the parentObj where the port is supposed to be added and a dictionary + object which contains the mapping between the newly assigned Ids and imported Ids. + */ + function createPorts(graph, block, left, top, right, bottom, parentObj, nodeDataObject) { + + createInputPorts(graph, block, left, top, parentObj, nodeDataObject); + createOutputPorts(graph, block, right, bottom, parentObj, nodeDataObject); + + } + + function createInputPorts(graph, block, leftArray, topArray, parentObj, nodeDataObject) { + + var topNumber = topArray.length; + var leftNumber = leftArray.length; + + if (leftNumber != 0) { + for (var i = 1; i <= leftNumber; i++) { + + var x = 0; + var y = (i / (leftNumber + 1)).toFixed(4); + var portType = leftArray[i - 1]; + //console.log(parentObj.inputIds); + if (parentObj != null) { + createInputPort(graph, block, x, y, portType, 'left', i, nodeDataObject, parentObj.inputIds); + } else { + createInputPort(graph, block, x, y, portType, 'left', i); + } + + } + } + if (topNumber != 0) { + for (var i = 1; i <= topNumber; i++) { + var x = (i / (topNumber + 1)).toFixed(4); + var y = 0; + var portType = topArray[i - 1]; + //console.log(parentObj.controlIds); + if (parentObj != null) { + createInputPort(graph, block, x, y, portType, 'top', i, nodeDataObject, parentObj.controlIds); + } else { + createInputPort(graph, block, x, y, portType, 'top', i); + } + } + } + + }; + + function createOutputPorts(graph, block, rightArray, bottomArray, parentObj, nodeDataObject) { + + var bottomNumber = bottomArray.length; + var rightNumber = rightArray.length; + if (rightNumber != 0) { + for (var i = 1; i <= rightNumber; i++) { + var x = 1; + var y = (i / (rightNumber + 1)).toFixed(4); + var portType = rightArray[i - 1]; + //console.log(parentObj.outputIds); + if (parentObj != null) { + createOutputPort(graph, block, x, y, portType, 'right', i, nodeDataObject, parentObj.outputIds); + } else { + createOutputPort(graph, block, x, y, portType, 'right', i); + } + } + } + if (bottomNumber != 0) { + for (var i = 1; i <= bottomNumber; i++) { + var x = (i / (bottomNumber + 1)).toFixed(4); + var y = 1; + var portType = bottomArray[i - 1]; + //console.log(parentObj.commandIds); + if (parentObj != null) { + createOutputPort(graph, block, x, y, portType, 'bottom', i, nodeDataObject, parentObj.commandIds); + } else { + createOutputPort(graph, block, x, y, portType, 'bottom', i); + } + } + } + + }; + + function createInputPort(graph, block, x, y, portType, position, ordering, nodeDataObject, idArray) { + + var port = null; + if (portType == 'COMMAND') { + port = graph.insertVertex(block, null, 'CommandPort', x, y, 10, 10, 'CommandPort', true); + } else if (portType == 'CONTROL') { + port = graph.insertVertex(block, null, 'ControlPort', x, y, 10, 10, 'ControlPort', true); + } else if (portType == 'I') { + port = graph.insertVertex(block, null, 'ImplicitInputPort', x, y, 10, 10, 'ImplicitInputPort', true); + } else if (portType == 'E') { + port = graph.insertVertex(block, null, 'ExplicitInputPort', x, y, 10, 10, 'ExplicitInputPort', true); + } + if (port != null) { + if (position == 'top') { + port.geometry.offset = new mxPoint(-6, -10); + } else if (position == 'left') { + port.geometry.offset = new mxPoint(-10, -6); + } + port.ordering = ordering; + + if (nodeDataObject != null) { + var obj = new Object(); + obj.newId = port.id; + obj.oldId = idArray[ordering - 1]; + //console.log(idArray[ordering-1]); + nodeDataObject[idArray[ordering - 1]] = obj; + } + + if (block.style == 'Split') { + port.setVisible(false); + port.setConnectable(false); + } + } + }; + + function createOutputPort(graph, block, x, y, portType, position, ordering, nodeDataObject, idArray) { + var port = null; + + if (portType == 'COMMAND') { + port = graph.insertVertex(block, null, 'CommandPort', x, y, 10, 10, 'CommandPort', true); + } else if (portType == 'CONTROL') { + port = graph.insertVertex(block, null, 'ControlPort', x, y, 10, 10, 'ControlPort', true); + } else if (portType == 'I') { + port = graph.insertVertex(block, null, 'ImplicitOutputPort', x, y, 10, 10, 'ImplicitOutputPort', true); + } else if (portType == 'E') { + port = graph.insertVertex(block, null, 'ExplicitOutputPort', x, y, 10, 10, 'ExplicitOutputPort', true); + } + if (port != null) { + if (position == 'bottom') { + port.geometry.offset = new mxPoint(-6, 0); + } + if (position == 'right') { + port.geometry.offset = new mxPoint(0, -6); + } + port.ordering = ordering; + + if (nodeDataObject != null) { + var obj = new Object(); + obj.newId = port.id; + obj.oldId = idArray[ordering - 1]; + //console.log(idArray[ordering-1]); + nodeDataObject[idArray[ordering - 1]] = obj; + } + + if (block.style == 'Split') { + port.setVisible(false); + port.setConnectable(false); + } + } + }; + + function configureStylesheet(graph) { + var req = mxUtils.load('styles/Xcos-style.xml'); + var root = req.getDocumentElement(); + var dec = new mxCodec(root.ownerDocument); + dec.decode(root, graph.stylesheet); + }; + </script> + <!-- + Updates connection points before the routing is called. + --> + <script type="text/javascript"> + // Computes the position of edge to edge connection points. + mxGraphView.prototype.updateFixedTerminalPoint = function(edge, terminal, source, constraint) { + + // Store the edge state for every newly created edge in edgeState variable + edgeState = edge; + var pt = null; + + if (constraint != null) { + pt = this.graph.getConnectionPoint(terminal, constraint); + } + + if (source) { + edge.sourceSegment = null; + } else { + edge.targetSegment = null; + } + + if (pt == null) { + var s = this.scale; + var tr = this.translate; + var orig = edge.origin; + var geo = this.graph.getCellGeometry(edge.cell); + pt = geo.getTerminalPoint(source); + + // Computes edge-to-edge connection point + if (pt != null) { + pt = new mxPoint(s * (tr.x + pt.x + orig.x), + s * (tr.y + pt.y + orig.y)); + + // Finds nearest segment on edge and computes intersection + if (terminal != null && terminal.absolutePoints != null) { + var seg = mxUtils.findNearestSegment(terminal, pt.x, pt.y); + + // Finds orientation of the segment + var p0 = terminal.absolutePoints[seg]; + var pe = terminal.absolutePoints[seg + 1]; + var horizontal = (p0.x - pe.x == 0); + + // Stores the segment in the edge state + var key = (source) ? 'sourceConstraint' : 'targetConstraint'; + var value = (horizontal) ? 'horizontal' : 'vertical'; + edge.style[key] = value; + + // Keeps the coordinate within the segment bounds + if (horizontal) { + pt.x = p0.x; + pt.y = Math.min(pt.y, Math.max(p0.y, pe.y)); + pt.y = Math.max(pt.y, Math.min(p0.y, pe.y)); + } else { + pt.y = p0.y; + pt.x = Math.min(pt.x, Math.max(p0.x, pe.x)); + pt.x = Math.max(pt.x, Math.min(p0.x, pe.x)); + } + } + } + // Computes constraint connection points on vertices and ports + else if (terminal != null && terminal.cell.geometry.relative) { + pt = new mxPoint(this.getRoutingCenterX(terminal), + this.getRoutingCenterY(terminal)); + } + } + + edge.setAbsoluteTerminalPoint(pt, source); + }; + </script> + + <!-- + Overrides methods to preview and create new edges. + --> + <script type="text/javascript"> + // Sets source terminal point for edge-to-edge connections. + mxConnectionHandler.prototype.createEdgeState = function(me) { + var edge = this.graph.createEdge(); + + if (this.sourceConstraint != null && this.previous != null) { + edge.style = mxConstants.STYLE_EXIT_X + '=' + this.sourceConstraint.point.x + ';' + + mxConstants.STYLE_EXIT_Y + '=' + this.sourceConstraint.point.y + ';'; + } else if (this.graph.model.isEdge(me.getCell())) { + var scale = this.graph.view.scale; + var tr = this.graph.view.translate; + var pt = new mxPoint(this.graph.snap(me.getGraphX() / scale) - tr.x, + this.graph.snap(me.getGraphY() / scale) - tr.y); + edge.geometry.setTerminalPoint(pt, true); + } + + return this.graph.view.createState(edge); + }; + + mxConnectionHandler.prototype.isStopEvent = function(me) { + return me.getState() != null || mxEvent.isRightMouseButton(me.getEvent()); + }; + + // Updates target terminal point for edge-to-edge connections. + mxConnectionHandlerUpdateCurrentState = mxConnectionHandler.prototype.updateCurrentState; + mxConnectionHandler.prototype.updateCurrentState = function(me) { + mxConnectionHandlerUpdateCurrentState.apply(this, arguments); + + if (this.edgeState != null) { + this.edgeState.cell.geometry.setTerminalPoint(null, false); + + if (this.shape != null && this.currentState != null && + this.currentState.view.graph.model.isEdge(this.currentState.cell)) { + var scale = this.graph.view.scale; + var tr = this.graph.view.translate; + var pt = new mxPoint(this.graph.snap(me.getGraphX() / scale) - tr.x, + this.graph.snap(me.getGraphY() / scale) - tr.y); + this.edgeState.cell.geometry.setTerminalPoint(pt, false); + } + } + }; + + // Updates the terminal and control points in the cloned preview. + mxEdgeSegmentHandler.prototype.clonePreviewState = function(point, terminal) { + var clone = mxEdgeHandler.prototype.clonePreviewState.apply(this, arguments); + clone.cell = clone.cell.clone(); + + if (this.isSource || this.isTarget) { + clone.cell.geometry = clone.cell.geometry.clone(); + + // Sets the terminal point of an edge if we're moving one of the endpoints + if (this.graph.getModel().isEdge(clone.cell)) { + clone.cell.geometry.setTerminalPoint(point, this.isSource); + } else { + clone.cell.geometry.setTerminalPoint(null, this.isSource); + } + } + + return clone; + }; + + var mxEdgeHandlerConnect = mxEdgeHandler.prototype.connect; + mxEdgeHandler.prototype.connect = function(edge, terminal, isSource, isClone, me) { + var result = null; + var model = this.graph.getModel(); + var parent = model.getParent(edge); + + model.beginUpdate(); + try { + result = mxEdgeHandlerConnect.apply(this, arguments); + var geo = model.getGeometry(result); + + if (geo != null) { + geo = geo.clone(); + var pt = null; + + if (model.isEdge(terminal)) { + pt = this.abspoints[(this.isSource) ? 0 : this.abspoints.length - 1]; + pt.x = pt.x / this.graph.view.scale - this.graph.view.translate.x; + pt.y = pt.y / this.graph.view.scale - this.graph.view.translate.y; + + var pstate = this.graph.getView().getState( + this.graph.getModel().getParent(edge)); + + if (pstate != null) { + pt.x -= pstate.origin.x; + pt.y -= pstate.origin.y; + } + + pt.x -= this.graph.panDx / this.graph.view.scale; + pt.y -= this.graph.panDy / this.graph.view.scale; + } + + geo.setTerminalPoint(pt, isSource); + model.setGeometry(edge, geo); + } + } finally { + model.endUpdate(); + } + + return result; + }; + </script> + <!-- + Adds in-place highlighting for complete cell area (no hotspot). + --> + <script type="text/javascript"> + mxConnectionHandlerCreateMarker = mxConnectionHandler.prototype.createMarker; + mxConnectionHandler.prototype.createMarker = function() { + var marker = mxConnectionHandlerCreateMarker.apply(this, arguments); + + // Uses complete area of cell for new connections (no hotspot) + marker.intersects = function(state, evt) { + return true; + }; + + return marker; + }; + + mxEdgeHandlerCreateMarker = mxEdgeHandler.prototype.createMarker; + mxEdgeHandler.prototype.createMarker = function() { + var marker = mxEdgeHandlerCreateMarker.apply(this, arguments); + + // Adds in-place highlighting when reconnecting existing edges + marker.highlight.highlight = this.graph.connectionHandler.marker.highlight.highlight; + + return marker; + } + </script> + <!-- + Implements a perpendicular wires connection edge style + --> + <script type="text/javascript"> + mxEdgeStyle.WireConnector = function(state, source, target, hints, result) { + state.cell.waypoints = state.cell.geometry.points; + // Creates array of all way- and terminalpoints + var pts = state.absolutePoints; + var horizontal = true; + var hint = null; + + // Gets the initial connection from the source terminal or edge + if (source != null && state.view.graph.model.isEdge(source.cell)) { + horizontal = state.style['sourceConstraint'] == 'horizontal'; + } + // If the source terminal is a Split Block, set the horizontal false + else if (source != null && source.cell.name == 'SPLIT_f') { + if (state.cell.source != null) { + // If the port is the third child of splitBlock, only then set the horizontal as false + if (state.cell.source == state.cell.source.parent.getChildAt(2)) { + horizontal = state.style['sourceConstraint'] == 'horizontal'; + } + } + } else if (source != null) { + horizontal = source.style['portConstraint'] != 'vertical'; + + // Checks the direction of the shape and rotates + var direction = source.style[mxConstants.STYLE_DIRECTION]; + + if (direction == 'north' || direction == 'south') { + horizontal = !horizontal; + } + } + + // Adds the first point + var pt = pts[0]; + + /* @jiteshjha splitBlock + */ + if (state.cell.getGeometry().getTerminalPoint(true) != null) { + source.cell['sourcePoint'] = state.cell.getGeometry().getTerminalPoint(true); + } + + if (pt == null && source != null) { + pt = new mxPoint(state.view.getRoutingCenterX(source), state.view.getRoutingCenterY(source)); + } else if (pt != null) { + pt = pt.clone(); + } + + var first = pt; + if (state.cell.getGeometry().getTerminalPoint(false) != null) { + target.cell['sourcePoint'] = state.cell.getGeometry().getTerminalPoint(false); + } + + // Adds the waypoints + if (hints != null && hints.length > 0) { + + + for (var i = 0; i < hints.length; i++) { + horizontal = !horizontal; + hint = state.view.transformControlPoint(state, hints[i]); + + if (horizontal) { + if (pt.y != hint.y) { + pt.y = hint.y; + result.push(pt.clone()); + } + } else if (pt.x != hint.x) { + pt.x = hint.x; + result.push(pt.clone()); + } + } + } else { + hint = pt; + } + + // Adds the last point + pt = pts[pts.length - 1]; + if (pt == null && target != null) { + pt = new mxPoint(state.view.getRoutingCenterX(target), state.view.getRoutingCenterY(target)); + + } + + if (horizontal) { + if (pt.y != hint.y && first.x != pt.x) { + result.push(new mxPoint(pt.x, hint.y)); + } + } else if (pt.x != hint.x && first.y != pt.y) { + result.push(new mxPoint(hint.x, pt.y)); + } + + // If the target of the edge is a splitBlock, push final coordinate as vertical. + if (state.cell.target != null) { + if (state.cell.target.parent.name == "SPLIT_f") { + result.pop(); + result.push(new mxPoint(hint.x, pt.y)); + } + } + }; + + mxStyleRegistry.putValue('wireEdgeStyle', mxEdgeStyle.WireConnector); + + // This connector needs an mxEdgeSegmentHandler + mxGraphCreateHandler = mxGraph.prototype.createHandler; + mxGraph.prototype.createHandler = function(state) { + var result = null; + + if (state != null) { + if (this.model.isEdge(state.cell)) { + var style = this.view.getEdgeStyle(state); + + if (style == mxEdgeStyle.WireConnector) { + return new mxEdgeSegmentHandler(state); + } + } + } + + return mxGraphCreateHandler.apply(this, arguments); + }; + </script> + +</head> + +<!-- Page passes the container for the graph to the program --> + +<body onload="main(document.getElementById('graphContainer'), + document.getElementById('outlineContainer'), + document.getElementById('toolbarContainer'), + document.getElementById('sidebarContainer'), + document.getElementById('statusContainer'));" style="margin:0px;"> + + <!-- Creates a container for the splash screen --> + <div id="splash" style="position:absolute;top:0px;left:0px;width:100%;height:100%;background:white;z-index:1;"> + <center id="splash" style="padding-top:230px;"> + <img src="images/loading.gif"> + </center> + </div> + + <!-- Creates a container for the sidebar --> + <div id="toolbarContainer" style="position:absolute;white-space:nowrap;overflow:hidden;top:0px;left:0px;max-height:24px;height:36px;right:0px;padding:6px;background-image:url('images/toolbar_bg.gif');"> + </div> + + <!-- Creates a container for the toolbox --> + <div id="sidebarContainer" class="ui-accordion ui-widget ui-helper-reset" style="position:absolute;overflow:scroll;top:36px;left:0px;bottom:36px;max-width:266px;width:270px;padding-top:10px;padding-left:4px;"> + </div> + + <!-- Creates a container for the graph --> + <div id="graphContainer" style="position:absolute;overflow:hidden;top:36px;left:270px;bottom:36px;right:0px;background-image:url('images/grid.gif');cursor:default;"> + </div> + + <!-- Creates a container for the outline --> + <div id="outlineContainer" style="position:absolute;overflow:hidden;top:36px;right:0px;width:200px;height:140px;background:transparent;border-style:solid;border-color:black;"> + </div> + + <!-- Creates a container for the sidebar --> + <div id="statusContainer" style="text-align:right;position:absolute;overflow:hidden;bottom:0px;left:0px;max-height:24px;height:36px;right:0px;color:white;padding:6px;background-image:url('images/toolbar_bg.gif');"> + <div style="font-size:10pt;float:left;"> + <a href="http://fossee.in/" target="_tab">FOSSEE</a> + </div> + </div> + + <!-- Secret --> + <p class="accordion-expand-holder" style="display:none"> + <a id='toggleBlocks' class="accordion-expand-all">Expand All</a> + </p> + +</body> +<!-- It's good if this part happens after the entire page has loaded--> +<script type="text/javascript"> + // Preload all images + var directory = ["/blocks/", "/images/", "/palettes/"]; + for (folder in directory) { + $.ajax({ + type: "POST", + + // Invoke filenames.php + url: "filenames.php", + + // Receive the resultant filenames from the php script in JSON format + dataType: "json", + + // Add url for the required folder + data: { + url: directory[folder] + }, + success: function(data) { + function preload(sources) { + + /* + * @Parameter: sources will have the required filenames in the mentioned folder + * For each image url, make a new image to enable preloading + */ + for (i in sources) { + var image = new Image(); + image.src = sources[i]; + } + } + preload(data); + } + }); + } + + //Find out more here: http://stackoverflow.com/questions/12843418/jquery-ui-accordion-expand-collapse-all + $(window).load(function() { + var headers = $('#sidebarContainer .accordion-header'); + var contentAreas = $('#sidebarContainer .ui-accordion-content ').hide(); + var expandLink = $('.accordion-expand-all'); + + // add the accordion functionality + headers.click(function() { + var panel = $(this).next(); + var isOpen = panel.is(':visible'); + + // open or close as necessary + panel[isOpen ? 'slideUp' : 'slideDown']() + // trigger the correct custom event + .trigger(isOpen ? 'hide' : 'show'); + + // stop the link from causing a pagescroll + return false; + }); + + // hook up the expand/collapse all + expandLink.click(function() { + var isAllOpen = $(this).data('isAllOpen'); + + contentAreas[isAllOpen ? 'hide' : 'show']() + .trigger(isAllOpen ? 'hide' : 'show'); + }); + + // when panels open or close, check to see if they're all open + contentAreas.on({ + // whenever we open a panel, check to see if they're all open + // if all open, swap the button to collapser + show: function() { + var isAllOpen = !contentAreas.is(':hidden'); + if (isAllOpen) { + expandLink.text('Collapse All') + .data('isAllOpen', true); + } + }, + // whenever we close a panel, check to see if they're all open + // if not all open, swap the button to expander + hide: function() { + var isAllOpen = !contentAreas.is(':hidden'); + if (!isAllOpen) { + expandLink.text('Expand All') + .data('isAllOpen', false); + } + } + }); + }); +</script> + +</html>
\ No newline at end of file |