Browse Source

8.5.0 release

Gaudenz Alder 7 years ago
parent
commit
974b75cfeb

+ 4 - 0
ChangeLog

@@ -1,3 +1,7 @@
+23-MAR-2018: 8.5.0
+
+- Adds shapes in Basic sidebar
+
 21-MAR-2018: 8.4.8
 
 - Gliffy import improvements

+ 1 - 1
VERSION

@@ -1 +1 @@
-8.4.8
+8.5.0

+ 1 - 1
src/main/webapp/cache.manifest

@@ -1,7 +1,7 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 03/21/2018 05:29 PM
+# 03/23/2018 11:58 AM
 
 app.html
 index.html?offline=1

File diff suppressed because it is too large
+ 270 - 0
src/main/webapp/connect/confluence/connect-dev.json


+ 29 - 8
src/main/webapp/connect/confluence/connectUtils-1-4-8.js

@@ -1054,7 +1054,10 @@ AC.init = function(baseUrl, location, pageId, editor, diagramName, initialXml, d
 					{
 						var resp = null;
 						var revision = '1';
-
+						var contentId = null;
+						var contentVer = null;
+						
+						//TODO Why this code (Is it expected to have incorrect responseText?)
 						try
 						{
 							resp = JSON.parse(responseText);
@@ -1069,7 +1072,25 @@ AC.init = function(baseUrl, location, pageId, editor, diagramName, initialXml, d
 						//TODO Is prev comment still needed with REST API?
 						if (resp != null && resp.results != null && resp.results[0])
 						{
-							revision = resp.results[0].version.number;
+							var attObj = resp.results[0];
+							revision = attObj.version.number;
+							//Save/update the custom content
+							var spaceKey = AC.getSpaceKey(attObj._expandable.space);
+							var pageType = attObj.container.type;
+
+							AC.saveCustomContent(spaceKey, pageId, pageType, diagramName, revision, 
+									(drawMsg.macroData != null) ? drawMsg.macroData.contentId  : null,
+									(drawMsg.macroData != null) ? drawMsg.macroData.contentVer : null,
+									function(responseText) 
+									{
+										var content = JSON.parse(responseText);
+										
+										contentId = content.id;
+										contentVer = content.version.number;
+										
+										AC.saveDiagram(pageId, diagramName + '.png', AC.b64toBlob(imageData, 'image/png'),
+												successPng, saveError, false, 'image/png', 'draw.io preview', false, draftPage);
+									}, saveError);
 						}
 						else
 						{
@@ -1087,6 +1108,10 @@ AC.init = function(baseUrl, location, pageId, editor, diagramName, initialXml, d
 							{
 								// do nothing
 							}
+							
+							//TODO Save png here in case responseText is incorrect (But why it can be incorrect?)
+							AC.saveDiagram(pageId, diagramName + '.png', AC.b64toBlob(imageData, 'image/png'),
+									successPng, saveError, false, 'image/png', 'draw.io preview', false, draftPage);
 						}
 
 						function successPng(pngResponseText) 
@@ -1098,6 +1123,8 @@ AC.init = function(baseUrl, location, pageId, editor, diagramName, initialXml, d
 									diagramName: diagramName,
 									revision: revision,
 									pageId: newPage ? null : pageId,
+									contentId: contentId,
+									contentVer: contentVer,
 									baseUrl: baseUrl,
 									width: diaWidth,
 									height: diaHeight,
@@ -1127,12 +1154,6 @@ AC.init = function(baseUrl, location, pageId, editor, diagramName, initialXml, d
 									titleKey: 'errorSavingFile', message: e.message, buttonKey: 'ok'}), '*');
 							}
 						};
-
-						if (diagramName != null) 
-						{
-							AC.saveDiagram(pageId, diagramName + '.png', AC.b64toBlob(imageData, 'image/png'),
-								successPng, saveError, false, 'image/png', 'draw.io preview', false, draftPage);
-						}
 					};
 
 					if (diagramName != null) 

+ 93 - 0
src/main/webapp/connect/jira/connect-dev.json

@@ -0,0 +1,93 @@
+{
+     "name": "Draw.io gaudenz",
+     "description": "Draw.io add-on for JIRA",
+     "key": "com.mxgraph.jira.plugins.drawio.gaudenz",
+     "baseUrl": "https://0d961297.ngrok.io/",
+     "vendor": {
+         "name": "JGraph Ltd.",
+         "url": "https://www.jgraph.com"
+     },
+     "authentication": 
+     {
+         "type": "none"
+     },
+     "version": "1.0.4",
+     "scopes": 
+     [
+     	"READ",
+     	"WRITE",
+     	"DELETE"
+	 ],
+     "modules": 
+     {
+      "generalPages": 
+      [
+      	{
+			"url":"/connect/jira/editor2.html?issueId=${issue.id}",
+			"key":"drawioEditor",
+			"name":
+			{
+				"value":"Draw.io Editor"
+			},
+			"location":"hidden"
+		},
+		{
+			"url":"/connect/jira/fullScreenViewer2.html?issueId=${issue.id}",
+			"key":"drawioFullScreenViewer",
+			"name":
+			{
+				"value":"Draw.io Full Screen Viewer"
+			},
+			"location":"hidden"
+		}
+      ],
+	  "webItems": [
+	    {
+	      "location": "operations-attachments",
+	      "weight": 50,
+	      "key": "drawioEditorBlank",
+	      "url": "/connect/jira/editor2.html?issueId=${issue.id}",
+	      "name": {
+	        "value": "Add Draw.io Diagram"
+	      },
+	      "target": 
+	      {
+			"type":"dialog",
+			"options": 
+			{
+				"width":"100%",
+				"height":"100%",
+				"chrome":false
+			}
+		  }
+	    }, 
+	    {
+       	   "key": "drawioEditorDialog",
+	        "name": 
+	        {
+	            "value": "Draw.io Editor"
+	        },
+	        "url": "/connect/jira/editor2.html?issueId=${issue.id}",
+	        "location": "none",
+	        "context": "addon"
+	    }
+	  ],
+	  "webPanels": 
+	  [
+      {
+        "url": "/connect/jira/viewerPanel2.html?issueId=${issue.id}",
+        "location": "atl.jira.view.issue.right.context",
+        "layout": 
+        {
+          "width": "300px"
+        },
+        "weight": 50,
+        "key": "drawioViewerPanel",
+        "name": 
+        {
+          "value": "Draw.io Diagrams"
+        }
+      }
+    ] 
+	}
+ }

BIN
src/main/webapp/images/sidebar-basic.png


File diff suppressed because it is too large
+ 114 - 113
src/main/webapp/js/app.min.js


File diff suppressed because it is too large
+ 100 - 100
src/main/webapp/js/atlas-viewer.min.js


File diff suppressed because it is too large
+ 114 - 113
src/main/webapp/js/atlas.min.js


+ 0 - 6
src/main/webapp/js/diagramly/App.js

@@ -64,12 +64,6 @@ App = function(editor, container, lightbox)
 		
 		this.handleError(message);
 	});
