瀏覽代碼

6.5.10 release

David Benson 8 年之前
父節點
當前提交
dd5d722e08
共有 100 個文件被更改,包括 3430 次插入2250 次删除
  1. 18 0
      ChangeLog
  2. 1 1
      VERSION
  3. 33 9
      war/js/diagramly/ElectronApp.js
  4. 4 0
      etc/electron/README
  5. 1 1
      war/electron.js
  6. 0 0
      etc/electron/package.json
  7. 3 3
      etc/mxgraph/mxClient.js
  8. 97 0
      src/com/mxgraph/io/vsdx/export/ModelExtAttrib.java
  9. 557 0
      src/com/mxgraph/io/vsdx/export/mxVsdxExporter.java
  10. 1 0
      src/com/mxgraph/io/vsdx/resources/export/[Content_Types].xml
  11. 1 0
      src/com/mxgraph/io/vsdx/resources/export/_rels/.rels
  12. 1 0
      src/com/mxgraph/io/vsdx/resources/export/docProps/app.xml
  13. 1 0
      src/com/mxgraph/io/vsdx/resources/export/docProps/core.xml
  14. 1 0
      src/com/mxgraph/io/vsdx/resources/export/docProps/custom.xml
  15. 1 0
      src/com/mxgraph/io/vsdx/resources/export/visio/_rels/document.xml.rels
  16. 1 0
      src/com/mxgraph/io/vsdx/resources/export/visio/document.xml
  17. 1 0
      src/com/mxgraph/io/vsdx/resources/export/visio/masters/_rels/masters.xml.rels
  18. 1 0
      src/com/mxgraph/io/vsdx/resources/export/visio/masters/masters.xml
  19. 2 0
      src/com/mxgraph/io/vsdx/resources/export/visio/pages/_rels/page1.xml.rels
  20. 1 0
      src/com/mxgraph/io/vsdx/resources/export/visio/windows.xml
  21. 1 1
      war/WEB-INF/appengine-web.xml
  22. 5 1
      war/cache.manifest
  23. 二進制
      war/images/connect-down-new.png
  24. 二進制
      war/images/connect-left-new.png
  25. 二進制
      war/images/connect-right-new.png
  26. 二進制
      war/images/connect-up-new.png
  27. 二進制
      war/images/handle-rotate-new.png
  28. 2 21
      war/index.html
  29. 590 582
      war/js/app.min.js
  30. 280 275
      war/js/atlas-viewer.min.js
  31. 649 641
      war/js/atlas.min.js
  32. 7 3
      war/js/diagramly/App.js
  33. 53 11
      war/js/diagramly/Dialogs.js
  34. 2 2
      war/js/diagramly/DrawioFile.js
  35. 6 0
      war/js/diagramly/DriveRealtime.js
  36. 73 24
      war/js/diagramly/Editor.js
  37. 162 70
      war/js/diagramly/EditorUi.js
  38. 2 2
      war/js/diagramly/Menus.js
  39. 2 2
      war/js/diagramly/Settings.js
  40. 4 4
      war/js/diagramly/sidebar/Sidebar-Basic.js
  41. 87 87
      war/js/embed-static.min.js
  42. 61 49
      war/js/mxgraph/Dialogs.js
  43. 8 2
      war/js/mxgraph/EditorUi.js
  44. 1 1
      war/js/mxgraph/Format.js
  45. 56 42
      war/js/mxgraph/Graph.js
  46. 3 1
      war/js/mxgraph/Menus.js
  47. 2 2
      war/js/mxgraph/Sidebar.js
  48. 24 11
      war/js/mxgraph/Toolbar.js
  49. 87 87
      war/js/reader.min.js
  50. 282 278
      war/js/viewer.min.js
  51. 83 0
      war/plugins/import.js
  52. 28 25
      war/plugins/mind/mind.js
  53. 二進制
      war/templates/business/accd.png
  54. 12 0
      war/templates/business/accd.xml
  55. 二進制
      war/templates/business/archimate.png
  56. 12 0
      war/templates/business/archimate.xml
  57. 二進制
      war/templates/business/bpmn.png
  58. 12 1
      war/templates/business/bpmn.xml
  59. 二進制
      war/templates/business/business_model_1.png
  60. 12 0
      war/templates/business/business_model_1.xml
  61. 二進制
      war/templates/business/business_model_2.png
  62. 12 0
      war/templates/business/business_model_2.xml
  63. 二進制
      war/templates/business/leanMapping.png
  64. 0 1
      war/templates/business/leanMapping.xml
  65. 二進制
      war/templates/business/pert_1.png
  66. 12 0
      war/templates/business/pert_1.xml
  67. 二進制
      war/templates/business/pert_2.png
  68. 12 0
      war/templates/business/pert_2.xml
  69. 二進制
      war/templates/business/swimlane.png
  70. 0 1
      war/templates/business/swimlane.xml
  71. 二進制
      war/templates/business/swot.png
  72. 0 1
      war/templates/business/swot.xml
  73. 二進制
      war/templates/business/swot2.png
  74. 0 1
      war/templates/business/swot2.xml
  75. 二進制
      war/templates/business/swot3.png
  76. 0 1
      war/templates/business/swot3.xml
  77. 二進制
      war/templates/business/swot4.png
  78. 0 1
      war/templates/business/swot4.xml
  79. 二進制
      war/templates/business/timeline_1.png
  80. 12 0
      war/templates/business/timeline_1.xml
  81. 二進制
      war/templates/business/timeline_2.png
  82. 12 0
      war/templates/business/timeline_2.xml
  83. 二進制
      war/templates/charts/bar.png
  84. 0 1
      war/templates/charts/bar.xml
  85. 二進制
      war/templates/charts/bar2.png
  86. 0 1
      war/templates/charts/bar2.xml
  87. 二進制
      war/templates/charts/city_org.png
  88. 0 1
      war/templates/charts/city_org.xml
  89. 二進制
      war/templates/charts/coc.png
  90. 12 0
      war/templates/charts/coc.xml
  91. 二進制
      war/templates/charts/org1.png
  92. 0 1
      war/templates/charts/org1.xml
  93. 二進制
      war/templates/charts/org2.png
  94. 0 1
      war/templates/charts/org2.xml
  95. 二進制
      war/templates/charts/org_chart_1.png
  96. 12 0
      war/templates/charts/org_chart_1.xml
  97. 二進制
      war/templates/charts/org_chart_2.png
  98. 12 0
      war/templates/charts/org_chart_2.xml
  99. 二進制
      war/templates/charts/work_breakdown_structure.png
  100. 0 0
      war/templates/charts/work_breakdown_structure.xml

+ 18 - 0
ChangeLog

@@ -1,3 +1,21 @@
+13-MAY-2017: 6.5.10
+
+- Fixes case sensitivity issue for template names and folders
+
+12-MAY-2017: 6.5.9
+
+- Adds export as URL in Chrome App
+- Adds drag and drop for all file formats in Sidebar and Library dialog
+- Fixes handling of invalid files after close with realtime
+- Adds offline app status icon for cached state
+- Removes standalone mode to fix offline iOS home screen apps
+- Redirects PDF export to print action when offline
+- Fixes text preview for resize with custom handles
+- Improvements for small mobile screens
+- Forces HTTPS for offline app
+- Fixes partial rectangles in Basic palette
+- Uses mxGraph 3.7.3 beta 5
+
 08-MAY-2017: 6.5.8
 
 - Adds .vssx stencil import

+ 1 - 1
VERSION

@@ -1 +1 @@
-6.5.8
+6.5.10

+ 33 - 9
war/js/diagramly/ElectronApp.js

@@ -6,6 +6,9 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 	// Overrides default mode
 	App.mode = App.MODE_DEVICE;
 
+	// Disables new window option in edit diagram dialog
+	EditDiagramDialog.showNewWindowOption = false;
+
 	// Redirects printing to iframe to avoid document.write
 	var printDialogCreatePrintPreview = PrintDialog.createPrintPreview; 
 	
