/** *Stack holds all the figures on the screen *It will also hold the groups formed on the screen *@this {Stack} *@constructor **/ function Stack(){ /**Keeps all the figures on the canvas*/ this.figures = []; /**Keeps all the groups in the canvas*/ this.groups = []; this.containers = []; /**Keeps current generated Id. Not for direct access*/ this.currentId = 0; /**Keeps a map like (figure Id, figure index). It is similar to an index*/ this.idToIndex = []; /**Type used in serialization*/ this.oType = 'Stack'; } /**Creates a {Stack} out of JSON parsed object *@param {JSONObject} o - the JSON parsed object *@return {Stack} a newly constructed Stack *@author Alex Gheorghiu **/ Stack.load = function(o){ var newStack = new Stack(); //empty constructor newStack.figures = Figure.loadArray(o.figures); newStack.containers = Container.loadArray(o.containers); newStack.groups = Group.loadArray(o.groups); newStack.figureSelectedIndex = o.figureSelectedIndex; newStack.currentId = o.currentId; newStack.idToIndex = o.idToIndex; return newStack; } Stack.prototype = { constructor: Stack, /**Creates a {Group} based on a set of figure IDs * Group is created by 1. creating a Group and 2. setting Figure's groupId property to the new id of the Group *@param {Array} figureIds - all the ids of {Figure}s *@param {Number} groupId - the id of the {Group} (optional) *@return {Number} - the id of newly created Group **/ groupCreate: function (figureIds, groupId) { //we should allow to create more than one temporary group for (var i = 0; i < this.groups.length; i++) { if (this.groups[i].permanent == false) { throw 'Stack::groupCreate() You can not create new groups while you have temporary groups alive'; } } //create group var g = new Group(groupId); //add figures to group for (var i = 0; i < figureIds.length; i++) { var f = this.figureGetById(figureIds[i]); f.groupId = g.id; } var bounds = g.getBounds(); g.rotationCoords.push(new Point(bounds[0] + (bounds[2] - bounds[0]) / 2, bounds[1] + (bounds[3] - bounds[1]) / 2)); g.rotationCoords.push(new Point(bounds[0] + (bounds[2] - bounds[0]) / 2, bounds[1])); //save group to STACK this.groups.push(g); return g.id; }, /**Finds a {Group} by it's id *@param {Number} groupId - the {Group}'s id *@return {Group} founded group of null if none finded **/ groupGetById: function (groupId) { for (var i = 0; i < this.groups.length; i++) { if (this.groups[i].id == groupId) { return this.groups[i]; } } return null; }, /**Destroy a group by it's Id. *I will be removed from Stack's groups and any member figure will be removed *from group (by set the groupId to -1) * @param {Number} groupId - the id of the group **/ groupDestroy: function (groupId) { var index = -1; //search for the group for (var i = 0; i < this.groups.length; i++) { if (this.groups[i].id == groupId) { index = i; break; } } //remove it if (index > -1) { //remove Group this.groups.splice(index, 1); //remove the Figures from Group var groupFigures = this.figureGetByGroupId(groupId); for (var i = 0; i < groupFigures.length; i++) { groupFigures[i].groupId = -1; } } }, /**Removes any temporary group*/ groupRemoveTemporary: function () { throw Exception("Not implemented"); }, /**See if this STACK is equal to another. It is a shallow compare. *@param {Stack} anotherStack - the other STACK object *@return {Boolean} - true if equals, false otherwise **/ equals: function (anotherStack) { var msg = ''; if (!anotherStack instanceof Stack) { return false; msg += 'not same class'; } //test figures if (this.figures.length != anotherStack.figures.length) { msg += 'not same nr of figures'; return false; } for (var i = 0; i < this.figures.length; i++) { if (!this.figures[i].equals(anotherStack.figures[i])) { msg += 'figures not the same'; return false; } } //test groups if (this.groups.length != anotherStack.groups.length) { msg += 'not same nr of groups'; return false; } for (var i = 0; i < this.groups.length; i++) { if (!this.groups[i].equals(anotherStack.groups[i])) { msg += 'groups not the same'; return false; } } //test idToIndex for (var i = 0; i < this.figures.idToIndex; i++) { if (this.idToIndex[i] != undefined //if not undefined && anotherStack.idToIndex != undefined //if not undefined && this.idToIndex[i] != anotherStack.idToIndex[i]) { msg += 'not same idToIndex'; return false; } } if (this.currentId != anotherStack.currentId) { msg += 'not same currentId'; return false; } if (msg != '') { alert(msg); } return true; }, /**Generates an returns a new unique ID *@return {Number} - next id*/ generateId: function () { return this.currentId++; }, /**Adds a figure to the Stack of figures *@param {Figure} figure - the figure to add **/ figureAdd: function (figure) { this.figures.push(figure); this.idToIndex[figure.id] = this.figures.length - 1; }, containerAdd: function (container) { this.containers.push(container); }, /*code taken from ConnectionPoint.removeConnector *@param {Figure} figure - the figure to remove *@deprecated **/ figureRemove_deprecated: function (figure) { var index = -1; for (var i = 0; i < this.figures.length; i++) { if (this.figures[i] == figure) { index = i; break; } } CONNECTOR_MANAGER.connectionPointRemoveAllByParent(figure.id); if (index > -1) { this.figures.splice(index, 1); for (var i = index; i < this.figures.length; i++) { this.idToIndex[this.figures[i].id] = i; } } if (index < this.figureSelectedIndex && index != -1) { this.figureSelectedIndex--; } }, /**Removes a container by it's id *@param {Number} containerId - the {Container}'s id *@author Alex Gheorghiu **/ containerRemoveById: function (containerId) { var index = -1; for (var i = 0; i < this.containers.length; i++) { if (this.containers[i].id === containerId) { index = i; break; } } if (index > -1) { //remove figure this.containers.splice(index, 1); //reindex // this.reindex(); } }, /**Removes a figure by it's id *@param {Number} figId - the {Figure}'s id *@author Alex Gheorghiu **/ figureRemoveById: function (figId) { var index = -1; for (var i = 0; i < this.figures.length; i++) { if (this.figures[i].id == figId) { index = i; break; } } if (index > -1) { //remove all affected Glues var cCPs = CONNECTOR_MANAGER.connectionPointGetAllByParent(figId); //get all connection points var length = cCPs.length; var k; for (k = 0; k < length; k++) { CONNECTOR_MANAGER.glueRemoveAllByFirstId(cCPs[k].id); } // remove figure's connection points CONNECTOR_MANAGER.connectionPointRemoveAllByParent(figId); //remove figure this.figures.splice(index, 1); //reindex this.reindex(); } }, /**Recreates the index (id, index) *@author Alex Gheorghiu **/ reindex: function () { for (var i = 0; i < this.figures.length; i++) { this.idToIndex[this.figures[i].id] = i; } }, /**Deletes all the figure and reset any index*/ reset: function () { this.figures = []; this.figureSelectedIndex = -1; this.currentId = 0; }, /**Find the storage index of a figure *@param {Figure} figure - the figure you search for *@return {Number} - the index where you can find the Figure or -1 if not founded **/ getIndex: function (figure) { for (var i = 0; i < this.figures.length; i++) { if (this.figures[i] == figure) { return i; } } return -1; }, /**Returns all figures from a group *@param {Number} groupId - the id of the group *@return {Array} - the {Array} of {Figure}s that belong to the group **/ figureGetByGroupId: function (groupId) { var groupFigures = []; for (var i = 0; i < this.figures.length; i++) { if (this.figures[i].groupId == groupId) { groupFigures.push(this.figures[i]); } } return groupFigures; }, /**Returns all figures ids from a group *@param {Number} groupId - the id of the group *@return {Array} - the {Array} of {Number}s that belong to the group **/ figureGetIdsByGroupId: function (groupId) { var groupFiguresIds = []; for (var i = 0; i < this.figures.length; i++) { if (this.figures[i].groupId == groupId) { groupFiguresIds.push(this.figures[i].id); } } return groupFiguresIds; }, /**Returns a figure by id *@param {Number} id - the id of the figure *@return {Figure} - the figure object or null if no figure with that id found *TODO: use idToIndex to speed up the search....well there is no search at all :) **/ figureGetById: function (id) { for (var i = 0; i < this.figures.length; i++) { if (this.figures[i].id == id) { return this.figures[i]; } } return null; }, /** *Returns first figure glued to a connector *@param {Number} connectorId - the id of the connector *@return {Figure} - the figure connected, or null if none **/ figureGetAsFirstFigureForConnector: function (connectorId) { Log.group("Stack:figureGetAsFirstFigureForConnector"); /*Algorithm *Connector -> first Connector's ConnectionPoint-> Glue -> Figure's ConnectionPoint -> Figure **/ var figure = null; //var connector = CONNECTOR_MANAGER.connectorGetById(connectorId); Log.debug("Connector id = " + connectorId); var startConnectionPoint = CONNECTOR_MANAGER.connectionPointGetFirstForConnector(connectorId); Log.debug("ConnectionPoint id = " + startConnectionPoint.id); var startGlue = CONNECTOR_MANAGER.glueGetBySecondConnectionPointId(startConnectionPoint.id)[0]; if (startGlue) { Log.debug("Glue id1 = (" + startGlue.id1 + ", " + startGlue.id2 + ')'); var figureConnectionPoint = CONNECTOR_MANAGER.connectionPointGetById(startGlue.id1); Log.debug("Figure's ConnectionPoint id = " + figureConnectionPoint.id); figure = this.figureGetById(figureConnectionPoint.parentId); } else { Log.debug("no glue"); } Log.groupEnd(); return figure; }, /** *Returns second figure glued to a connector *@param {Number} connectorId - the id of the connector *@return {Figure} - the figure connected, or null if none **/ figureGetAsSecondFigureForConnector: function (connectorId) { Log.group("Stack:figureGetAsSecondFigureForConnector"); /*Algorithm *Connector -> first Connector's ConnectionPoint-> Glue -> Figure's ConnectionPoint -> Figure **/ var figure = null; //var connector = CONNECTOR_MANAGER.connectorGetById(connectorId); Log.debug("Connector id = " + connectorId); var endConnectionPoint = CONNECTOR_MANAGER.connectionPointGetSecondForConnector(connectorId); Log.debug("ConnectionPoint id = " + endConnectionPoint.id); var startGlue = CONNECTOR_MANAGER.glueGetBySecondConnectionPointId(endConnectionPoint.id)[0]; if (startGlue) { Log.debug("Glue id1 = (" + startGlue.id1 + ", " + startGlue.id2 + ')'); var figureConnectionPoint = CONNECTOR_MANAGER.connectionPointGetById(startGlue.id1); Log.debug("Figure's ConnectionPoint id = " + figureConnectionPoint.id); figure = this.figureGetById(figureConnectionPoint.parentId); } else { Log.debug("no glue"); } Log.groupEnd(); return figure; }, /** *Returns the Figure's id if there is a figure for the given coordinates *It will return the first figure we found from top to bottom (Z-order) *@param {Number} x - the value on Ox axis *@param {Number} y - the value on Ox axis *@return {Number} - the id of the figure or -1 if none found *@author Alex Gheorghiu **/ figureGetByXY: function (x, y) { var id = -1; for (var i = this.figures.length - 1; i >= 0; i--) { if (this.figures[i].contains(x, y)) { id = this.figures[i].id; break; /* *Some old stuff left from a previous version. *TODO: delete it if no longer needed after the grouping has been (re)done *we always want to get the group of a figure, not the figure itself where possible *(this section only does anything when we change the order of some items *var figure = this.figures[i]; *While the figure belongs to a group or the group is part of another group *we will go up in the ancestor hierarchy * while(figure.groupId >= 0){ * figure = this.figureGetById(figure.groupId); * } return figure; */ } //end if } //end for return id; }, /** *Returns the Text primitive of parent figure for the given coordinates *It will return the first Text primitive we found from top to bottom (Z-order) *@param {Number} fId - the id of figure - parent of target Text primitive *@param {Number} x - the value on Ox axis *@param {Number} y - the value on Oy axis *@return {Number} - the id value of Text primitive or -1 if none found *@author Artyom Pokatilov **/ textGetByFigureXY: function (fId, x, y) { var figureLength = this.figures.length; for (var i = figureLength - 1; i >= 0; i--) { var figure = this.figures[i]; if (figure.id === fId) { var primitiveLength = figure.primitives.length; for (var j = primitiveLength - 1; j >= 0; j--) { //top to bottom var primitive = figure.primitives[j]; if ((primitive.oType === "Text") && primitive.contains(x, y)) { return primitive.id; } } } //end if } //end for return -1; }, /** *Returns the Text primitive of parent container for the given coordinates *It will return the first Text primitive we found from top to bottom (Z-order) *@param {Number} cId - the id of container - parent of target Text primitive *@param {Number} x - the value on Ox axis *@param {Number} y - the value on Oy axis *@return {Number} - the id value of Text primitive or -1 if none found *@author Artyom Pokatilov **/ textGetByContainerXY: function (cId, x, y) { var containerLength = this.containers.length; for (var i = containerLength - 1; i >= 0; i--) { var container = this.containers[i]; if (container.id === cId) { var primitiveLength = container.primitives.length; for (var j = primitiveLength - 1; j >= 0; j--) { var primitive = container.primitives[j]; if ((primitive.oType == "Text") && primitive.contains(x, y)) { return primitive.id; } } } //end if } //end for return -1; }, /** *Returns the Container's id if there is a container for the given coordinates *It will return the first container we found from top to bottom (Z-order) *@param {Number} x - the value on Ox axis *@param {Number} y - the value on Ox axis *@return {Number} - the id of the container or -1 if none found *@author Alex Gheorghiu **/ containerGetByXY: function (x, y) { var id = -1; for (var i = this.containers.length - 1; i >= 0; i--) { if (this.containers[i].contains(x, y)) { id = this.containers[i].id; break; } //end if } //end for return id; }, /** *Returns the Container's id if there is a container for the given coordinates *It will return the first container we found from top to bottom (Z-order) *@param {Number} x - the value on Ox axis *@param {Number} y - the value on Ox axis *@return {Number} - the id of the {Container} or -1 if none found *@author Alex Gheorghiu **/ containerGetByXYOnEdge: function (x, y) { var id = -1; for (var i = this.containers.length - 1; i >= 0; i--) { if (this.containers[i].onEdge(x, y)) { id = this.containers[i].id; break; } //end if } //end for return id; }, /**Returns a container by id *@param {Number} id - the id of the container *@return {Container} - the container object or null if no container with that id found **/ containerGetById: function (id) { for (var i = 0; i < this.containers.length; i++) { if (this.containers[i].id == id) { return this.containers[i]; } } return null; }, /** *Returns an Array of Figure's id if there are figures for the given coordinates *@param {Number} x - the value on Ox axis *@param {Number} y - the value on Ox axis *@return {Array} of {Number} - the array of {Figure} ids. Figures are arranged from top (closer to viewer) * to bottom (far from viewer) *@author Alex Gheorghiu **/ figuresGetByXY: function (x, y) { var ids = []; for (var i = this.figures.length - 1; i >= 0; i--) { if (this.figures[i].contains(x, y)) { ids.push(this.figures[i].id); } } return ids; }, /**Returns a imageFrame by figureId *@param {Number} figureId - the figureId of the Figure *@return {ImageFrame} - the ImageFrame object or null if no ImageFrame with that found **/ figuresImagePrimitiveGetByFigureId: function (figureId) { var f = this.figureGetById(figureId); var imageFrame = null; for (var i = 0; i < f.primitives.length; i++) { if (f.primitives[i].oType == 'ImageFrame') { imageFrame = f.primitives[i]; } } return imageFrame; }, /**Returns a Text by figureId *@param {Number} figureId - the figureId of the Figure *@return {Text} - the Text object or null if no Text with that found **/ figuresTextPrimitiveGetByFigureId: function (figureId) { var f = this.figureGetById(figureId); var text = null; if (f) { for (var i = 0; i < f.primitives.length; i++) { if (f.primitives[i].oType == 'Text') { text = f.primitives[i]; } } } return text; }, /* Sets the z index of a figure * @param {Figure} figure - the figure to move * @param {Number} position - the Z index. The bigger value means closer to user (last painted); * @deprecated * */ setPosition_deprecated: function (figure, position) { var figureIndex = -1; for (var i = 0; i < this.figures.length; i++) { if (this.figures[i] == figure) { figureIndex = i; } } if (figureIndex != -1 && position >= 0 && position < this.figures.length) { //tempFigures=[]; //tempFigures.spli //if(position * Note: it's just a simple switch between current position and new position *

* Zack: Is it just a switch? All you are doing is swapping, what if the user didn't want to swap, but shift up * using this method, if you have 5 figures, and bring the very back one to the front, the front figure * is moved to the very back, surely the correct solution is to move everything back 1, and move the selected * figure to the front *

* Alex: What you are saying is an insert at a certain position which is not what we want with this method. * Maybe we should rename it swapToPosition(...) or swapIntoPosition(...) *

* @param {Number} figureId - the id of the {Figure} * @param {Number} newPosition - the new Z index of the figure. The bigger the value, close to user (last painted); * @author Alex Gheorghiu * */ swapToPosition: function (figureId, newPosition) { var oldPosition = this.idToIndex[figureId]; if (oldPosition != -1 /**oldPosition valid*/ && newPosition >= 0 && newPosition < this.figures.length /**newPosition in vector bounds*/) { //update idToIndex index this.idToIndex[figureId] = newPosition; this.idToIndex[this.figures[newPosition].id] = oldPosition; //switch figures var temp = this.figures[oldPosition]; this.figures[oldPosition] = this.figures[newPosition]; this.figures[newPosition] = temp; } }, /** *Insert a figure into a position and shifts all other figures *Used by moveToBack and moveToFront, sets the selected figure to the selected position, and rotates all other figures away *@example *[0] = 0 *[1] = 1 *[2] = 2 * *change to * *@example *[0] = 1 *[1] = 2 *[2] = 0 * *@example *figureA *figureB *figureC * *change to * *@example *figureB *figureC *figureA *@param {Number} figureId - the id of the figure *@param {Number} newPosition - the new position of the figure *@author Zack Newsham */ setPosition: function (figureId, newPosition) { //are we moving forward or back? var oldPosition = this.idToIndex[figureId]; var temp = this.figures[oldPosition]; var direction = -1; //move to back if (oldPosition < newPosition) {//move to front direction = 1; } Log.info(direction); //while i between oldposition and new position, move 1 in given direction for (var i = oldPosition; i != newPosition; i += direction) { this.figures[i] = this.figures[i + direction]; //set the figure this.idToIndex[this.figures[i].id] = i; //change the index } this.figures[newPosition] = temp; //replace the temp this.idToIndex[this.figures[newPosition].id] = newPosition; }, /**Test if an (x,y) is over a figure *@param {Number} x - the x coordinates *@param {Number} y - the y coordinates *@return {Boolean} - true if over a figure, false otherwise **/ figureIsOver: function (x, y) { var found = false; for (var i = 0; i < this.figures.length; i++) { var figure = this.figures[i]; if (figure.contains(x, y)) { found = true; break; } } return found; }, /**Test if an (x,y) is over a container *@param {Number} x - the x coordinates *@param {Number} y - the y coordinates *@return {Boolean} - true if over a container, false otherwise **/ containerIsOver: function (x, y) { var found = false; for (var i = 0; i < this.containers.length; i++) { var container = this.containers[i]; if (container.contains(x, y)) { found = true; break; } } return found; }, /**Test if an (x,y) is over a Container's edge (rigt on its edge) *@param {Number} x - the x coordinates *@param {Number} y - the y coordinates *@return {Boolean} - true if over a container, false otherwise **/ containerIsOnEdge: function (x, y) { var found = false; for (var i = 0; i < this.containers.length; i++) { var container = this.containers[i]; if (container.onEdge(x, y)) { found = true; break; } } return found; }, /**Return the bounds for all objects on work area (canvas). * *@return {Array} - returns [minX, minY, maxX, maxY] - bounds, where * all objects on canvas (Figures/Containers/Connectors) are in the bounds. * *@author Artyom Pokatilov **/ getWorkAreaBounds: function () { var minX; var maxX; var minY; var maxY; var unset = true; // defines if there were no object - no bounds set // function to run for any bounds in format [minX, minY, maxX, maxY] // compares given bounds with current values of canvas var compareAndSet = function (bounds) { // if minX is unset or bigger than given if (typeof (minX) === 'undefined' || minX > bounds[0]) { minX = bounds[0]; } // if minY is unset or bigger than given if (typeof (minY) === 'undefined' || minY > bounds[1]) { minY = bounds[1]; } // if maxX is unset or bigger than given if (typeof (maxX) === 'undefined' || bounds[2] > maxX) { maxX = bounds[2]; } // if maxY is unset or bigger than given if (typeof (maxY) === 'undefined' || bounds[3] > maxY) { maxY = bounds[3]; } // if once function were ran - one object setted it's bounds unset = false; }; var i; // get bounds of containers var containerLength = this.containers.length; for (i = 0; i < containerLength; i++) { compareAndSet(this.containers[i].getBounds()); } // get bounds of figures var figureLength = this.figures.length; for (i = 0; i < figureLength; i++) { compareAndSet(this.figures[i].getBounds()); } // get bounds of connectors var connectorLength = CONNECTOR_MANAGER.connectors.length; for (i = 0; i < connectorLength; i++) { compareAndSet(CONNECTOR_MANAGER.connectors[i].getBounds()); } // bounds were setted/changed? if (unset) { // return full canvas size return [0, 0, canvasProps.getWidth(), canvasProps.getHeight()]; } else { // return setted new bounds return [minX, minY, maxX, maxY]; } }, /** *Apply a transformation to all Figures and Containers in Stack *@param {Matrix} matrix - a matrix of numbers * *@author Artyom Pokatilov **/ transform: function (matrix) { // translate Containers var i; var containerLength = this.containers.length; for (i = 0; i < containerLength; i++) { this.containers[i].transform(matrix); } // translate Figures var figureLength = this.figures.length; for (i = 0; i < figureLength; i++) { // Does Figure is placed outside of container? if (CONTAINER_MANAGER.getContainerForFigure(this.figures[i].id) === -1) { this.figures[i].transform(matrix); } // otherwise it is already transformed } }, /**Paints all {Figure}s from back to top (Z order) *@param {Context} context - the 2D context *@param {boolean} ignoreSelection - if ignoreSelection is set to true selections will not be painted **/ paint: function (context, ignoreSelection) { // Log.group("STACK: paint"); /*The idea is to paint from bottom to top * 1. figures (first) * 2. connectors * 3. handlers * 4. selection area (last) **/ if (DIAGRAMO.debug) { var pos = 1; context.save(); context.font = "10px Arial"; context.fillStyle = '#000000'; context.strokeStyle = '#000000'; context.lineWidth = 1; context.fillText("state: " + state, 0, 10 * pos++); context.fillText("selectedFigureId: : " + selectedFigureId, 0, 10 * pos++); context.fillText("selectedGroupId: : " + selectedGroupId, 0, 10 * pos++); context.fillText("selectedContainerId: : " + selectedContainerId, 0, 10 * pos++); if (selectedGroupId != -1) { var logGroup = this.groupGetById(selectedGroupId); context.fillText("permanent: : " + logGroup.permanent, 0, 10 * pos++); } context.fillText("selectedConnectorId: : " + selectedConnectorId, 0, 10 * pos++); if (selectedConnectorId != -1) { var connector = CONNECTOR_MANAGER.connectorGetById(selectedConnectorId); context.fillText("connector type: : " + connector.type, 0, 10 * pos++); } context.restore(); } //paint containers for (var i = 0; i < this.containers.length; i++) { context.save(); this.containers[i].paint(context); context.restore(); } //end paint containers //paint figures for (var i = 0; i < this.figures.length; i++) { if (!context.save) { alert("save() no present") } context.save(); this.figures[i].paint(context); context.restore(); //if we are connecting something we should paint connection points too if (state == STATE_CONNECTOR_PICK_FIRST || state == STATE_CONNECTOR_PICK_SECOND || state == STATE_CONNECTOR_MOVE_POINT) { CONNECTOR_MANAGER.connectionPointPaint(context, this.figures[i].id); } } //end for //if we are connecting something we should paint currentCloud too if (state == STATE_CONNECTOR_PICK_FIRST || state == STATE_CONNECTOR_PICK_SECOND || state == STATE_CONNECTOR_MOVE_POINT) { CONNECTOR_MANAGER.connectionCloudPaint(context); } //paint connector(s) CONNECTOR_MANAGER.connectorPaint(context, selectedConnectorId); //paint handlers for selected shape if (state == STATE_FIGURE_SELECTED) { //FIGURE var f = this.figureGetById(selectedFigureId); //self dgq if (f) { f.style.gradientBounds = f.getBounds(); HandleManager.shapeSet(f); } //alert('Paint handles'); if (!ignoreSelection) { HandleManager.paint(context); } } else if (state == STATE_CONNECTOR_SELECTED) { //CONNECTOR var c = CONNECTOR_MANAGER.connectorGetById(selectedConnectorId); HandleManager.shapeSet(c); if (!ignoreSelection) { HandleManager.paint(context); } } else if (state == STATE_CONTAINER_SELECTED) { //CONTAINER var cont = STACK.containerGetById(selectedContainerId); HandleManager.shapeSet(cont); if (!ignoreSelection) { HandleManager.paint(context); } } else if (state == STATE_GROUP_SELECTED) { //GROUP var g = this.groupGetById(selectedGroupId); HandleManager.shapeSet(g); if (!ignoreSelection) { HandleManager.paint(context); } } else if (state == STATE_SELECTING_MULTIPLE) { //SELECTION /* If shift is pressed, then leave the selected figure * or group drawn on screen and allow drawing region in same time*/ if (SHIFT_PRESSED) { if (selectedFigureId != -1) { var f = this.figureGetById(selectedFigureId); HandleManager.paint(context); } if (selectedGroupId != -1) { var g = this.groupGetById(selectedGroupId); HandleManager.paint(context); } } selectionArea.paint(context); Log.info(selectionArea.toString()); } if (DIAGRAMO.debug) { // Log.group("Visual debug"); var colors = { 's0': '#ff0000', 's1_1': '#009900', 's1_2': '#0033ff', 's2_1': '#00ff33', 's2_2': '#ff3399', 's2_3': '#808019', 's2_4': '#e6e64c', 's2_5': '#e67814', 's2_6': '#309bda' }; context.save(); for (var i = 0; i < DIAGRAMO.debugSolutions.length; i++) { var shift = 3 + i * 3; var solution = DIAGRAMO.debugSolutions[i]; // Log.info("Solution: " + solution + " type of " + typeof(solution[2]) + " length: " + solution.length ); // Log.info("Solution points: " + solution[2]); var points = solution[2]; //get points //paint line context.save(); context.strokeStyle = colors[solution[1]]; context.lineWidth = 1; context.beginPath(); context.moveTo(points[0].x + shift, points[0].y + shift); for (var j = 1; j < points.length; j++) { context.lineTo(points[j].x + shift, points[j].y + shift) } //context.closePath(); context.stroke(); context.restore(); //paint points for (var j = 0; j < points.length; j++) { context.save(); // points[j].style.strokeStyle = '#FF0000'; // points[j].paint(context); context.beginPath(); //context.strokeStyle= colors[solution[1]]; context.strokeStyle = '#cccccc'; //context.arc(points[j].x,points[j].y, 2 + i * 3, 0, Math.PI*2, true); context.arc(points[j].x, points[j].y, 3, 0, Math.PI * 2, true); //context.closePath(); context.stroke(); context.restore(); } } //paint the legend pos += 4; for (var solName in colors) { context.save(); context.strokeText(solName, 0, 10 * pos); context.strokeStyle = colors[solName]; context.beginPath(); context.moveTo(50, 10 * pos); context.lineTo(150, 10 * pos); //context.endPath(); context.stroke(); context.restore(); pos += 2; } context.restore(); // Log.groupEnd(); } // Log.groupEnd(); }, /**Convert all STACK to SVG representation *@return {String} - the SVG string representation*/ toSVG: function () { var svg = ''; for (var i = 0; i < this.figures.length; i++) { svg += this.figures[i].toSVG(); } return svg; } }