/** Container holds one or more figure into a visual (and probably conceptual) * unit * * @constructor * @this {Container} * @param {Number} id the id of the Container * @param {Point} topLeft top left {Point} * @param {Point} bottomRight bottom right {Point} * @author Alex */ function Container(id, topLeft, bottomRight) { /**Group's id*/ if(id == null){ this.id = STACK.generateId(); } else{ this.id = id; } this.topLeft = topLeft.clone(); this.bottomRight = bottomRight.clone(); /**An {Array} of primitives that make the figure*/ this.primitives = []; /**An {Array} of primitives*/ this.properties = []; /**The {@link Style} of the polygon*/ this.style = new Style(); this.style.strokeStyle = "#000000"; this.style.fillStyle = "#F9F8F6"; this.style.lineStyle = Style.LINE_STYLE_CONTINOUS; this.style.gradientBounds = this.getBounds(); /**We keep the figure position by having different points *[central point of the figure, the middle of upper edge] * An {Array} or {@link Point}s **/ //TODO: These coordinates are no necessary as we already have topLeft and bottomRight //but this will request changes to code for Container to work this.rotationCoords = [ new Point( (this.topLeft.x + this.bottomRight.x) / 2, (this.topLeft.y + this.bottomRight.y)/2), new Point( (this.topLeft.x + this.bottomRight.x) / 2, this.topLeft.y) ]; //SHAPE - or decoration of the container var headerHeight = 20; // figure's path var containerPath = new Path(); //HEADER var hBottomRight = new Point(this.bottomRight.x, this.topLeft.y + headerHeight); var roundness = 10; var l1 = new Line( new Point(this.topLeft.x, hBottomRight.y), new Point(this.topLeft.x, this.topLeft.y + roundness) ); containerPath.addPrimitive(l1); var c1 = new QuadCurve( new Point(this.topLeft.x, this.topLeft.y + roundness), new Point(this.topLeft.x, this.topLeft.y), new Point(this.topLeft.x + roundness, this.topLeft.y) ); containerPath.addPrimitive(c1); var l2 = new Line( new Point(this.topLeft.x + roundness, this.topLeft.y), new Point(hBottomRight.x - roundness, this.topLeft.y) ); containerPath.addPrimitive(l2); var c2 = new QuadCurve( new Point(hBottomRight.x - roundness, this.topLeft.y), new Point(hBottomRight.x, this.topLeft.y), new Point(hBottomRight.x, this.topLeft.y + roundness) ); containerPath.addPrimitive(c2); var l3 = new Line( new Point(hBottomRight.x, this.topLeft.y + roundness), new Point(hBottomRight.x, hBottomRight.y) ); containerPath.addPrimitive(l3); //BODY var l = new Line( new Point(this.topLeft.x, this.topLeft.y + headerHeight), new Point(this.bottomRight.x, this.topLeft.y + headerHeight) ); containerPath.addPrimitive(l); l = new Line( new Point(this.bottomRight.x, this.topLeft.y + headerHeight), new Point(this.bottomRight.x, this.bottomRight.y - roundness) ); containerPath.addPrimitive(l); var c = new QuadCurve( new Point(this.bottomRight.x, this.bottomRight.y - roundness), new Point(this.bottomRight.x, this.bottomRight.y), new Point(this.bottomRight.x - roundness, this.bottomRight.y) ); containerPath.addPrimitive(c); l = new Line( new Point(this.bottomRight.x - roundness, this.bottomRight.y), new Point(this.topLeft.x + roundness, this.bottomRight.y) ); containerPath.primitives.push(l); c = new QuadCurve( new Point(this.topLeft.x + roundness, this.bottomRight.y), new Point(this.topLeft.x, this.bottomRight.y), new Point(this.topLeft.x, this.bottomRight.y - roundness) ); containerPath.addPrimitive(c); l = new Line( new Point(this.topLeft.x, this.bottomRight.y - roundness), new Point(this.topLeft.x, this.topLeft.y + headerHeight) ); containerPath.primitives.push(l); this.addPrimitive(containerPath); this.properties.push(new BuilderProperty('Stroke Style', 'style.strokeStyle', BuilderProperty.TYPE_COLOR)); this.properties.push(new BuilderProperty('Fill Style', 'style.fillStyle', BuilderProperty.TYPE_COLOR)); this.properties.push(new BuilderProperty('Line Width', 'style.lineWidth',BuilderProperty.TYPE_LINE_WIDTH)); this.properties.push(new BuilderProperty('Line Style', 'style.lineStyle',BuilderProperty.TYPE_LINE_STYLE)); //TITLE var title = new Text("Container", (this.topLeft.x + this.bottomRight.x)/2, this.topLeft.y + Text.DEFAULT_SIZE /*@see https://bitbucket.org/scriptoid/diagramo/issue/31/text-vertical-aligment*/, Text.FONTS[0].Text, Text.DEFAULT_SIZE, false); // title.debug = true; title.style.fillStyle = '#000000'; this.addPrimitive(title); // this.properties.push(new BuilderProperty(BuilderProperty.SEPARATOR)); this.properties.push(new BuilderProperty('Text', 'primitives.1.str', BuilderProperty.TYPE_TEXT)); this.properties.push(new BuilderProperty('Text Size', 'primitives.1.size', BuilderProperty.TYPE_TEXT_FONT_SIZE)); this.properties.push(new BuilderProperty('Font', 'primitives.1.font', BuilderProperty.TYPE_TEXT_FONT_FAMILY)); this.properties.push(new BuilderProperty('Alignment', 'primitives.1.align', BuilderProperty.TYPE_TEXT_FONT_ALIGNMENT)); this.properties.push(new BuilderProperty('Text Underlined', 'primitives.1.underlined', BuilderProperty.TYPE_TEXT_UNDERLINED)); this.properties.push(new BuilderProperty('Text Color', 'primitives.1.style.fillStyle', BuilderProperty.TYPE_COLOR)); /**Serialization type*/ this.oType = 'Container'; } /**Creates a new {Array} of {Container}s out of JSON parsed object *@param {JSONObject} v - the JSON parsed object *@return {Array} of newly constructed {Container}s *@author Artyom Pokatilov **/ Container.loadArray = function(v){ var newContainers = []; var containerLength = v.length; for(var i = 0; i < containerLength; i++){ newContainers.push(Container.load(v[i])); } return newContainers; } /**Creates a new {Container} out of JSON parsed object *@param {JSONObject} o - the JSON parsed object *@return {Container} a newly constructed Container *@author Artyom Pokatilov **/ Container.load = function(o){ // parse first topLeft and bottomRight points from JSON var topLeft = Point.load(o.topLeft); var bottomRight = Point.load(o.bottomRight); var newContainer = new Container(Number(o.id), topLeft, bottomRight); newContainer.primitives = []; for(var i=0; i< o.primitives.length; i++){ var primitive = Util.loadPrimitive(o.primitives[i]); if (primitive != null) { newContainer.addPrimitive(primitive); } } newContainer.style = Style.load(o.style); newContainer.properties = BuilderProperty.loadArray(o.properties); newContainer.rotationCoords = Point.loadArray(o.rotationCoords); return newContainer; } Container.prototype = { constructor: Container, /**Paint the container into certain context * @param {Context2D} context - the context where to paint the container */ paint: function(context) { if(this.style){ this.style.setupContext(context); } for(var i = 0; i} - returns [minX, minY, maxX, maxY] - bounds, where * all points are in the bounds. */ getBounds: function() { return Util.getBounds([this.bottomRight, this.topLeft]); }, /**Detects if */ onEdge : function(theX, theY){ var topRight = new Point(this.bottomRight.x, this.topLeft.y); var bottomLeft = new Point(this.topLeft.x, this.bottomRight.y); var edge = new Polygon(); edge.points = [this.topLeft, topRight, this.bottomRight, bottomLeft]; return edge.near(theX, theY, 3); }, near: function() { throw "container:near() Not implemented"; }, getPoints: function() { throw "container:getPoints() Not implemented"; }, addPrimitive:function(primitive){ // add id property to primitive equal its index primitive.id = this.primitives.length; this.primitives.push(primitive); } }; /** Creates the link between a {Container} and a {Figure} * As relation between Container and Figure is a 1-to-many (at least now) * we will use this class to represent the link * * @constructor * @this {ContainerFigure} * @param {Number} containerId the id of the {Container} * @param {Number} figureId the id of the {Figure} * @author Alex */ function ContainerFigure(containerId, figureId) { this.containerId = containerId; this.figureId = figureId; } ContainerFigure.prototype = { constructor: ContainerFigure }; /**Manages the relation between containers and figures. * The figures and containers are stored in {Stack} * but the relationship between them are stored inside {ContainerFigureManager} * @constructor * @this {ContainerFigure} * */ function ContainerFigureManager() { /**An {Array} of [containerId, figureId] */ this.data = []; } ContainerFigureManager.prototype = { constructor: ContainerFigure, /**Adds a figure to a container * @param {Number} containerId the id of the {Container} * @param {Number} figureId the id of the {Figure} * */ addFigure : function(containerId, figureId){ var i; var v; var present = false; //Test to see if figure is in ANY container ad a figure should be present in ONLY ONE container for(i in this.data){ v = this.data[i]; if(v[1] === figureId){ present = true; break; } } if(!present){ this.data.push([containerId, figureId]); } }, /**Removes a figure from a container * @param {Number} containerId the id of the {Container} * @param {Number} figureId the id of the {Figure} * */ removeFigure : function(containerId, figureId){ var i; var v; var index = -1; for(i in this.data){ v = this.data[i]; if(v[0] === containerId && v[1] === figureId){ index = i; break; } } if(index !== -1){ this.data.splice(index, 1); } }, /**Get all {Figure}s' ids that live inside a container * @param {Number} containerId the id of the {Container} * @return {Array}{Number} an array of Figure id * @author Alex * */ getAllFigures : function(containerId){ var i; var figureIds = []; for(i in this.data){ var v = this.data[i]; if(v[0] === containerId){ figureIds.push(v[1]); } } return figureIds; }, /**Check if a figure is inside a container * @param {Number} containerId the id of the {Container} * @param {Number} figureId the id of the {Figure} * @return {Boolean} true - if figure is inside a container * */ isFigureInContainer : function(containerId, figureId){ var i; var v; var present = false; for(i in this.data){ v = this.data[i]; if(v[0] === containerId && v[1] === figureId){ present = true; break; } } return present; }, /**Check if a figure is inside a container * @param {Number} figureId the id of the {Figure} * @return {Number} containerId the id of the {Container} or -1 if none found * */ getContainerForFigure : function(figureId){ var i; var v; var containerId = -1; for(i in this.data){ v = this.data[i]; if( v[1] === figureId){ containerId = v[0]; break; } } return containerId; }, equals:function (anotherManager){ if ( !(anotherManager instanceof ContainerFigureManager) ) { Log.info("ContainerFigureManager:equals() 0"); return false; } // test data if(this.data.length === anotherManager.data.length){ for(var i = 0; i < this.data.length; i++){ if(this.data[i][0] !== anotherManager.data[i][0] || this.data[i][1] !== anotherManager.data[i][1]){ Log.info("ContainerFigureManager:equals() 1"); return false; } } } else{ Log.info("ContainerFigureManager:equals() 2"); return false; } return true; } }; /**Creates a {ContainerFigureManager} out of JSON parsed object *@param {JSONObject} o - the JSON parsed object *@return {ContainerFigureManager} a newly constructed ContainerFigureManager *@author Alex Gheorghiu **/ ContainerFigureManager.load = function(o){ var containerFigureManager = new ContainerFigureManager(); //empty constructor //TODO: it should work....not tested containerFigureManager.data = []; var dataLength = o.data.length; for (var i = 0; i < dataLength; i++) { var newData = [ // convert value to Number Number(o.data[i][0]), Number(o.data[i][1]) ]; containerFigureManager.data.push(newData); } return containerFigureManager; };