@@ -257,12 +260,27 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 	// Uses local picker
 	App.prototype.pickFile = function()
 	{
-		this.chooseFileEntry(mxUtils.bind(this, function(fileEntry, data)
+		var doPickFile = mxUtils.bind(this, function()
 		{
-			var file = new LocalFile(this, data, '');
-			file.fileObject = fileEntry;
-			this.fileLoaded(file);
-		}));
+			this.chooseFileEntry(mxUtils.bind(this, function(fileEntry, data)
+			{
+				var file = new LocalFile(this, data, '');
+				file.fileObject = fileEntry;
+				this.fileLoaded(file);
+			}));
+		});
+
+		var file = this.getCurrentFile();
+		
+		if (file != null && file.isModified())
+		{
+			this.confirm(mxResources.get('allChangesLost'), null, doPickFile,
+				mxResources.get('cancel'), mxResources.get('discardChanges'));
+		}
+		else
+		{
+			doPickFile();
+		}
 	};
 	
 	/**
@@ -321,7 +339,17 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
         	}));
         }
 	};
+
+	// Disables temp files in Electron
+	var LocalFileCtor = LocalFile;
 	
+	LocalFile = function(ui, data, title, temp)
+	{
+		LocalFileCtor.call(this, ui, data, title, false);
+	};
+
+	mxUtils.extend(LocalFile, LocalFileCtor);
+
 	LocalFile.prototype.isAutosave = function()
 	{
 		return this.ui.editor.autosave;
@@ -366,10 +394,6 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 	{
 		var fn = mxUtils.bind(this, function()
 		{
-			// Disables temporary file state
-			this.mode = App.MODE_DEVICE;
-			this.ui.mode = this.mode;
-			
 			var doSave = mxUtils.bind(this, function(data, enc)
 			{
 				if (!this.savingFile)

+ 4 - 0
etc/electron/README

@@ -0,0 +1,4 @@
+1. Go to this directory
+2. Run "npm install" once
+3. Execute "export NODE_ENV=development" for dev mode
+4. Run "npm start" to start the client

+ 1 - 1
war/electron.js

@@ -34,7 +34,7 @@ function createWindow (opt = {}) {
 	console.log('createWindow', opt)
 
 	let wurl = url.format({
-		pathname: `${__dirname}/index.html`,
+		pathname: `${__dirname}/../../war/index.html`,
 		protocol: 'file:',
 		query: {
 			'dev': __DEV__ ? 1 : 0,

war/package.json → etc/electron/package.json


文件差異過大導致無法顯示
+ 3 - 3
etc/mxgraph/mxClient.js


+ 97 - 0
src/com/mxgraph/io/vsdx/export/ModelExtAttrib.java

@@ -0,0 +1,97 @@
+package com.mxgraph.io.vsdx.export;
+
+public class ModelExtAttrib 
+{
+	private double pageScale = 1, 
+			pageWidth = 839, pageHeight = 1188, //A4 size in pixels as a default
+			gridSize = 10;
+	private boolean pageVisible = true, gridEnabled = true, guidesEnabled = true, foldingEnabled = true, 
+			shadowVisible = false, tooltips = true, connect = true, arrows = true, mathEnabled = true;
+	private String backgroundClr = "#FFFFFF";
+	//TODO add backgroundImage support
+	
+	public double getPageScale() {
+		return pageScale;
+	}
+	public double getPageWidth() {
+		return pageWidth;
+	}
+	public double getPageHeight() {
+		return pageHeight;
+	}
+	public double getGridSize() {
+		return gridSize;
+	}
+	public boolean isPageVisible() {
+		return pageVisible;
+	}
+	public boolean isGridEnabled() {
+		return gridEnabled;
+	}
+	public boolean isGuidesEnabled() {
+		return guidesEnabled;
+	}
+	public boolean isFoldingEnabled() {
+		return foldingEnabled;
+	}
+	public boolean isShadowVisible() {
+		return shadowVisible;
+	}
+	public boolean isTooltips() {
+		return tooltips;
+	}
+	public boolean isConnect() {
+		return connect;
+	}
+	public boolean isArrows() {
+		return arrows;
+	}
+	public boolean isMathEnabled() {
+		return mathEnabled;
+	}
+	public String getBackgroundClr() {
+		return backgroundClr;
+	}
+	public void setPageScale(double pageScale) {
+		this.pageScale = pageScale;
+	}
+	public void setPageWidth(double pageWidth) {
+		this.pageWidth = pageWidth;
+	}
+	public void setPageHeight(double pageHeight) {
+		this.pageHeight = pageHeight;
+	}
+	public void setGridSize(double gridSize) {
+		this.gridSize = gridSize;
+	}
+	public void setPageVisible(boolean pageVisible) {
+		this.pageVisible = pageVisible;
+	}
+	public void setGridEnabled(boolean gridEnabled) {
+		this.gridEnabled = gridEnabled;
+	}
+	public void setGuidesEnabled(boolean guidesEnabled) {
+		this.guidesEnabled = guidesEnabled;
+	}
+	public void setFoldingEnabled(boolean foldingEnabled) {
+		this.foldingEnabled = foldingEnabled;
+	}
+	public void setShadowVisible(boolean shadowVisible) {
+		this.shadowVisible = shadowVisible;
+	}
+	public void setTooltips(boolean tooltips) {
+		this.tooltips = tooltips;
+	}
+	public void setConnect(boolean connect) {
+		this.connect = connect;
+	}
+	public void setArrows(boolean arrows) {
+		this.arrows = arrows;
+	}
+	public void setMathEnabled(boolean mathEnabled) {
+		this.mathEnabled = mathEnabled;
+	}
+	public void setBackgroundClr(String backgroundClr) {
+		this.backgroundClr = backgroundClr;
+	}
+}

文件差異過大導致無法顯示
+ 557 - 0
src/com/mxgraph/io/vsdx/export/mxVsdxExporter.java


文件差異過大導致無法顯示
+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/[Content_Types].xml


文件差異過大導致無法顯示
+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/_rels/.rels


+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/docProps/app.xml

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Properties xmlns='http://schemas.openxmlformats.org/officeDocument/2006/extended-properties' xmlns:vt='http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes'><Application>Microsoft Visio</Application><AppVersion>15.0000</AppVersion><Template /><Manager /><Company /><HyperlinkBase /></Properties>

+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/docProps/core.xml

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><cp:coreProperties xmlns:cp='http://schemas.openxmlformats.org/package/2006/metadata/core-properties' xmlns:dc='http://purl.org/dc/elements/1.1/' xmlns:dcterms='http://purl.org/dc/terms/' xmlns:dcmitype='http://purl.org/dc/dcmitype/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><dc:title /><dc:subject /><dc:creator /><cp:keywords /><dc:description /><cp:category /><dc:language>en-US</dc:language></cp:coreProperties>

+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/docProps/custom.xml

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Properties xmlns='http://schemas.openxmlformats.org/officeDocument/2006/custom-properties' xmlns:vt='http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes' />

文件差異過大導致無法顯示
+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/visio/_rels/document.xml.rels


文件差異過大導致無法顯示
+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/visio/document.xml


+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/visio/masters/_rels/masters.xml.rels

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Relationships xmlns='http://schemas.openxmlformats.org/package/2006/relationships' />

+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/visio/masters/masters.xml

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><Masters xmlns='http://schemas.microsoft.com/office/visio/2012/main' xmlns:r='http://schemas.openxmlformats.org/officeDocument/2006/relationships' xml:space='preserve' />

+ 2 - 0
src/com/mxgraph/io/vsdx/resources/export/visio/pages/_rels/page1.xml.rels

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<Relationships xmlns='http://schemas.openxmlformats.org/package/2006/relationships' />

+ 1 - 0
src/com/mxgraph/io/vsdx/resources/export/visio/windows.xml

@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Windows ClientWidth='0' ClientHeight='0' xmlns='http://schemas.microsoft.com/office/visio/2012/main' xmlns:r='http://schemas.openxmlformats.org/officeDocument/2006/relationships' xml:space='preserve' />

+ 1 - 1
war/WEB-INF/appengine-web.xml

@@ -2,7 +2,7 @@
 <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
 	<application>drawdotio</application>
 	<!-- IMPORTANT! DO NOT CHANGE THIS VALUE IN SOURCE CONTROL! -->
-	<version>test</version>
+	<version>6-5-10</version>
 	
 	<!-- Configure java.util.logging -->
 	<system-properties>

+ 5 - 1
war/cache.manifest

@@ -1,10 +1,11 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 05/08/2017 10:18 PM
+# 05/13/2017 12:10 AM
 
 app.html
 index.html?offline=1
+index.html?offline=1&https=0
 offline.html
 open.html
 js/app.min.js
@@ -33,6 +34,7 @@ img/clipart/Gear_128x128.png
 images/delete.png
 images/droptarget.png
 images/edit.gif
+images/help.png
 images/download.png
 images/logo-flat.png
 images/osa_drive-harddisk.png
@@ -40,6 +42,8 @@ images/osa_database.png
 images/glyphicons_star.png
 images/logo-confluence.png
 images/logo-jira.png
+images/clear.gif
+images/spin.gif
 images/checkmark.gif
 images/favicon-32x32.png
 images/favicon-194x194.png

二進制
war/images/connect-down-new.png


二進制
war/images/connect-left-new.png


二進制
war/images/connect-right-new.png


二進制
war/images/connect-up-new.png


二進制
war/images/handle-rotate-new.png


+ 2 - 21
war/index.html

@@ -14,7 +14,6 @@
 	<meta itemprop="image" content="https://lh4.googleusercontent.com/-cLKEldMbT_E/Tx8qXDuw6eI/AAAAAAAAAAs/Ke0pnlk8Gpg/w500-h344-k/BPMN%2Bdiagram%2Brc2f.png">
     <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
     <meta name="mobile-web-app-capable" content="yes">
-    <meta name="apple-mobile-web-app-capable" content="yes">
     <link rel="canonical" href="https://www.draw.io">
     <script type="text/javascript">
 		/**
@@ -75,7 +74,7 @@
 					}
 					
 					// Redirects to SSL/non-SSL
-					if (urlParams['demo'] != '1' && urlParams['offline'] != '1')
+					if (urlParams['demo'] != '1')
 					{
 						var ssl = (urlParams['https'] != null) ? urlParams['https'] == '1' :
 							navigator.userAgent.indexOf('MSIE') < 0 || document.documentMode >= 9;
@@ -326,7 +325,7 @@
 		if (window && window.process && window.process.type)
 		{
 			// Electron
-			mxscript('js/diagramly/ElectronApp.js');
+			mxscript('../etc/electron/ElectronApp.js');
 		}
 		
 		// Adds basic error handling
@@ -393,24 +392,6 @@
 	</table>
 </div>
 <script type="text/javascript">
-// Testing new icons
-(function()
-{
-	if (urlParams['icons'] == 'test')
-	{
-		HoverIcons.prototype.triangleUp = new mxImage(IMAGE_PATH + '/connect-up-new.png', 20, 20);
-		HoverIcons.prototype.triangleRight = new mxImage(IMAGE_PATH + '/connect-right-new.png', 20, 20);
-		HoverIcons.prototype.triangleDown = new mxImage(IMAGE_PATH + '/connect-down-new.png', 20, 20);
-		HoverIcons.prototype.triangleLeft = new mxImage(IMAGE_PATH + '/connect-left-new.png', 20, 20);
-		HoverIcons.prototype.rotationHandle = new mxImage(IMAGE_PATH + '/handle-rotate-new.png', 18, 18);
-		Sidebar.prototype.triangleUp = HoverIcons.prototype.triangleUp;
-		Sidebar.prototype.triangleRight = HoverIcons.prototype.triangleRight;
-		Sidebar.prototype.triangleDown = HoverIcons.prototype.triangleDown;
-		Sidebar.prototype.triangleLeft = HoverIcons.prototype.triangleLeft;
-		mxVertexHandler.prototype.rotationHandleVSpacing = -18;
-		HoverIcons.prototype.inactiveOpacity = 30;
-	}
-})();
 /**
  * Main
  */