-	
-	// Sets help link for placeholders
-	if (!this.isOffline())
-	{
-		EditDataDialog.placeholderHelpLink = 'https://desk.draw.io/support/solutions/articles/16000051979';
-	}
 
 	// Handles opening files via drag and drop
 	if (!this.editor.chromeless || this.editor.editable)

+ 6 - 0
src/main/webapp/js/diagramly/EditorUi.js

@@ -6706,6 +6706,12 @@
 			pageLinkClicked(evt.getProperty('href'));
 		});
 		
+		// Sets help link for placeholders
+		if (!this.isOffline() && typeof window.EditDataDialog !== 'undefined')
+		{
+			EditDataDialog.placeholderHelpLink = 'https://desk.draw.io/support/solutions/articles/16000051979';
+		}
+		
 		// Passes current page to editor window
 		var editorGetEditBlankUrl = ui.editor.getEditBlankUrl;
 		

+ 5 - 4
src/main/webapp/js/diagramly/sidebar/Sidebar-Basic.js

@@ -16,14 +16,15 @@
 			this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;right=0;top=0;bottom=0;fillColor=none;routingCenterX=-0.5;', 120, 60, '', 'Partial Rectangle'),
 			this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;bottom=0;right=0;fillColor=none;', 120, 60, '', 'Partial Rectangle'),
 			this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;top=0;left=0;fillColor=none;', 120, 60, '', 'Partial Rectangle'),