文件差異過大導致無法顯示
+ 590 - 582
war/js/app.min.js


文件差異過大導致無法顯示
+ 280 - 275
war/js/atlas-viewer.min.js


文件差異過大導致無法顯示
+ 649 - 641
war/js/atlas.min.js


+ 7 - 3
war/js/diagramly/App.js

@@ -185,7 +185,7 @@ App.pluginRegistry = {'4xAKTrabTpTzahoLthkwPNUn': '/plugins/explore.js',
 	'number': '/plugins/number.js', 'sql': '/plugins/sql.js',
 	'props': '/plugins/props.js', 'text': '/plugins/text.js',
 	'anim': '/plugins/animation.js', 'update': '/plugins/update.js',
-	'mind': '/plugins/mind/mind.js'};
+	'mind': '/plugins/mind/mind.js', 'import': '/plugins/import.js'};
 
 /**
  * Function: authorize
@@ -5079,8 +5079,12 @@ App.prototype.updateUserElement = function()
 		if (user != null)
 		{
 			this.userElement.innerHTML = '';
-			mxUtils.write(this.userElement, user.displayName);
-			this.userElement.style.display = 'block';
+			
+			if (screen.width > 560)
+			{
+				mxUtils.write(this.userElement, user.displayName);
+				this.userElement.style.display = 'block';
+			}
 		}
 		else
 		{

+ 53 - 11
war/js/diagramly/Dialogs.js

@@ -7339,9 +7339,11 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 				
 				try
 				{
-					if (data != null && data.substring(0, 10) == '<mxlibrary')
+					editorUi.spinner.stop();
+					var doc = mxUtils.parseXml(data);
+					
+					if (doc.documentElement.nodeName == 'mxlibrary')
 					{
-						var doc = mxUtils.parseXml(data);
 						var temp = JSON.parse(mxUtils.getTextContent(doc.documentElement));
 							
 						if (temp != null && temp.length > 0)
@@ -7359,7 +7361,20 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 							}
 						}
 						
-						editorUi.spinner.stop();
+						done = true;
+					}
+					else if (doc.documentElement.nodeName == 'mxfile')
+					{
+						var pages = doc.documentElement.getElementsByTagName('diagram');
+						
+						for (var i = 0; i < pages.length; i++)
+						{
+							var temp = mxUtils.getTextContent(pages[i]);
+							var cells = editorUi.stringToCells(editorUi.editor.graph.decompress(temp));
+							var size = editorUi.editor.graph.getBoundingBoxFromGeometry(cells);
+							addButton(null, null, 0, 0, 0, 0, {xml: temp, w: size.width, h: size.height});
+						}
+						
 						done = true;
 					}
 				}
@@ -7418,6 +7433,38 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 		evt.preventDefault();
 	};
 	
+	var createImportHandler = function(evt)
+	{
+		return function(data, mimeType, x, y, w, h, img, doneFn, file)
+		{
+			if (file != null && !editorUi.isOffline() && new XMLHttpRequest().upload && editorUi.isRemoteFileFormat(data, file.name))
+			{
+				editorUi.parseFile(file, mxUtils.bind(this, function(xhr)
+				{
+					if (xhr.readyState == 4)
+					{
+						editorUi.spinner.stop();
+	    				
+	    				if (xhr.status >= 200 && xhr.status <= 299)
+						{
+							var xml = xhr.responseText;
+							
+			    			addButton(xml, mimeType, x, y, w, h, img, 'fixed', (mxEvent.isAltDown(evt)) ?
+			    					null : img.substring(0, img.lastIndexOf('.')).replace(/_/g, ' '));
+			    			div.scrollTop = div.scrollHeight;
+						}
+					}
+				}));
+			}
+			else
+			{
+				addButton(data, mimeType, x, y, w, h, img, 'fixed', (mxEvent.isAltDown(evt)) ?
+						null : img.substring(0, img.lastIndexOf('.')).replace(/_/g, ' '));
+				div.scrollTop = div.scrollHeight;
+			}
+		};
+	};
+	
 	function dropHandler(evt)
 	{
 		evt.stopPropagation();
@@ -7442,12 +7489,7 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 		}
 	    else if (evt.dataTransfer.files.length > 0)
 	    {
-	    	editorUi.importFiles(evt.dataTransfer.files, 0, 0, editorUi.maxImageSize, function(data, mimeType, x, y, w, h, img)
-	    	{
-	    		addButton(data, mimeType, x, y, w, h, img, 'fixed', (mxEvent.isAltDown(evt)) ?
-		    		null : img.substring(0, img.lastIndexOf('.')).replace(/_/g, ' '));
-				div.scrollTop = div.scrollHeight;
-	    	});
+	    	editorUi.importFiles(evt.dataTransfer.files, 0, 0, editorUi.maxImageSize, createImportHandler(evt));
 		}
 	    else if (mxUtils.indexOf(evt.dataTransfer.types, 'text/uri-list') >= 0)
 	    {
@@ -7533,9 +7575,9 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 		{
 	    	errorShowed = false;
 				
-	    	editorUi.importFiles(fileInput.files, 0, 0, editorUi.maxImageSize, function(data, mimeType, x, y, w, h, img)
+	    	editorUi.importFiles(fileInput.files, 0, 0, editorUi.maxImageSize, function(data, mimeType, x, y, w, h, img, doneFn, file)
 	    	{
-	    		addButton(data, mimeType, x, y, w, h, img, 'fixed');
+	    		createImportHandler(evt)(data, mimeType, x, y, w, h, img, doneFn, file);
 
 	    		// Resets input to force change event for same file
 	    		fileInput.value = '';

+ 2 - 2
war/js/diagramly/DrawioFile.js

@@ -357,7 +357,7 @@ DrawioFile.prototype.addUnsavedStatus = function(err)
 {
 	if (err instanceof Error && err.message != null)
 	{
-		this.ui.editor.setStatus('<div class="geStatusAlert" style="cursor:pointer;">' +
+		this.ui.editor.setStatus('<div class="geStatusAlert" style="cursor:pointer;overflow:hidden;">' +
 				mxUtils.htmlEntities(mxResources.get('unsavedChanges')) +
 				' (' + mxUtils.htmlEntities(err.message) + ')</div>');
 	}
@@ -377,7 +377,7 @@ DrawioFile.prototype.addUnsavedStatus = function(err)
 //			}
 //		}
 		
-		this.ui.editor.setStatus('<div class="geStatusMessage" style="cursor:pointer;">' +
+		this.ui.editor.setStatus('<div class="geStatusAlert" style="cursor:pointer;overflow:hidden;">' +
 			mxUtils.htmlEntities(mxResources.get('unsavedChangesClickHereToSave')) + '</div>');
 		
 		// Installs click handler for saving

+ 6 - 0
war/js/diagramly/DriveRealtime.js

@@ -1271,6 +1271,12 @@ DriveRealtime.prototype.updateCollaborators = function()
 		this.collaboratorsElement.style.backgroundPosition = '100% 60%';
 		this.collaboratorsElement.style.backgroundRepeat = 'no-repeat';
 		
+		if (screen.width <= 540)
+		{
+			this.collaboratorsElement.style.maxWidth = Math.max(10, screen.width - 500) + 'px';
+			this.collaboratorsElement.style.overflow = 'hidden';
+		}
+		
 		this.ui.toolbarContainer.appendChild(this.collaboratorsElement);
 		
 		mxEvent.addListener(this.collaboratorsElement, 'click', mxUtils.bind(this, function(evt)

+ 73 - 24
war/js/diagramly/Editor.js

@@ -112,6 +112,48 @@
 		'Edward Morrison,Brand Manager,emo,Office 2,Evan Miller,me@example.com,#d5e8d4,#82b366,,https://www.draw.io,https://cdn3.iconfinder.com/data/icons/user-avatars-1/512/users-10-3-128.png\n' +
 		'Ron Donovan,System Admin,rdo,Office 3,Evan Miller,me@example.com,#d5e8d4,#82b366,"emo,tva",https://www.draw.io,https://cdn3.iconfinder.com/data/icons/user-avatars-1/512/users-2-128.png\n' +
 		'Tessa Valet,HR Director,tva,Office 4,Evan Miller,me@example.com,#d5e8d4,#82b366,,https://www.draw.io,https://cdn3.iconfinder.com/data/icons/user-avatars-1/512/users-3-128.png\n';
+	
+	/**
+	 * Global configuration of the Editor. Possible configuration values are:
+	 * 
+	 * - presetColors: array of color codes for upper palette, default is ColorDialog.prototype.presetColors (no leading #)
+	 * - defaultColors: array of color codes for the lower palette, default is ColorDialog.prototype.defaultColors (no leading #)
+	 * - defaultFonts: array of available font family names, default is Menus.prototype.defaultFonts
+	 * - defaultColorSchemes: array of array of available color schemes, default is StyleFormatPanel.prototype.defaultColorSchemes
+	 * 
+	 * (code)
+	 * Editor.configure({defaultFonts: ['Helvetica', 'Verdana', 'Times New Roman', 'Garamond',
+	 * 		'Comic Sans MS', 'Courier New', 'Georgia', 'Lucida Console', 'Tahoma'],
+	 *   presetColors: ['E6D0DE', 'CDA2BE', 'B5739D', 'E1D5E7', 'C3ABD0', 'A680B8', 'D4E1F5',
+	 *   	'A9C4EB', '7EA6E0', 'D5E8D4', '9AC7BF', '67AB9F', 'D5E8D4', 'B9E0A5', '97D077', 'FFF2CC',
+	 *   	'FFE599', 'FFD966', 'FFF4C3', 'FFCE9F', 'FFB570', 'F8CECC', 'F19C99', 'EA6B66'],
+	 * 	 defaultColorSchemes: [[null, {fill: '#f5f5f5', stroke: '#666666'},
+	 * 		{fill: '#dae8fc', stroke: '#6c8ebf'}, {fill: '#d5e8d4', stroke: '#82b366'},
+	 * 		{fill: '#ffe6cc', stroke: '#d79b00'}, {fill: '#fff2cc', stroke: '#d6b656'},
+	 * 		{fill: '#f8cecc', stroke: '#b85450'}, {fill: '#e1d5e7', stroke: '#9673a6'}],
+	 * 	    [null,
+	 * 		{fill: '#f5f5f5', stroke: '#666666', gradient: '#b3b3b3'},
+	 * 		{fill: '#dae8fc', stroke: '#6c8ebf', gradient: '#7ea6e0'},
+	 * 		{fill: '#d5e8d4', stroke: '#82b366', gradient: '#97d077'},
+	 * 		{fill: '#ffcd28', stroke: '#d79b00', gradient: '#ffa500'},
+	 * 		{fill: '#fff2cc', stroke: '#d6b656', gradient: '#ffd966'},
+	 * 		{fill: '#f8cecc', stroke: '#b85450', gradient: '#ea6b66'},
+	 * 		{fill: '#e6d0de', stroke: '#996185', gradient: '#d5739d'}],
+	 * 		[null, {fill: '#eeeeee', stroke: '#36393d'},
+	 * 		{fill: '#f9f7ed', stroke: '#36393d'}, {fill: '#ffcc99', stroke: '#36393d'},
+	 * 		{fill: '#cce5ff', stroke: '#36393d'}, {fill: '#ffff88', stroke: '#36393d'},
+	 * 		{fill: '#cdeb8b', stroke: '#36393d'}, {fill: '#ffcccc', stroke: '#36393d'}]]});
+	 * (end)
+	 */
+	Editor.configure = function(config)
+	{
+		// LATER: DefaultFont and DefaultFontSize should override Graph's stylesheet,
+		// default edge and vertex styles would have to be set before loading mxSettings
+		ColorDialog.prototype.presetColors = config.presetColors || ColorDialog.prototype.presetColors;
+		ColorDialog.prototype.defaultColors = config.defaultColors || ColorDialog.prototype.defaultColors;
+		Menus.prototype.defaultFonts = config.defaultFonts || Menus.prototype.defaultFonts;
+		StyleFormatPanel.prototype.defaultColorSchemes = config.defaultColorSchemes || StyleFormatPanel.prototype.defaultColorSchemes;
+	};
 
 	/**
 	 * Executes the first step for connecting to Google Drive.
@@ -639,6 +681,26 @@
 
 			return div;
 		};
+		
+		/**
+		 * Configures global color schemes.
+		 */
+		StyleFormatPanel.prototype.defaultColorSchemes = [[null, {fill: '#f5f5f5', stroke: '#666666'},
+			{fill: '#dae8fc', stroke: '#6c8ebf'}, {fill: '#d5e8d4', stroke: '#82b366'},
+			{fill: '#ffe6cc', stroke: '#d79b00'}, {fill: '#fff2cc', stroke: '#d6b656'},
+			{fill: '#f8cecc', stroke: '#b85450'}, {fill: '#e1d5e7', stroke: '#9673a6'}],
+		    [null,
+			{fill: '#f5f5f5', stroke: '#666666', gradient: '#b3b3b3'},
+			{fill: '#dae8fc', stroke: '#6c8ebf', gradient: '#7ea6e0'},
+			{fill: '#d5e8d4', stroke: '#82b366', gradient: '#97d077'},
+			{fill: '#ffcd28', stroke: '#d79b00', gradient: '#ffa500'},
+			{fill: '#fff2cc', stroke: '#d6b656', gradient: '#ffd966'},
+			{fill: '#f8cecc', stroke: '#b85450', gradient: '#ea6b66'},
+			{fill: '#e6d0de', stroke: '#996185', gradient: '#d5739d'}],
+			[null, {fill: '#eeeeee', stroke: '#36393d'},
+			{fill: '#f9f7ed', stroke: '#36393d'}, {fill: '#ffcc99', stroke: '#36393d'},
+			{fill: '#cce5ff', stroke: '#36393d'}, {fill: '#ffff88', stroke: '#36393d'},
+			{fill: '#cdeb8b', stroke: '#36393d'}, {fill: '#ffcccc', stroke: '#36393d'}]];
 
 		/**
 		 * Adds predefiend styles.
@@ -805,43 +867,30 @@
 				this.editorUi.currentScheme = 0;
 			}
 
-			var schemes = [[null, {fill: '#f5f5f5', stroke: '#666666'},
-				{fill: '#dae8fc', stroke: '#6c8ebf'}, {fill: '#d5e8d4', stroke: '#82b366'},
-				{fill: '#ffe6cc', stroke: '#d79b00'}, {fill: '#fff2cc', stroke: '#d6b656'},
-				{fill: '#f8cecc', stroke: '#b85450'}, {fill: '#e1d5e7', stroke: '#9673a6'}],
-			    [null,
-				{fill: '#f5f5f5', stroke: '#666666', gradient: '#b3b3b3'},
-				{fill: '#dae8fc', stroke: '#6c8ebf', gradient: '#7ea6e0'},
-				{fill: '#d5e8d4', stroke: '#82b366', gradient: '#97d077'},
-				{fill: '#ffcd28', stroke: '#d79b00', gradient: '#ffa500'},
-				{fill: '#fff2cc', stroke: '#d6b656', gradient: '#ffd966'},
-				{fill: '#f8cecc', stroke: '#b85450', gradient: '#ea6b66'},
-				{fill: '#e6d0de', stroke: '#996185', gradient: '#d5739d'}],
-				[null, {fill: '#eeeeee', stroke: '#36393d'},
-				{fill: '#f9f7ed', stroke: '#36393d'}, {fill: '#ffcc99', stroke: '#36393d'},
-				{fill: '#cce5ff', stroke: '#36393d'}, {fill: '#ffff88', stroke: '#36393d'},
-				{fill: '#cdeb8b', stroke: '#36393d'}, {fill: '#ffcccc', stroke: '#36393d'}]];
-			
 			var left = document.createElement('div');
 			left.style.cssText = 'position:absolute;left:10px;top:8px;bottom:8px;width:20px;margin:4px;opacity:0.5;' +
 				'background-repeat:no-repeat;background-position:center center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAQBAMAAADQT4M0AAAAIVBMVEUAAAB2dnZ4eHh3d3d1dXVxcXF2dnZ2dnZ2dnZxcXF2dnYmb3w1AAAACnRSTlMAfCTkhhvb7cQSPH2JPgAAADRJREFUCNdjwACMAmBKaiGYs2oJmLPKAZ3DabU8AMRTXpUKopislqFyVzCAuUZgikkBZjoAcMYLnp53P/UAAAAASUVORK5CYII=);';
-			div.appendChild(left);
 			
 			mxEvent.addListener(left, 'click', mxUtils.bind(this, function()
 			{
-				this.editorUi.currentScheme = mxUtils.mod(this.editorUi.currentScheme - 1, schemes.length);
-				updateScheme(schemes[this.editorUi.currentScheme]);
+				this.editorUi.currentScheme = mxUtils.mod(this.editorUi.currentScheme - 1, this.defaultColorSchemes.length);
+				updateScheme(this.defaultColorSchemes[this.editorUi.currentScheme]);
 			}));
 			
 			var right = document.createElement('div');
 			right.style.cssText = 'position:absolute;left:202px;top:8px;bottom:8px;width:20px;margin:4px;opacity:0.5;' +
 				'background-repeat:no-repeat;background-position:center center;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAQBAMAAADQT4M0AAAAIVBMVEUAAAB2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnYBuwCcAAAACnRSTlMAfCTkhhvb7cQSPH2JPgAAADZJREFUCNdjQAOMAmBKaiGY8loF5rKswsZlrVo8AUiFrTICcbIWK8A5DF1gDoMymMPApIAwHwCS0Qx/U7qCBQAAAABJRU5ErkJggg==);';
-			div.appendChild(right);
+
+			if (this.defaultColorSchemes.length > 1)
+			{
+				div.appendChild(left);
+				div.appendChild(right);
+			}
 			
 			mxEvent.addListener(right, 'click', mxUtils.bind(this, function()
 			{
-				this.editorUi.currentScheme = mxUtils.mod(this.editorUi.currentScheme + 1, schemes.length);
-				updateScheme(schemes[this.editorUi.currentScheme]);
+				this.editorUi.currentScheme = mxUtils.mod(this.editorUi.currentScheme + 1, this.defaultColorSchemes.length);
+				updateScheme(this.defaultColorSchemes[this.editorUi.currentScheme]);
 			}));
 			
 			// Hover state
@@ -860,7 +909,7 @@
 			addHoverState(left);
 			addHoverState(right);
 			
-			updateScheme(schemes[this.editorUi.currentScheme]);
+			updateScheme(this.defaultColorSchemes[this.editorUi.currentScheme]);
 			
 			return div;
 		};

+ 162 - 70
war/js/diagramly/EditorUi.js

@@ -1222,6 +1222,7 @@
 		var noFile = mxUtils.bind(this, function()
 		{
 			this.setGraphEnabled(false);
+			this.setCurrentFile(null);
 			
 			// Keeps initial title if no file existed before
 			if (oldFile != null)
@@ -1367,7 +1368,15 @@
 					}
 					else if (oldFile != null)
 					{
-						this.fileLoaded(oldFile);
+						// Workaround for close realtime model is to reload the file from scratch
+						if (oldFile.constructor == DriveFile)
+						{
+							this.loadFile(oldFile.getHash());
+						}
+						else
+						{
+							this.fileLoaded(oldFile);
+						}
 					}
 					else
 					{
@@ -1939,7 +1948,7 @@
 					
 				    if (evt.dataTransfer.files.length > 0)
 				    {	
-				    	this.importFiles(evt.dataTransfer.files, 0, 0, this.maxImageSize, mxUtils.bind(this, function(data, mimeType, x, y, w, h, img)
+				    	this.importFiles(evt.dataTransfer.files, 0, 0, this.maxImageSize, mxUtils.bind(this, function(data, mimeType, x, y, w, h, img, doneFn, file)
 				    	{
 							if (data != null && mimeType.substring(0, 6) == 'image/')
 							{
@@ -1949,59 +1958,104 @@
 								cells[0].vertex = true;
 	
 								addCells(cells, new mxRectangle(0, 0, w, h), evt, (mxEvent.isAltDown(evt)) ? null : img.substring(0, img.lastIndexOf('.')).replace(/_/g, ' '));
+
+								if (dropTarget != null && dropTarget.parentNode != null && images.length > 0)
+								{
+									dropTarget.parentNode.removeChild(dropTarget);
+									dropTarget = null;
+								}
 							}
 							else
 							{
 								var done = false;
 								
-								if (data != null && mimeType == 'text/xml')
+								var doImport = mxUtils.bind(this, function(theData, theMimeType)
 								{
-									var doc = mxUtils.parseXml(data);
-									
-									if (doc.documentElement.nodeName == 'mxlibrary')
+									if (theData != null && theMimeType == 'text/xml')
 									{
-										try
+										var doc = mxUtils.parseXml(theData);
+										
+										if (doc.documentElement.nodeName == 'mxlibrary')
 										{
-											var temp = JSON.parse(mxUtils.getTextContent(doc.documentElement));
-											addImages(temp, contentDiv);
-											images = images.concat(temp);
-											saveLibrary(evt);
-											this.spinner.stop();
-											done = true;
+											try
+											{
+												var temp = JSON.parse(mxUtils.getTextContent(doc.documentElement));
+												addImages(temp, contentDiv);
+												images = images.concat(temp);
+												saveLibrary(evt);
+												this.spinner.stop();
+												done = true;
+											}
+											catch (e)
+											{
+												// ignore
+											}
 										}
-										catch (e)
+										else if (doc.documentElement.nodeName == 'mxfile')
 										{
-											// ignore
+											try
+											{
+												var pages = doc.documentElement.getElementsByTagName('diagram');
+												
+												for (var i = 0; i < pages.length; i++)
+												{
+													var temp = mxUtils.getTextContent(pages[i]);
+													var cells = this.stringToCells(this.editor.graph.decompress(temp));
+													var size = this.editor.graph.getBoundingBoxFromGeometry(cells);
+													addCells(cells, new mxRectangle(0, 0, size.width, size.height), evt);
+												}
+												
+												done = true;
+											}
+											catch (e)
+											{
+												if (window.console != null)
+												{
+													console.log('error in drop handler:', e);
+												}
+											}
 										}
 									}
-									else if (doc.documentElement.nodeName == 'mxfile')
+									
+									if (!done)
 									{
-										try
-										{
-											var temp = mxUtils.getTextContent(doc.documentElement.getElementsByTagName('diagram')[0]);
-											var cells = this.stringToCells(this.editor.graph.decompress(temp));
-											addCells(cells, new mxRectangle(0, 0, w, h), evt);
-											done = true;
-										}
-										catch (e)
+										this.spinner.stop();
+										this.handleError({message: mxResources.get('errorLoadingFile')})
+									}
+
+									if (dropTarget != null && dropTarget.parentNode != null && images.length > 0)
+									{
+										dropTarget.parentNode.removeChild(dropTarget);
+										dropTarget = null;
+									}
+								});
+								
+								if (!this.isOffline() && new XMLHttpRequest().upload && this.isRemoteFileFormat(data, img) && file != null)
+								{
+									this.parseFile(file, mxUtils.bind(this, function(xhr)
+									{
+										if (xhr.readyState == 4)
 										{
-											// ignore
+											this.spinner.stop();
+											
+											if (xhr.status >= 200 && xhr.status <= 299)
+											{
+												doImport(xhr.responseText, 'text/xml');
+											}
+											else
+											{
+												this.handleError({message: mxResources.get((xhr.status == 413) ?
+					            						'drawingTooLarge' : 'invalidOrMissingFile')},
+					            						mxResources.get('errorLoadingFile'));
+											}
 										}
-									}
+									}));
 								}
-								
-								if (!done)
+								else
 								{
-									this.spinner.stop();
-									this.handleError({message: mxResources.get('errorLoadingFile')})
+									doImport(data, mimeType);
 								}
 							}
-							
-							if (dropTarget != null && dropTarget.parentNode != null && images.length > 0)
-							{
-								dropTarget.parentNode.removeChild(dropTarget);
-								dropTarget = null;
-							}
 				    	}));
 					}
 				    
@@ -2193,7 +2247,7 @@
 	{
 		var dlg = new LibraryDialog(this, name, sidebar, images, file, mode);
 		
-		this.showDialog(dlg.container, 620, 440, true, true, mxUtils.bind(this, function(cancel)
+		this.showDialog(dlg.container, 620, 440, true, false, mxUtils.bind(this, function(cancel)
 		{
 			if (cancel && this.getCurrentFile() == null && urlParams['embed'] != '1')
 			{
@@ -3087,7 +3141,7 @@
 			params.push('title=' + encodeURIComponent(file.getTitle()));
 		}
 		
-		return ((mxClient.IS_CHROMEAPP) ? 'https://www.draw.io/' : 'https://' + location.host + '/') +
+		return ((mxClient.IS_CHROMEAPP || EditorUi.isElectronApp) ? 'https://www.draw.io/' : 'https://' + location.host + '/') +
 			((params.length > 0) ? '?' + params.join('&') : '') + data;
 	};
 	
@@ -4935,6 +4989,11 @@
 						
 						if (xml != null && xml.substring(0, 10) == '<mxlibrary')
 						{
+							if (filename != null && filename.toLowerCase().substring(filename.length - 5) == '.vssx')
+							{
+								filename = filename.substring(0, filename.length - 5) + '.xml';
+							}
+							
 							this.loadLibrary(new LocalLibrary(this, xml, filename));
 						}
 						else
@@ -5220,7 +5279,7 @@
 				    				if (!containsModel)
 				    				{
 				    					// Cannot load local files in Chrome App
-				    					if (window.chrome != null && chrome.app != null && chrome.app.runtime != null)
+				    					if (mxClient.IS_CHROMEAPP)
 				    					{
 				    						this.spinner.stop();
 				    						this.showError(mxResources.get('error'), mxResources.get('dragAndDropNotSupported'),
@@ -6513,7 +6572,7 @@
 											this.openLocalFile(xml, null, true);
 										}
 									}
-									if (!this.isOffline() && this.isRemoteFileFormat(data))
+									else if (!this.isOffline() && this.isRemoteFileFormat(data))
 									{
 							    		new mxXmlRequest(OPEN_URL, 'format=xml&data=' + encodeURIComponent(data)).send(mxUtils.bind(this, function(req)
 										{
@@ -8298,37 +8357,70 @@
 		
 		if (this.isOfflineApp())
 		{
-			// In FF, IE and Safari (desktop) the cache status never changes
-			if ((mxClient.IS_GC || (mxClient.IS_IOS && mxClient.IS_SF)) && applicationCache != null)
-			{
-				var appCache = applicationCache;
-		
-				if (this.offlineStatus == null)
+			var appCache = applicationCache;
+			
+			// NOTE: HTML5 Cache is deprecated
+			if (appCache != null && this.offlineStatus == null)
+			{
+				this.offlineStatus = document.createElement('div');
+				this.offlineStatus.className = 'geItem';
+				this.offlineStatus.style.position = 'absolute';
+				this.offlineStatus.style.fontSize = '8pt';
+				this.offlineStatus.style.top = '2px';
+				this.offlineStatus.style.right = '12px';
+				this.offlineStatus.style.color = '#666';
+				this.offlineStatus.style.margin = '4px';
+				this.offlineStatus.style.padding = '2px';
+				this.offlineStatus.style.verticalAlign = 'middle';
+				this.offlineStatus.innerHTML = '';
+				
+				this.menubarContainer.appendChild(this.offlineStatus);
+				
+				var appCache = window.applicationCache;
+
+				function getImageTagForStatus(status)
+				{
+					switch (status)
+					{
+					  case appCache.UNCACHED: // UNCACHED == 0
+					    return '';
+					    break;
+					  case appCache.IDLE: // IDLE == 1
+					    return '<img title="Cached" border="0" src="' + IMAGE_PATH + '/checkmark.gif"/>';
+					    break;
+					  case appCache.CHECKING: // CHECKING == 2
+					    return '<img title="Checking..." border="0" src="' + IMAGE_PATH + '/spin.gif"/>';
+					    break;
+					  case appCache.DOWNLOADING: // DOWNLOADING == 3
+					    return '<img title="Downloading..." border="0" src="' + IMAGE_PATH + '/spin.gif"/>';
+					    break;
+					  case appCache.UPDATEREADY:  // UPDATEREADY == 4
+					    return '<img title="Update ready" border="0" src="' + IMAGE_PATH + '/download.png"/>';
+					    break;
+					  case appCache.OBSOLETE: // OBSOLETE == 5
+					    return '<img title="Obsolete" border="0" src="' + IMAGE_PATH + '/clear.gif"/>';
+					    break;
+					  default:
+					    return '<img title="Unknown" border="0" src="' + IMAGE_PATH + '/clear.gif"/>';
+					    break;
+					};
+				};
+
+				var updateStatus = mxUtils.bind(this, function()
 				{
-					this.offlineStatus = document.createElement('div');
-					this.offlineStatus.className = 'geItem';
-					this.offlineStatus.style.position = 'absolute';
-					this.offlineStatus.style.fontSize = '8pt';
-					this.offlineStatus.style.top = '2px';
-					this.offlineStatus.style.right = '12px';
-					this.offlineStatus.style.color = '#666';
-					this.offlineStatus.style.margin = '4px';
-					this.offlineStatus.style.padding = '2px';
-					this.offlineStatus.style.verticalAlign = 'middle';
-					this.offlineStatus.innerHTML = '';
-					
-					this.menubarContainer.appendChild(this.offlineStatus);
-		
-					// Events are not working, use polling instead (10 secs interval)
-					var thread = window.setTimeout(mxUtils.bind(this, function()
-					{
-						if (appCache.status == appCache.IDLE)
-						{
-							this.offlineStatus.innerHTML = '[' + '<img title="Cached" border="0" src="' + IMAGE_PATH + '/checkmark.gif"/>]';
-							window.clearTimeout(thread);
-						}
-					}), 5000);
-				}
+					this.offlineStatus.innerHTML = getImageTagForStatus(appCache.status);
+				});
+				
+				mxEvent.addListener(appCache, 'checking', updateStatus);
+				mxEvent.addListener(appCache, 'noupdate', updateStatus);
+				mxEvent.addListener(appCache, 'downloading', updateStatus);
+				mxEvent.addListener(appCache, 'progress', updateStatus);
+				mxEvent.addListener(appCache, 'cached', updateStatus);
+				mxEvent.addListener(appCache, 'updateready', updateStatus);
+				mxEvent.addListener(appCache, 'obsolete', updateStatus);
+				mxEvent.addListener(appCache, 'error', updateStatus);
+				
+				updateStatus();
 			}
 		}
 		else

+ 2 - 2
war/js/diagramly/Menus.js

@@ -1221,7 +1221,7 @@
 			menu.addSeparator(parent);
 
 			// Redirects export to PDF to print in Chrome App
-			if (editorUi.printPdfExport)
+			if (editorUi.isOffline() || editorUi.printPdfExport)
 			{
 				menu.addItem(mxResources.get('formatPdf') + '...', null, this.editorUi.actions.get('exportPdf').funct, parent);
 			}
@@ -1335,7 +1335,7 @@
 			}), parent);
 
 			// Disables menu item for all external hosted integrations
-			if (/.*\.draw\.io$/.test(window.location.hostname))
+			if (mxClient.IS_CHROMEAPP || EditorUi.isElectronApp ||/.*\.draw\.io$/.test(window.location.hostname))
 			{
 				menu.addItem(mxResources.get('url') + '...', null, mxUtils.bind(this, function()
 				{

+ 2 - 2
war/js/diagramly/Settings.js

@@ -19,7 +19,7 @@ var mxSettings =
 		recentColors: [],
 		formatWidth: '240',
 		currentEdgeStyle: Graph.prototype.defaultEdgeStyle,
-		currentVertexStyle: {},
+		currentVertexStyle: Graph.prototype.defaultVertexStyle,
 		createTarget: false,
 		pageFormat: mxGraph.prototype.pageFormat,
 		search: true,
@@ -234,7 +234,7 @@ var mxSettings =
 			
 			if (this.settings.currentVertexStyle == null)
 			{
-				this.settings.currentVertexStyle = {};
+				this.settings.currentVertexStyle = Graph.prototype.defaultEdgeStyle;
 			}
 			
 			if (this.settings.createTarget == null)

+ 4 - 4
war/js/diagramly/sidebar/Sidebar-Basic.js

@@ -12,10 +12,10 @@
 		
 		this.addPaletteFunctions('basic', mxResources.get('basic'), false,
 		[
-			this.createVertexTemplateEntry('whiteSpace=wrap;html=1;aspect=fixed;', 80, 80, '', 'Square', null, null, 'square'),
-			this.createVertexTemplateEntry('ellipse;whiteSpace=wrap;html=1;aspect=fixed;', 80, 80, '', 'Circle', null, null, 'circle'),
-			this.createVertexTemplateEntry('shape=ext;double=1;whiteSpace=wrap;html=1;aspect=fixed;', 80, 80, '', 'Double Square', null, null, 'double square'),
-			this.createVertexTemplateEntry('ellipse;shape=doubleEllipse;whiteSpace=wrap;html=1;aspect=fixed;', 80, 80, '', 'Double Circle', null, null, 'double circle'),
+			this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;left=0;right=0;fillColor=none;', 120, 60, '', 'Partial Rectangle'),
+			this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;top=0;bottom=0;fillColor=none;', 120, 60, '', 'Partial Rectangle'),
+			this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;left=0;right=0;top=0;fillColor=none;routingCenterY=0.5;', 120, 60, '', 'Partial Rectangle'),
+			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(s2 + '4_point_star', 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(' ')),

文件差異過大導致無法顯示
+ 87 - 87
war/js/embed-static.min.js


文件差異過大導致無法顯示
+ 61 - 49
war/js/mxgraph/Dialogs.js


+ 8 - 2
war/js/mxgraph/EditorUi.js

@@ -428,7 +428,7 @@ EditorUi = function(editor, container, lightbox)
 	this.clearDefaultStyle = function()
 	{
 		graph.currentEdgeStyle = graph.defaultEdgeStyle;
-		graph.currentVertexStyle = {};
+		graph.currentVertexStyle = graph.defaultVertexStyle;
 		
 		// Updates UI
 		this.fireEvent(new mxEventObject('styleChanged', 'keys', [], 'values', [], 'cells', []));
@@ -931,7 +931,7 @@ EditorUi.prototype.editButtonLink = null;
  * Specifies the position of the horizontal split bar. Default is 204 or 120 for
  * screen widths <= 500px.
  */
-EditorUi.prototype.hsplitPosition = (screen.width <= 500) ? 116 : 208;
+EditorUi.prototype.hsplitPosition = (screen.width <= 640) ? ((screen.width <= 360) ? 62 : 116) : 208;
 
 /**
  * Specifies if animations are allowed in <executeLayout>. Default is true.
@@ -2869,6 +2869,12 @@ EditorUi.prototype.createStatusContainer = function()
 	var container = document.createElement('a');
 	container.className = 'geItem geStatus';
 	
+	if (screen.width < 420)
+	{
+		container.style.maxWidth = Math.max(20, screen.width - 320) + 'px';
+		container.style.overflow = 'hidden';
+	}
+	
 	return container;
 };
 

+ 1 - 1
war/js/mxgraph/Format.js

@@ -249,7 +249,7 @@ Format.prototype.isComicState = function(state)
 	                        'swimlane', 'triangle', 'trapezoid', 'ext', 'step', 'tee', 'process', 'link', 'rhombus',
 	                        'offPageConnector', 'loopLimit', 'hexagon', 'manualInput', 'singleArrow', 'doubleArrow',
 	                        'flexArrow', 'card', 'umlLifeline', 'connector', 'folder', 'component', 'sortShape',
-	                        'cross', 'umlFrame', 'cube', 'isoCube', 'isoRectangle'], shape) >= 0;
+	                        'cross', 'umlFrame', 'cube', 'isoCube', 'isoRectangle', 'partialRectangle'], shape) >= 0;
 };
 
 /**

+ 56 - 42
war/js/mxgraph/Graph.js

@@ -69,7 +69,9 @@ Graph = function(container, model, renderHint, stylesheet, themes)
 	mxGraph.call(this, container, model, renderHint, stylesheet);
 	
 	this.themes = themes || this.defaultThemes;
-	
+	this.currentEdgeStyle = this.defaultEdgeStyle;
+	this.currentVertexStyle = this.defaultVertexStyle;
+
 	// Sets the base domain URL and domain path URL for relative links.
 	var b = this.baseUrl;
 	var p = b.indexOf('//');
@@ -422,7 +424,7 @@ Graph = function(container, model, renderHint, stylesheet, themes)
 		{
 			this.loadStylesheet();
 		}
-		
+
 		// Adds page centers to the guides for moving cells
 		var graphHandlerGetGuideStates = this.graphHandler.getGuideStates;
 		this.graphHandler.getGuideStates = function()
@@ -3225,42 +3227,46 @@ HoverIcons.prototype.setCurrentState = function(state)
 		        pt = mxUtils.getRotatedPoint(pt, cos, sin, center);
 		    }
 		    
-		    // Finds closest connection point
-		    if (start != null)
-		    {
-		        var constraints = this.graph.getAllConnectionConstraints(start)
-		        var nearest = null;
-		        var dist = null;
-		    
-		        for (var i = 0; i < constraints.length; i++)
-		        {
-		            var cp = this.graph.getConnectionPoint(start, constraints[i]);
-		            
-		            if (cp != null)
-		            {
-		                var tmp = (cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);
-		            
-		                if (dist == null || tmp < dist)
-		                {
-		                    nearest = cp;
-		                    dist = tmp;
-		                }
-		            }
-		        }
-		        
-		        if (nearest != null)
-		        {
-		            pt = nearest;
-		        }
-		    }
-		    
-		    edge.setAbsoluteTerminalPoint(pt, source);
+		    edge.setAbsoluteTerminalPoint(this.snapToAnchorPoint(edge, start, end, source, pt), source);
 		}
 		else
 		{
 			mxGraphViewUpdateFloatingTerminalPoint.apply(this, arguments);
 		}
 	};
+
+	mxGraphView.prototype.snapToAnchorPoint = function(edge, start, end, source, pt)
+	{
+		if (start != null && edge != null)
+		{
+	        var constraints = this.graph.getAllConnectionConstraints(start)
+	        var nearest = null;
+	        var dist = null;
+	    
+	        for (var i = 0; i < constraints.length; i++)
+	        {
+	            var cp = this.graph.getConnectionPoint(start, constraints[i]);
+	            
+	            if (cp != null)
+	            {
+	                var tmp = (cp.x - pt.x) * (cp.x - pt.x) + (cp.y - pt.y) * (cp.y - pt.y);
+	            
+	                if (dist == null || tmp < dist)
+	                {
+	                    nearest = cp;
+	                    dist = tmp;
+	                }
+	            }
+	        }
+	        
+	        if (nearest != null)
+	        {
+	            pt = nearest;
+	        }
+		}
+		
+		return pt;
+	};
 		
 	/**
 	 * Adds support for placeholders in text elements of shapes.
@@ -3673,21 +3679,16 @@ if (typeof mxVertexHandler != 'undefined')
 			return marker;
 		};
 		
+		/**
+		 * 
+		 */
+		Graph.prototype.defaultVertexStyle = {};
+
 		/**
 		 * Contains the default style for edges.
 		 */
 		Graph.prototype.defaultEdgeStyle = {'edgeStyle': 'orthogonalEdgeStyle', 'rounded': '0', 'html': '1',
 			'jettySize': 'auto', 'orthogonalLoop': '1'};