-			this.createVertexTemplateEntry(s2 + '4_point_star', w, h, '', '4 Point Star', null, null, this.getTagsForStencil(gn, '4_point_star', dt).join(' ')),
+			this.createVertexTemplateEntry(s2 + '4_point_star_2;dx=0.8;', w, h, '', '4 Point Star', null, null, this.getTagsForStencil(gn, '4_point_star', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + '6_point_star', w, h * 0.9, '', '6 Point Star', null, null, this.getTagsForStencil(gn, '6_point_star', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + '8_point_star', w, h, '', '8 Point Star', null, null, this.getTagsForStencil(gn, '8_point_star', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'banner', w, h * 0.5, '', 'Banner', null, null, this.getTagsForStencil(gn, 'banner', dt).join(' ')),
 			this.createVertexTemplateEntry(s + 'cloud_callout', w * 0.9, h * 0.6, '', 'Cloud Callout', null, null, this.getTagsForStencil(gn, 'cloud_callout', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'cone', w, h, '', 'Cone', null, null, this.getTagsForStencil(gn, 'cone', dt).join(' ')),
-			this.createVertexTemplateEntry(s2 + 'cross2;dx=15;', w, h, '', 'Cross', null, null, this.getTagsForStencil(gn, 'cross', dt).join(' ')),
+			this.createVertexTemplateEntry(s2 + 'cone2;dx=0.5;dy=0.9;', w, h, '', 'Cone (adjustable)', null, null, this.getTagsForStencil(gn, 'cone', dt).join(' ')),
 			this.createVertexTemplateEntry(s + 'document', w, h, '', 'Document', null, null, this.getTagsForStencil(gn, 'document', dt).join(' ')),
+			this.createVertexTemplateEntry(s2 + 'drop', w * 0.7, h, '', 'Drop', null, null, this.getTagsForStencil(gn, 'drop', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'flash', w * 0.6, h, '', 'Flash', null, null, this.getTagsForStencil(gn, 'flash', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'half_circle', w, h * 0.5, '', 'Half Circle', null, null, this.getTagsForStencil(gn, 'half_circle', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'heart', w, h, '', 'Heart', null, null, this.getTagsForStencil(gn, 'heart', dt).join(' ')),
@@ -36,15 +37,15 @@
 			this.createVertexTemplateEntry(s2 + 'acute_triangle;dx=0.5;', w, h * 0.7, '', 'Acute Triangle', null, null, this.getTagsForStencil(gn, 'acute_triangle', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'obtuse_triangle;dx=0.25;', w, h * 0.7, '', 'Obtuse Triangle', null, null, this.getTagsForStencil(gn, 'obtuse_triangle', dt).join(' ')),
 			this.createVertexTemplateEntry(s + 'oval_callout', w, h * 0.6, '', 'Oval Callout', null, null, this.getTagsForStencil(gn, 'oval_callout', dt).join(' ')),
-			this.createVertexTemplateEntry(s3 + 'parallelogram;whiteSpace=wrap;align=center;size=0.24;', w, h * 0.6, '', 'Parallelepiped', null, null, this.getTagsForStencil(gn, 'parallelepiped', dt).join(' ')),
 			this.createVertexTemplateEntry(s + 'pentagon', w, h * 0.9, '', 'Pentagon', null, null, this.getTagsForStencil(gn, 'pentagon', dt).join(' ')),
+			this.createVertexTemplateEntry(s + 'pointed_oval', w * 0.5, h, '', 'Pointed Oval', null, null, this.getTagsForStencil(gn, 'pointed oval', dt).join(' ')),
+			this.createVertexTemplateEntry(s2 + 'pyramid;dx1=0.4;dx2=0.6;dy1=0.9;dy2=0.8;', w, h, '', 'Pyramid', null, null, this.getTagsForStencil(gn, 'pyramid', dt).join(' ')),
 			this.createVertexTemplateEntry(s + 'rectCallout;dx=30;dy=15;boundedLbl=1;', w, h * 0.6, '', 'Rectangular Callout', null, null, this.getTagsForStencil(gn, 'rectangular_callout', dt).join(' ')),
 			this.createVertexTemplateEntry(s + 'roundRectCallout;dx=30;dy=15;size=5;boundedLbl=1;', w, h * 0.6, '', 'Rounded Rectangular Callout', null, null, this.getTagsForStencil(gn, 'rectangular_callout', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'smiley', w, h, '', 'Smiley', null, null, this.getTagsForStencil(gn, 'smiley', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'star', w, h * 0.95, '', 'Star', null, null, this.getTagsForStencil(gn, 'star', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'sun', w, h, '', 'Sun', null, null, this.getTagsForStencil(gn, 'sun', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'tick', w * 0.85, h, '', 'Tick', null, null, this.getTagsForStencil(gn, 'tick', dt).join(' ')),
-			this.createVertexTemplateEntry(s3 + 'trapezoid;size=0.24;', w, h, '', 'Trapezoid', null, null, this.getTagsForStencil(gn, 'trapezoid', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'wave2;dy=0.3;', w, h * 0.6, '', 'Wave', null, null, this.getTagsForStencil(gn, 'wave', dt).join(' ')),
 			this.createVertexTemplateEntry(s2 + 'x', w, h, '', 'X', null, null, this.getTagsForStencil(gn, 'x', dt).join(' '))
 			

File diff suppressed because it is too large
+ 1 - 1
src/main/webapp/js/embed-static.min.js


+ 1 - 1
src/main/webapp/js/mxgraph/Actions.js

@@ -261,7 +261,7 @@ Actions.prototype.init = function()
 		if (cell != null)
 		{
 			var dlg = new EditDataDialog(ui, cell);
-			ui.showDialog(dlg.container, 320, 320, true, false, null, false);
+			ui.showDialog(dlg.container, 340, 340, true, false, null, false);
 			dlg.init();
 		}
 	}, null, null, Editor.ctrlKey + '+M');

+ 4 - 1
src/main/webapp/js/mxgraph/EditorUi.js

@@ -865,7 +865,10 @@ EditorUi = function(editor, container, lightbox)
    	{
    		window.setTimeout(mxUtils.bind(this, function()
    		{
-   			this.refresh();
+   			if (this.editor.graph != null)
+   			{
+   				this.refresh();
+   			}
    		}), 0);
    	});
 	

File diff suppressed because it is too large
+ 1 - 1
src/main/webapp/js/reader.min.js


File diff suppressed because it is too large
+ 14 - 0
src/main/webapp/js/shapes.min.js


File diff suppressed because it is too large
+ 1 - 1
src/main/webapp/js/stencils.min.js


File diff suppressed because it is too large
+ 100 - 100
src/main/webapp/js/viewer.min.js


+ 321 - 1
src/main/webapp/shapes/mxBasic.js

@@ -1,6 +1,6 @@
 /**
  * $Id: mxBasic.js,v 1.5 2016/04/1 12:32:06 mate Exp $
- * Copyright (c) 2006-2016, JGraph Ltd
+ * Copyright (c) 2006-2018, JGraph Ltd
  */
 //**********************************************************************************************************************************************************
 // Cross
@@ -574,3 +574,323 @@ Graph.handleFactory[mxShapeBasicTriangleObtuse.prototype.cst.OBTUSE_TRIANGLE] =
 	return handles;
 };
 
+//**********************************************************************************************************************************************************
+//Drop
+//**********************************************************************************************************************************************************
+/**
+* Extends mxShape.
+*/
+function mxShapeBasicDrop(bounds, fill, stroke, strokewidth)
+{
+	mxShape.call(this);
+	this.bounds = bounds;
+	this.fill = fill;
+	this.stroke = stroke;
+	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
+};
+
+/**
+* Extends mxShape.
+*/
+mxUtils.extend(mxShapeBasicDrop, mxActor);
+
+mxShapeBasicDrop.prototype.cst = {DROP : 'mxgraph.basic.drop'};
+
+/**
+* Function: paintVertexShape
+* 
+* Paints the vertex shape.
+*/
+mxShapeBasicDrop.prototype.paintVertexShape = function(c, x, y, w, h)
+{
+	c.translate(x, y);
+
+	var r = Math.min(h, w) * 0.5;
+	var d = h - r;
+	var a = Math.sqrt(d * d - r * r);
+	
+	var angle = Math.atan(a / r);
+	
+	var x1 = r * Math.sin(angle);
+	var y1 = r * Math.cos(angle);
+	
+	c.begin();
+	c.moveTo(w * 0.5, 0);
+	c.lineTo(w * 0.5 + x1, h - r - y1);
+	c.arcTo(r, r, 0, 0, 1, w * 0.5 + r, h - r);
+	c.arcTo(r, r, 0, 0, 1, w * 0.5, h);
+	c.arcTo(r, r, 0, 0, 1, w * 0.5 - r, h - r);
+	c.arcTo(r, r, 0, 0, 1, w * 0.5 - x1, h - r - y1);
+	c.close();
+	c.fillAndStroke();
+};
+
+mxCellRenderer.registerShape(mxShapeBasicDrop.prototype.cst.DROP, mxShapeBasicDrop);
+
+mxShapeBasicDrop.prototype.constraints = null;
+
+//**********************************************************************************************************************************************************
+//Cone 2
+//**********************************************************************************************************************************************************
+/**
+* Extends mxShape.
+*/
+function mxShapeBasicCone2(bounds, fill, stroke, strokewidth)
+{
+	mxShape.call(this);
+	this.bounds = bounds;
+	this.fill = fill;
+	this.stroke = stroke;
+	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
+	this.dx = 0.5;
+	this.dy = 0.9;
+};
+
+/**
+* Extends mxShape.
+*/
+mxUtils.extend(mxShapeBasicCone2, mxActor);
+
+mxShapeBasicCone2.prototype.cst = {CONE2 : 'mxgraph.basic.cone2'};
+
+/**
+* Function: paintVertexShape
+* 
+* Paints the vertex shape.
+*/
+mxShapeBasicCone2.prototype.paintVertexShape = function(c, x, y, w, h)
+{
+	c.translate(x, y);
+
+	var dx = w * Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
+	var dy = h * Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy', this.dy))));
+	
+	var ry = h - dy;
+	
+	c.begin();
+	c.moveTo(dx, 0);
+	
+	if (ry > 0)
+	{
+		c.lineTo(w, h - ry);
+		c.arcTo(w * 0.5, ry, 0, 0, 1, w * 0.5, h);
+		c.arcTo(w * 0.5, ry, 0, 0, 1, 0, h - ry);
+	}
+	else
+	{
+		c.lineTo(w, h);
+		c.lineTo(0, h);
+	}
+	
+	c.close();
+	c.fillAndStroke();
+};
+
+mxCellRenderer.registerShape(mxShapeBasicCone2.prototype.cst.CONE2, mxShapeBasicCone2);
+
+mxShapeBasicCone2.prototype.constraints = null;
+
+Graph.handleFactory[mxShapeBasicCone2.prototype.cst.CONE2] = function(state)
+{
+	var handles = [Graph.createHandle(state, ['dx'], function(bounds)
+	{
+		var dx = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
+
+		return new mxPoint(bounds.x + dx * bounds.width, bounds.y + 10);
+	}, function(bounds, pt)
+	{
+		this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(1, (pt.x - bounds.x) / bounds.width))) / 100;
+	})];
+
+	var handle2 = Graph.createHandle(state, ['dy'], function(bounds)
+	{
+		var dy = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy', this.dy))));
+
+		return new mxPoint(bounds.x + 10, bounds.y + dy * bounds.height);
+	}, function(bounds, pt)
+	{
+		this.state.style['dy'] = Math.round(100 * Math.max(0, Math.min(1, (pt.y - bounds.y) / bounds.height))) / 100;
+	});
+	
+	handles.push(handle2);
+	
+	return handles;
+};
+
+//**********************************************************************************************************************************************************
+//Pyramid
+//**********************************************************************************************************************************************************
+/**
+* Extends mxShape.
+*/
+function mxShapeBasicPyramid(bounds, fill, stroke, strokewidth)
+{
+	mxShape.call(this);
+	this.bounds = bounds;
+	this.fill = fill;
+	this.stroke = stroke;
+	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
+	this.dx1 = 0.5;
+	this.dx2 = 0.6;
+	this.dy1 = 0.9;
+	this.dy2 = 0.8;
+};
+
+/**
+* Extends mxShape.
+*/
+mxUtils.extend(mxShapeBasicPyramid, mxActor);
+
+mxShapeBasicPyramid.prototype.cst = {PYRAMID : 'mxgraph.basic.pyramid'};
+
+/**
+* Function: paintVertexShape
+* 
+* Paints the vertex shape.
+*/
+mxShapeBasicPyramid.prototype.paintVertexShape = function(c, x, y, w, h)
+{
+	c.translate(x, y);
+
+	var dx1 = w * Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx1', this.dx1))));
+	var dx2 = w * Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx2', this.dx2))));
+	var dy1 = h * Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy1', this.dy1))));
+	var dy2 = h * Math.max(0, Math.min(h, parseFloat(mxUtils.getValue(this.style, 'dy2', this.dy2))));
+	
+	c.begin();
+	c.moveTo(dx1, 0);
+	c.lineTo(w, dy2);
+	c.lineTo(dx2, h);
+	c.lineTo(0, dy1);
+	c.close();
+	c.fillAndStroke();
+	
+	c.setShadow(false);
+	
+	c.begin();
+	c.moveTo(dx1, 0);
+	c.lineTo(dx2, h);
+	c.stroke();
+};
+
+mxCellRenderer.registerShape(mxShapeBasicPyramid.prototype.cst.PYRAMID, mxShapeBasicPyramid);
+
+mxShapeBasicPyramid.prototype.constraints = null;
+
+Graph.handleFactory[mxShapeBasicPyramid.prototype.cst.PYRAMID] = function(state)
+{
+	var handles = [Graph.createHandle(state, ['dx1'], function(bounds)
+	{
+		var dx1 = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dx1', this.dx1))));
+
+		return new mxPoint(bounds.x + dx1 * bounds.width, bounds.y + 10);
+	}, function(bounds, pt)
+	{
+		this.state.style['dx1'] = Math.round(100 * Math.max(0, Math.min(1, (pt.x - bounds.x) / bounds.width))) / 100;
+	})];
+
+	var handle2 = Graph.createHandle(state, ['dx2'], function(bounds)
+	{
+		var dx2 = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dx2', this.dx2))));
+
+		return new mxPoint(bounds.x + dx2 * bounds.width, bounds.y + bounds.height - 10);
+	}, function(bounds, pt)
+	{
+		this.state.style['dx2'] = Math.round(100 * Math.max(0, Math.min(1, (pt.x - bounds.x) / bounds.width))) / 100;
+	});
+	
+	handles.push(handle2);
+	
+	var handle3 = Graph.createHandle(state, ['dy1'], function(bounds)
+	{
+		var dy1 = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy1', this.dy1))));
+
+		return new mxPoint(bounds.x + 10, bounds.y + dy1 * bounds.height);
+	}, function(bounds, pt)
+	{
+		this.state.style['dy1'] = Math.round(100 * Math.max(0, Math.min(1, (pt.y - bounds.y) / bounds.height))) / 100;
+	});
+	
+	handles.push(handle3);
+	
+	var handle4 = Graph.createHandle(state, ['dy2'], function(bounds)
+	{
+		var dy2 = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dy2', this.dy2))));
+
+		return new mxPoint(bounds.x + bounds.width - 10, bounds.y + dy2 * bounds.height);
+	}, function(bounds, pt)
+	{
+		this.state.style['dy2'] = Math.round(100 * Math.max(0, Math.min(1, (pt.y - bounds.y) / bounds.height))) / 100;
+	});
+	
+	handles.push(handle4);
+	
+	return handles;
+};
+
+//**********************************************************************************************************************************************************
+//4 Point Star 2
+//**********************************************************************************************************************************************************
+/**
+* Extends mxShape.
+*/
+function mxShapeBasic4PointStar2(bounds, fill, stroke, strokewidth)
+{
+	mxShape.call(this);
+	this.bounds = bounds;
+	this.fill = fill;
+	this.stroke = stroke;
+	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
+	this.dx = 0.8;
+};
+
+/**
+* Extends mxShape.
+*/
+mxUtils.extend(mxShapeBasic4PointStar2, mxActor);
+
+mxShapeBasic4PointStar2.prototype.cst = {FOUR_POINT_STAR_2 : 'mxgraph.basic.4_point_star_2'};
+
+/**
+* Function: paintVertexShape
+* 
+* Paints the vertex shape.
+*/
+mxShapeBasic4PointStar2.prototype.paintVertexShape = function(c, x, y, w, h)
+{
+	c.translate(x, y);
+
+	var dx = 0.5 * Math.max(0, Math.min(w, parseFloat(mxUtils.getValue(this.style, 'dx', this.dx))));
+
+	c.begin();
+	c.moveTo(0, h * 0.5);
+	c.lineTo(dx * w, dx * h);
+	c.lineTo(w * 0.5, 0);
+	c.lineTo(w - dx * w, dx * h);
+	c.lineTo(w, h * 0.5);
+	c.lineTo(w - dx * w, h - dx * h);
+	c.lineTo(w * 0.5, h);
+	c.lineTo(dx * w, h - dx * h);
+	c.close();
+	c.fillAndStroke();
+};
+
+mxCellRenderer.registerShape(mxShapeBasic4PointStar2.prototype.cst.FOUR_POINT_STAR_2, mxShapeBasic4PointStar2);
+
+mxShapeBasic4PointStar2.prototype.constraints = null;
+
+Graph.handleFactory[mxShapeBasic4PointStar2.prototype.cst.FOUR_POINT_STAR_2] = function(state)
+{
+	var handles = [Graph.createHandle(state, ['dx'], function(bounds)
+	{
+		var dx = Math.max(0, Math.min(1, parseFloat(mxUtils.getValue(this.state.style, 'dx', this.dx))));
+
+		return new mxPoint(bounds.x + dx * bounds.width / 2, bounds.y + 10);
+	}, function(bounds, pt)
+	{
+		this.state.style['dx'] = Math.round(100 * Math.max(0, Math.min(1, 2 * (pt.x - bounds.x) / bounds.width))) / 100;
+	})];
+
+	return handles;
+};
+

+ 14 - 0
src/main/webapp/stencils/basic.xml

@@ -586,6 +586,20 @@
 <fillstroke/>
 </foreground>
 </shape>
+<shape aspect="variable" h="100" name="Pointed Oval" strokewidth="inherit" w="50.93">
+    <connections/>
+    <background>
+        <path>
+            <move x="25.46" y="0"/>
+            <arc large-arc-flag="0" rx="75" ry="75" sweep-flag="0" x="25.46" x-axis-rotation="0" y="100"/>
+            <arc large-arc-flag="0" rx="75" ry="75" sweep-flag="0" x="25.46" x-axis-rotation="0" y="0"/>
+            <close/>
+        </path>
+    </background>
+    <foreground>
+        <fillstroke/>
+    </foreground>
+</shape>
 <shape name="Rectangular Callout" h="60" w="98" aspect="variable" strokewidth="inherit">
 <connections>
 <constraint x="0.5" y="0" perimeter="0" name="N"/>