-		
-		/**
-		 * Contains the current style for edges.
-		 */
-		Graph.prototype.currentEdgeStyle = Graph.prototype.defaultEdgeStyle;
-		
-		/**
-		 * Contains the current style for vertices.
-		 */
-		Graph.prototype.currentVertexStyle = {};
 
 		/**
 		 * Returns the current edge style as a string.
@@ -6327,6 +6328,19 @@ if (typeof mxVertexHandler != 'undefined')
 				{
 					dx = this.graph.snap(dx);
 					dy = this.graph.snap(dy);
+					
+					if (!this.graph.isGridEnabled())
+					{
+						if (dx < this.graph.tolerance)
+						{
+							dx = 0;
+						}
+						
+						if (dy < this.graph.tolerance)
+						{
+							dy = 0;
+						}
+					}
 				}
 			}
 			

+ 3 - 1
war/js/mxgraph/Menus.js

@@ -30,7 +30,9 @@ Menus.prototype.defaultFontSize = '12';
 /**
  * Sets the default font size.
  */
-Menus.prototype.defaultMenuItems = ['file', 'edit', 'view', 'arrange', 'extras', 'help'];
+Menus.prototype.defaultMenuItems = (screen.width > 480) ?
+	['file', 'edit', 'view', 'arrange', 'extras', 'help'] :
+	['file', 'edit', 'view', 'arrange', 'extras'];
 
 /**
  * Adds the label menu items to the given menu and parent.

+ 2 - 2
war/js/mxgraph/Sidebar.js

@@ -953,8 +953,8 @@ Sidebar.prototype.addBasicPalette = function(dir)
 		null, null, null, null, [
 		this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;left=0;right=0;fillColor=none;', 120, 60, '', 'Partial Rectangle'),
 		this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;top=0;bottom=0;fillColor=none;', 120, 60, '', 'Partial Rectangle'),
-		this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;left=0;right=0;top=0;fillColor=none;', 120, 60, '', 'Partial Rectangle'),
-		this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;right=0;top=0;bottom=0;fillColor=none;', 120, 60, '', 'Partial Rectangle')
+		this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;left=0;right=0;top=0;fillColor=none;routingCenterY=0.5;', 120, 60, '', 'Partial Rectangle'),
+		this.createVertexTemplateEntry('shape=partialRectangle;whiteSpace=wrap;html=1;right=0;top=0;bottom=0;fillColor=none;routingCenterX=-0.5;', 120, 60, '', 'Partial Rectangle')
 	]);
 };
 

+ 24 - 11
war/js/mxgraph/Toolbar.js

@@ -109,7 +109,7 @@ Toolbar.prototype.init = function()
 	elts[1].setAttribute('title', mxResources.get('undo') + ' (' + this.editorUi.actions.get('undo').shortcut + ')');
 	elts[2].setAttribute('title', mxResources.get('redo') + ' (' + this.editorUi.actions.get('redo').shortcut + ')');
 	
-	if (sw >= 470)
+	if (sw >= 320)
 	{
 		var elts = this.addItems(['-', 'delete']);
 		elts[1].setAttribute('title', mxResources.get('delete') + ' (' + this.editorUi.actions.get('delete').shortcut + ')');
@@ -120,24 +120,37 @@ Toolbar.prototype.init = function()
 		this.addItems(['-', 'toFront', 'toBack']);
 	}
 
-	if (sw >= 640)
+	if (sw >= 740)
 	{
-		this.addItems(['-', 'fillColor', 'strokeColor', 'shadow']);
+		this.addItems(['-', 'fillColor']);
+		
+		if (sw >= 780)
+		{
+			this.addItems(['strokeColor']);
+			
+			if (sw >= 820)
+			{
+				this.addItems(['shadow']);
+			}
+		}
 	}
 	
-	if (sw >= 320)
+	if (sw >= 400)
 	{
 		this.addSeparator();
 		
-		this.edgeShapeMenu = this.addMenuFunction('', mxResources.get('connection'), false, mxUtils.bind(this, function(menu)
+		if (sw >= 440)
 		{
-			this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], [null, null], 'geIcon geSprite geSprite-connection', null, true).setAttribute('title', mxResources.get('line'));
-			this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['link', null], 'geIcon geSprite geSprite-linkedge', null, true).setAttribute('title', mxResources.get('link'));
-			this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['flexArrow', null], 'geIcon geSprite geSprite-arrow', null, true).setAttribute('title', mxResources.get('arrow'));
-			this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['arrow', null], 'geIcon geSprite geSprite-simplearrow', null, true).setAttribute('title', mxResources.get('simpleArrow'));
-		}));
+			this.edgeShapeMenu = this.addMenuFunction('', mxResources.get('connection'), false, mxUtils.bind(this, function(menu)
+			{
+				this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], [null, null], 'geIcon geSprite geSprite-connection', null, true).setAttribute('title', mxResources.get('line'));
+				this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['link', null], 'geIcon geSprite geSprite-linkedge', null, true).setAttribute('title', mxResources.get('link'));
+				this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['flexArrow', null], 'geIcon geSprite geSprite-arrow', null, true).setAttribute('title', mxResources.get('arrow'));
+				this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_SHAPE, 'width'], ['arrow', null], 'geIcon geSprite geSprite-simplearrow', null, true).setAttribute('title', mxResources.get('simpleArrow'));
+			}));
 	
-		this.addDropDownArrow(this.edgeShapeMenu, 'geSprite-connection', 44, 50, 0, 0, 22, -4);
+			this.addDropDownArrow(this.edgeShapeMenu, 'geSprite-connection', 44, 50, 0, 0, 22, -4);
+		}
 	
 		this.edgeStyleMenu = this.addMenuFunction('geSprite-orthogonal', mxResources.get('waypoints'), false, mxUtils.bind(this, function(menu)
 		{

文件差異過大導致無法顯示
+ 87 - 87
war/js/reader.min.js


文件差異過大導致無法顯示
+ 282 - 278
war/js/viewer.min.js


+ 83 - 0
war/plugins/import.js

@@ -0,0 +1,83 @@
+/**
+ * Plugin for Freemind import.
+ * See https://github.com/jiangxin/freemind-mmx/tree/master/freemind
+ */
+Draw.loadPlugin(function(ui) {
+	var graph = ui.editor.graph;
+	
+	// Adds resource for action
+	mxResources.parse('importFreemind=Freemind');
+	
+	// Parses Freemind data
+	function importFreemindData(data)
+	{
+		// Gets the default parent for inserting new cells. This
+		// is normally the first child of the root (ie. layer 0).
+		var parent = graph.getDefaultParent();
+		var cells = [];
+		
+		// Makes the import one undoable edit
+		graph.getModel().beginUpdate();
+		try
+		{
+			// Gets point for free space in the graph for insert
+			var pt = graph.getFreeInsertPoint();
+
+			//
+			// TODO: Import freemind data at pt.x/pt.y like so...
+			//
+			cells.push(graph.insertVertex(parent, null, data, pt.x, pt.y, 80, 30));
+			
+			// Applies current styles to new cells (might not be needed)
+			graph.fireEvent(new mxEventObject('cellsInserted', 'cells', cells));
+		}
+		finally
+		{
+			graph.getModel().endUpdate();
+		}
+		
+		// Selects new cells and scrolls into view
+		graph.setSelectionCells(cells);
+       	graph.scrollCellToVisible(graph.getSelectionCell());
+	};
+
+  	// Adds action
+	ui.actions.addAction('importFreemind...', function()
+	{
+		// Only modern browsers for now. We'll move the import
+		// code above to the main codebase later
+		if (Graph.fileSupport && !mxClient.IS_IE && !mxClient.IS_IE11)
+		{
+			var input = document.createElement('input');
+			input.setAttribute('type', 'file');
+			
+			mxEvent.addListener(input, 'change', function()
+			{
+				if (input.files != null)
+				{
+					// Only one file for now...
+					var reader = new FileReader();
+					
+					reader.onload = function(e)
+					{
+						importFreemindData(e.target.result);
+					};
+					
+					reader.readAsText(input.files[0]);
+				}
+			});
+
+			input.click();
+		}
+	});
+	
+	// Adds menu
+	ui.menubar.addMenu('Import', function(menu, parent)
+	{
+		ui.menus.addMenuItem(menu, 'importFreemind');
+	});
+	
+	// Moves import menu to before help menu
+	ui.menubar.container.insertBefore(ui.menubar.container.lastChild,
+		ui.menubar.container.lastChild.previousSibling.previousSibling.previousSibling);
+});

+ 28 - 25
war/plugins/mind/mind.js

@@ -58,12 +58,11 @@ Draw.loadPlugin(function(ui)
 							tmp.push(vertex);
 						}
 						
-						return true;
+						// Stop traversal on collapsed vertices
+						return vertex == cells[i] || !graph.model.isCollapsed(vertex);
 					});
 					
 					graph.model.setCollapsed(cells[i], collapse);
-					
-					//mxUtils.remove(cells[i], newCells);
 				}
 			}
 
@@ -438,43 +437,47 @@ Draw.loadPlugin(function(ui)
 	
     sb.addPalette('mindmaps', 'Mindmaps', true, function(content)
     {
-    	content.appendChild(ui.sidebar.createVertexTemplate('shape=cloud;mindmapRoot=1;fontSize=15;fontStyle=1;strokeWidth=2;' +
-        	'align=center;points=[[0.16,0.55,0],[0.875,0.5,0]];snapToPoint=1;collapsible=1;', 120, 80, 'Main Idea', 'Mindmap Root'));
-        
+    	var sw = 1;
+    	
+    	content.appendChild(ui.sidebar.createVertexTemplate('ellipse;whiteSpace=wrap;html=1;mindmapRoot=1;' +
+    		'strokeWidth=' + sw + ';collapsible=0;container=1;recursiveResize=0;align=center;',
+        	120, 60, 'Main Topic', 'Mindmap Root'));
+
         (function()
         {
-	    	var cell = new mxCell('Main Topic', new mxGeometry(0, 0, 80, 20),
-	    		'shape=partialRectangle;top=0;left=0;bottom=1;right=0;points=[[0,1],[1,1]];snapToPoint=1;autosize=1;' +
-	    		'strokeColor=#000000;fillColor=none;align=center;verticalAlign=middle;fontSize=14;fontStyle=1;strokeWidth=2;');
+	    	var cell = new mxCell('Sub Topic', new mxGeometry(0, 0, 80, 20),
+	    		'whiteSpace=wrap;html=1;shape=partialRectangle;top=0;left=0;bottom=1;right=0;points=[[0,1],[1,1]];' +
+	    		'strokeColor=#000000;fillColor=none;align=center;verticalAlign=bottom;routingCenterY=0.5;' +
+	    		'snapToPoint=1;collapsible=0;container=1;recursiveResize=0;strokeWidth=' + sw + ';');
 	    	cell.vertex = true;
-	    	
-			var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;curved=1;' +
-				'startArrow=none;endArrow=none;endFill=0;jettySize=auto;strokeWidth=2;');
-			edge.geometry.setTerminalPoint(new mxPoint(-100, 60), true);
+
+	    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;curved=1;' +
+				'startArrow=none;endArrow=none;segment=10;strokeWidth=' + sw + ';');
+			edge.geometry.setTerminalPoint(new mxPoint(-60, 40), true);
 			edge.geometry.relative = true;
 			edge.edge = true;
-			
+
 			cell.insertEdge(edge, false);
 	
-			content.appendChild(sb.createVertexTemplateFromCells([cell, edge], 80, 20, 'Main Branch'));
+			content.appendChild(sb.createVertexTemplateFromCells([cell, edge], 80, 20, 'Sub Topic'));
         })();
         
         (function()
         {
-	    	var cell = new mxCell('Sub Topic', new mxGeometry(0, 0, 80, 20),
-	    		'shape=partialRectangle;top=0;left=0;bottom=1;right=0;points=[[0,1],[1,1]];snapToPoint=1;autosize=1;' +
-	    		'strokeColor=#000000;fillColor=none;align=center;verticalAlign=middle;fontSize=12;fontStyle=0;');
+	    	var cell = new mxCell('Sub Topic', new mxGeometry(0, 0, 100, 30),
+	    		'whiteSpace=wrap;html=1;rounded=1;arcSize=50;align=center;verticalAlign=middle;collapsible=1;' +
+	    		'collapsible=0;container=1;recursiveResize=0;strokeWidth=' + sw + ';');
 	    	cell.vertex = true;
-	    	
-			var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;curved=1;' +
-				'startArrow=none;endArrow=none;endFill=0;jettySize=auto;');
-			edge.geometry.setTerminalPoint(new mxPoint(-100, 60), true);
+
+	    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;curved=1;' +
+				'startArrow=none;endArrow=none;segment=10;strokeWidth=' + sw + ';');
+			edge.geometry.setTerminalPoint(new mxPoint(-60, 40), true);
 			edge.geometry.relative = true;
 			edge.edge = true;
-			
+
 			cell.insertEdge(edge, false);
-	
-			content.appendChild(sb.createVertexTemplateFromCells([cell, edge], 80, 20, 'Sub Branch'));
+
+			content.appendChild(sb.createVertexTemplateFromCells([cell, edge], 100, 30, 'Sub Topic'));
         })();
     });
     

二進制
war/templates/business/accd.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/business/accd.xml


二進制
war/templates/business/archimate.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/business/archimate.xml


二進制
war/templates/business/bpmn.png


文件差異過大導致無法顯示
+ 12 - 1
war/templates/business/bpmn.xml


二進制
war/templates/business/business_model_1.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/business/business_model_1.xml


二進制
war/templates/business/business_model_2.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/business/business_model_2.xml


二進制
war/templates/business/leanMapping.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/business/leanMapping.xml


二進制
war/templates/business/pert_1.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/business/pert_1.xml


二進制
war/templates/business/pert_2.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/business/pert_2.xml


二進制
war/templates/business/swimlane.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/business/swimlane.xml


二進制
war/templates/business/swot.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/business/swot.xml


二進制
war/templates/business/swot2.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/business/swot2.xml


二進制
war/templates/business/swot3.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/business/swot3.xml


二進制
war/templates/business/swot4.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/business/swot4.xml


二進制
war/templates/business/timeline_1.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/business/timeline_1.xml


二進制
war/templates/business/timeline_2.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/business/timeline_2.xml


二進制
war/templates/charts/bar.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/charts/bar.xml


二進制
war/templates/charts/bar2.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/charts/bar2.xml


二進制
war/templates/charts/city_org.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/charts/city_org.xml


二進制
war/templates/charts/coc.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/charts/coc.xml


二進制
war/templates/charts/org1.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/charts/org1.xml


二進制
war/templates/charts/org2.png


文件差異過大導致無法顯示
+ 0 - 1
war/templates/charts/org2.xml


二進制
war/templates/charts/org_chart_1.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/charts/org_chart_1.xml


二進制
war/templates/charts/org_chart_2.png


文件差異過大導致無法顯示
+ 12 - 0
war/templates/charts/org_chart_2.xml


二進制
war/templates/charts/work_breakdown_structure.png


+ 0 - 0
war/templates/charts/work_breakdown_structure.xml


部分文件因文件數量過多而無法顯示