فهرست منبع

6.7.9 release

Former-commit-id: 46a2eb1d0b2b9a9f69919c694bd2680c5d5a79f4
Gaudenz Alder 8 سال پیش
والد
کامیت
25c7908cf9

+ 6 - 0
ChangeLog

@@ -1,3 +1,9 @@
+12-JUN-2017: 6.7.9
+
+- Adds css, default styles, libraries to Editor.configure
+- Moves persistent settings to EditorUi.init
+- Fixes image export for (var)phi in ASCIIMathML
+
 08-JUN-2017: 6.7.8
 
 - Fixes saving local files in MS Edge

+ 1 - 1
VERSION

@@ -1 +1 @@
-6.7.8
+6.7.9

+ 59 - 28
src/com/mxgraph/io/gliffy/model/GliffyObject.java

@@ -1,63 +1,39 @@
 package com.mxgraph.io.gliffy.model;
 
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import com.mxgraph.io.gliffy.importer.PostDeserializer.PostDeserializable;
 import com.mxgraph.model.mxCell;
 
 /**
  * Class representing Gliffy diagram object
  * 
  */
-public class GliffyObject
+public class GliffyObject implements PostDeserializable
 {
-	public static String SWIMLANE = "com.gliffy.shape.swimlanes.swimlanes_v1.default";
-
-	public static String V_SWIMLANE = "com.gliffy.shape.swimlanes.swimlanes_v1.default.vertical";
-
-	public static String H_SWIMLANE = "com.gliffy.shape.swimlanes.swimlanes_v1.default.horizontal";
-
-	public static String H_SINGLE_SWIMLANE = "com.gliffy.shape.swimlanes.swimlanes_v1.default.horizontal_single_lane_pool";
-
-	public static String V_SINGLE_SWIMLANE = "com.gliffy.shape.swimlanes.swimlanes_v1.default.vertical_single_lane_pool";
-
 	private static Set<String> GRAPHICLESS_SHAPES = new HashSet<String>();
-
 	private static Set<String> GROUP_SHAPES = new HashSet<String>();
-	
 	private static Set<String> MINDMAP_SHAPES = new HashSet<>();
 
 	public float x;
-
 	public float y;
-
 	public int id;
-
 	public float width;
-
 	public float height;
-
 	public float rotation;
-
 	public String uid;
-	
 	public String tid;
-
 	public String order;
-
 	public boolean lockshape;
-
 	public Graphic graphic;
-
 	public List<GliffyObject> children;
-
 	public Constraints constraints;
-	
 	public List<LinkMap> linkMap;
 
 	public mxCell mxObject;// the mxCell this gliffy object got converted into
-
 	public GliffyObject parent = null;
 
 	static
@@ -242,7 +218,7 @@ public class GliffyObject
 
 	public boolean isSwimlane()
 	{
-		return uid != null && uid.startsWith(SWIMLANE);
+		return uid != null && uid.contains("com.gliffy.shape.swimlanes");
 	}
 
 	public boolean isText()
@@ -325,4 +301,59 @@ public class GliffyObject
 	{
 		return uid != null ? uid : tid;
 	}
+
+	@Override
+	public void postDeserialize() {
+		if(isGroup())
+			normalizeChildrenCoordinates();
+	}
+	
+	/**
+	 * Some Gliffy diagrams have groups whose children have negative coordinates.
+	 * This is a problem in draw.io as they get set to 0.
+	 * This method expands the groups left and up and adjusts children's coordinates so that they are never less than zero.
+	 */
+	private void normalizeChildrenCoordinates() {
+		//sorts the list to find the leftmost child and it's X
+		Comparator<GliffyObject> cx = new Comparator<GliffyObject>() {
+			@Override
+			public int compare(GliffyObject o1, GliffyObject o2) {
+				return (int)(o1.x - o2.x);
+			}
+		};
+		 
+		children.sort(cx);
+		float xMin = children.get(0).x;
+		
+		if(xMin < 0) 
+		{
+			width += -xMin; //increase width
+			x += xMin;
+			
+			for(GliffyObject child : children) //increase x 
+				child.x += -xMin;  
+		}
+		
+		//sorts the list to find the leftmost child and it's Y
+		Comparator<GliffyObject> cy = new Comparator<GliffyObject>() {
+			@Override
+			public int compare(GliffyObject o1, GliffyObject o2) {
+				return (int)(o1.y - o2.y);
+			}
+		};
+		 
+		children.sort(cy);
+		float yMin = children.get(0).y;
+		
+		if(yMin < 0) 
+		{
+			height += -yMin; //increase height
+			y += yMin;
+			
+			for(GliffyObject child : children) //increase y 
+				child.y += -yMin;  
+		}
+	}
+	
+	
 }

BIN
war/WEB-INF/lib/mxgraph-core.jar


+ 1 - 1
war/cache.manifest

@@ -1,7 +1,7 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 06/08/2017 03:21 PM
+# 06/12/2017 03:01 PM
 
 app.html
 index.html?offline=1

+ 29 - 0
war/export2.html

@@ -24,6 +24,35 @@
 		// NOTE: SVG Output fixes missing symbols in AsciiMath
 		// but produces larger output with clipping problems
 		Editor.initMath();
+	
+		// Workaround for varphi vs. phi export in MathJax on Phantom
+		// see https://github.com/mathjax/MathJax/issues/353
+		(function()
+		{
+			var authInit = MathJax.AuthorInit;
+	
+			MathJax.AuthorInit = function()
+			{
+				authInit();
+				
+				MathJax.Hub.Register.StartupHook('AsciiMath Jax Config', function()
+				{
+					var symbols = MathJax.InputJax.AsciiMath.AM.symbols;
+					
+					for (var i = 0, m = symbols.length; i < m; i++)
+					{
+				    	if (symbols[i].input === 'phi')
+				    	{
+				    		symbols[i].output = '\u03C6'
+				    	}
+				    	else if (symbols[i].input === 'varphi')
+				    	{
+				    		symbols[i].output = '\u03D5'; i = m
+				    	}
+				  	}
+				});
+			};
+		})();
 
 		function render(data)
 		{

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 152 - 147
war/js/app.min.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 161 - 156
war/js/atlas-viewer.min.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 140 - 135
war/js/atlas.min.js


+ 78 - 175
war/js/diagramly/App.js

@@ -75,9 +75,6 @@ App = function(editor, container, lightbox)
 		EditDataDialog.placeholderHelpLink = 'https://desk.draw.io/support/solutions/articles/16000051979';
 	}
 
-	// Gets recent colors from settings
-	ColorDialog.recentColors = mxSettings.getRecentColors(ColorDialog.recentColors);
-
 	// Handles opening files via drag and drop
 	this.addFileDropHandler([document]);
 	
@@ -99,10 +96,11 @@ App = function(editor, container, lightbox)
 			}
 		}
 		
-		window.Draw.loadPlugin = function(callback)
+		// Installs global callback for plugins
+		window.Draw.loadPlugin = mxUtils.bind(this, function(callback)
 		{
 			callback(this);
-		};
+		});
 	}
 
 	this.load();
@@ -348,81 +346,6 @@ App.getStoredMode = function()
 				mxscript('js/json/json2.min.js');
 			}
 		}
-
-		/**
-		 * Loading plugins.
-		 */
-		if (urlParams['plugins'] != '0' && urlParams['offline'] != '1')
-		{
-			var plugins = mxSettings.getPlugins();
-			var temp = urlParams['p'];
-			
-			if ((temp != null) || (plugins != null && plugins.length > 0))
-			{
-				// Workaround for need to load plugins now but wait for UI instance
-				App.DrawPlugins = [];
-				
-				// Global entry point for plugins is Draw.loadPlugin. This is the only
-				// long-term supported solution for access to the EditorUi instance.
-				window.Draw = new Object();
-				window.Draw.loadPlugin = function(callback)
-				{
-					App.DrawPlugins.push(callback);
-				};
-			}
-			
-			if (temp != null)
-			{
-				// Mapping from key to URL in App.plugins
-				var t = temp.split(';');
-				
-				for (var i = 0; i < t.length; i++)
-				{
-					var url = App.pluginRegistry[t[i]];
-					
-					if (url != null)
-					{
-						mxscript(url);
-					}
-					else if (window.console != null)
-					{
-						console.log('Unknown plugin:', t[i]);
-					}
-				}
-			}
-			
-			if (plugins != null && plugins.length > 0 && urlParams['plugins'] != '0')
-			{
-				// Loading plugins inside the asynchronous block below stops the page from loading so a 
-				// hardcoded message for the warning dialog is used since the resources are loadd below
-				var warning = 'The page has requested to load the following plugin(s):\n \n {1}\n \n Would you like to load these plugin(s) now?\n \n NOTE : Only allow plugins to run if you fully understand the security implications of doing so.\n';
-				var tmp = window.location.protocol + '//' + window.location.host;
-				var local = true;
-				
-				for (var i = 0; i < plugins.length && local; i++)
-				{
-					if (plugins[i].charAt(0) != '/' && plugins[i].substring(0, tmp.length) != tmp)
-					{
-						local = false;
-					}
-				}
-				
-				if (local || mxUtils.confirm(mxResources.replacePlaceholders(warning, [plugins.join('\n')]).replace(/\\n/g, '\n')))
-				{
-					for (var i = 0; i < plugins.length; i++)
-					{
-						try
-						{
-							mxscript(plugins[i]);
-						}
-						catch (e)
-						{
-							// ignore
-						}
-					}
-				}
-			}
-		}
 	}
 })();
 
@@ -553,6 +476,81 @@ App.main = function(callback)
 		{
 			mxscript(document.location.protocol + '//www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22picker%22%2C%22version%22%3A%221%22%2C%22language%22%3A%22' + mxClient.language + '%22%7D%5D%7D');
 		}
+
+		/**
+		 * Loading plugins.
+		 */
+		if (urlParams['plugins'] != '0' && urlParams['offline'] != '1')
+		{
+			var plugins = mxSettings.getPlugins();
+			var temp = urlParams['p'];
+			
+			if ((temp != null) || (plugins != null && plugins.length > 0))
+			{
+				// Workaround for need to load plugins now but wait for UI instance
+				App.DrawPlugins = [];
+				
+				// Global entry point for plugins is Draw.loadPlugin. This is the only
+				// long-term supported solution for access to the EditorUi instance.
+				window.Draw = new Object();
+				window.Draw.loadPlugin = function(callback)
+				{
+					App.DrawPlugins.push(callback);
+				};
+			}
+			
+			if (temp != null)
+			{
+				// Mapping from key to URL in App.plugins
+				var t = temp.split(';');
+				
+				for (var i = 0; i < t.length; i++)
+				{
+					var url = App.pluginRegistry[t[i]];
+					
+					if (url != null)
+					{
+						mxscript(url);
+					}
+					else if (window.console != null)
+					{
+						console.log('Unknown plugin:', t[i]);
+					}
+				}
+			}
+			
+			if (plugins != null && plugins.length > 0 && urlParams['plugins'] != '0')
+			{
+				// Loading plugins inside the asynchronous block below stops the page from loading so a 
+				// hardcoded message for the warning dialog is used since the resources are loadd below
+				var warning = 'The page has requested to load the following plugin(s):\n \n {1}\n \n Would you like to load these plugin(s) now?\n \n NOTE : Only allow plugins to run if you fully understand the security implications of doing so.\n';
+				var tmp = window.location.protocol + '//' + window.location.host;
+				var local = true;
+				
+				for (var i = 0; i < plugins.length && local; i++)
+				{
+					if (plugins[i].charAt(0) != '/' && plugins[i].substring(0, tmp.length) != tmp)
+					{
+						local = false;
+					}
+				}
+				
+				if (local || mxUtils.confirm(mxResources.replacePlaceholders(warning, [plugins.join('\n')]).replace(/\\n/g, '\n')))
+				{
+					for (var i = 0; i < plugins.length; i++)
+					{
+						try
+						{
+							mxscript(plugins[i]);
+						}
+						catch (e)
+						{
+							// ignore
+						}
+					}
+				}
+			}
+		}
 		
 		// Loads gapi for all browsers but IE8 and below if not disabled or if enabled and in embed mode
 		// Special case: Cannot load in asynchronous code below
@@ -706,10 +704,6 @@ App.prototype.fullscreenImage = (!mxClient.IS_SVG) ? IMAGE_PATH + '/fullscreen.p
  */
 App.prototype.timeout = 25000;
 
-// Restores app defaults for UI
-App.prototype.formatEnabled = urlParams['format'] != '0';
-App.prototype.formatWidth = (screen.width < 600) ? 0 : mxSettings.getFormatWidth();
-
 /**
  * Overriden UI settings depending on mode.
  */
@@ -1047,97 +1041,6 @@ App.prototype.init = function()
 		this.menubar.container.insertBefore(this.icon, this.menubar.container.firstChild);
 	}
 
-	if (isLocalStorage || mxClient.IS_CHROMEAPP)
-	{
-		/**
-		 * Persists current edge style.
-		 */
-		this.editor.graph.currentEdgeStyle = mxSettings.getCurrentEdgeStyle();
-		this.editor.graph.currentVertexStyle = mxSettings.getCurrentVertexStyle();
-		
-		// Updates UI to reflect current edge style
-		this.fireEvent(new mxEventObject('styleChanged', 'keys', [], 'values', [], 'cells', []));
-		
-		this.addListener('styleChanged', mxUtils.bind(this, function(sender, evt)
-		{
-			mxSettings.setCurrentEdgeStyle(this.editor.graph.currentEdgeStyle);
-			mxSettings.setCurrentVertexStyle(this.editor.graph.currentVertexStyle);
-			mxSettings.save();
-		}));
-
-		/**
-		 * Persists copy on connect switch.
-		 */
-		this.editor.graph.connectionHandler.setCreateTarget(mxSettings.isCreateTarget());
-		this.fireEvent(new mxEventObject('copyConnectChanged'));
-		
-		this.addListener('copyConnectChanged', mxUtils.bind(this, function(sender, evt)
-		{
-			mxSettings.setCreateTarget(this.editor.graph.connectionHandler.isCreateTarget());
-			mxSettings.save();
-		}));
-		
-		/**
-		 * Persists default page format.
-		 */
-		this.editor.graph.pageFormat = mxSettings.getPageFormat();
-		
-		this.addListener('pageFormatChanged', mxUtils.bind(this, function(sender, evt)
-		{
-			mxSettings.setPageFormat(this.editor.graph.pageFormat);
-			mxSettings.save();
-		}));
-		
-		/**
-		 * Persists default grid color.
-		 */
-		this.editor.graph.view.gridColor = mxSettings.getGridColor();
-		
-		this.addListener('gridColorChanged', mxUtils.bind(this, function(sender, evt)
-		{
-			mxSettings.setGridColor(this.editor.graph.view.gridColor);
-			mxSettings.save();
-		}));
-
-		/**
-		 * Persists autosave switch in Chrome app.
-		 */
-		if (mxClient.IS_CHROMEAPP)
-		{
-			this.editor.addListener('autosaveChanged', mxUtils.bind(this, function(sender, evt)
-			{
-				mxSettings.setAutosave(this.editor.autosave);
-				mxSettings.save();
-			}));
-			
-			this.editor.autosave = mxSettings.getAutosave();
-		}
-		
-		/**
-		 * 
-		 */
-		if (this.sidebar != null)
-		{
-			this.sidebar.showPalette('search', mxSettings.settings.search);
-		}
-		
-		/**
-		 * Shows scratchpad if never shown.
-		 */
-		if (!this.editor.chromeless && this.sidebar != null && (mxSettings.settings.isNew ||
-			parseInt(mxSettings.settings.version || 0) <= 8))
-		{
-			this.toggleScratchpad();
-			mxSettings.save();
-		}
-
-		// Saves app defaults for UI
-		this.addListener('formatWidthChanged', function()
-		{
-			mxSettings.setFormatWidth(this.formatWidth);
-			mxSettings.save();
-		});
-	}
 };
 
 /**

+ 41 - 16
war/js/diagramly/Editor.js

@@ -38,7 +38,12 @@
 	 * Blank 1x1 pixel transparent PNG image.
 	 */
 	Editor.blankImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==';
-	
+
+	/**
+	 * Default value for custom libraries in mxSettings.
+	 */
+	Editor.defaultCustomLibraries = [];
+
 	/**
 	 * Contains the default XML for an empty diagram.
 	 */
@@ -116,6 +121,9 @@
 	/**
 	 * Global configuration of the Editor
 	 * see https://desk.draw.io/solution/articles/16000058316
+	 * 
+	 * For defaultVertexStyle, defaultEdgeStyle and defaultLibraries, this must be called before
+	 * mxSettings.load via global config variable window.mxLoadSettings = false.
 	 */
 	Editor.configure = function(config)
 	{
@@ -126,23 +134,40 @@
 			ColorDialog.prototype.defaultColors = config.defaultColors || ColorDialog.prototype.defaultColors;
 			StyleFormatPanel.prototype.defaultColorSchemes = config.defaultColorSchemes || StyleFormatPanel.prototype.defaultColorSchemes;
 
-			// Overrides themes for default edge and vertex styles
-			var graphLoadStylesheet = Graph.prototype.loadStylesheet;
-			
-			Graph.prototype.loadStylesheet = function()
+			// Custom CSS injected directly into the page
+			if (config.css != null)
 			{
-				graphLoadStylesheet.apply(this, arguments);
+				var s = document.createElement('style');
+				s.setAttribute('type', 'text/css');
+				s.appendChild(document.createTextNode(config.css));
 				
-				if (config.defaultVertexStyle != null)
-				{
-					this.getStylesheet().putDefaultVertexStyle(config.defaultVertexStyle);
-				}
-				
-				if (config.defaultEdgeStyle != null)
-				{
-					this.getStylesheet().putDefaultEdgeStyle(config.defaultEdgeStyle);
-				}
-			};
+				var t = document.getElementsByTagName('script')[0];
+			  	t.parentNode.insertBefore(s, t);
+			}
+			
+			// Overrides default libraries
+			if (config.defaultLibraries != null)
+			{
+				Sidebar.prototype.defaultEntries = config.defaultLibraries;
+			}
+			
+			// Overrides default custom libraries
+			if (config.defaultCustomLibraries != null)
+			{
+				Editor.defaultCustomLibraries = config.defaultCustomLibraries;
+			}
+			
+			// Overrides default vertex style
+			if (config.defaultVertexStyle != null)
+			{
+				Graph.prototype.defaultVertexStyle = config.defaultVertexStyle;
+			}
+
+			// Overrides default edge style
+			if (config.defaultEdgeStyle != null)
+			{
+				Graph.prototype.defaultEdgeStyle = config.defaultEdgeStyle;
+			}
 		}
 	};
 

+ 155 - 28
war/js/diagramly/EditorUi.js

@@ -90,7 +90,12 @@
 	 * Specifies if PDF export with pages is enabled.
 	 */
 	EditorUi.prototype.pdfPageExport = true;
-	
+
+	/**
+	 * Restores app defaults for UI
+	 */
+	EditorUi.prototype.formatEnabled = urlParams['format'] != '0';
+
 	/**
 	 * Capability check for canvas export
 	 */
@@ -4293,34 +4298,44 @@
 			
 			img.onload = mxUtils.bind(this, function()
 			{
-				var canvas = document.createElement('canvas');
-				var w = parseInt(svgRoot.getAttribute('width'));
-				var h = parseInt(svgRoot.getAttribute('height'));
-				scale = (scale != null) ? scale : 1;
-				
-				if (width != null)
-				{
-					scale = (!limitHeight) ? width / w : Math.min(1, Math.min((width * 3) / (h * 4), width / w));
-				}
-				
-				w = Math.ceil(scale * w) + 2 * border;
-				h = Math.ceil(scale * h) + 2 * border;
-				
-				canvas.setAttribute('width', w);
-		   		canvas.setAttribute('height', h);
-		   		var ctx = canvas.getContext('2d');
-		   		
-		   		if (bg != null)
+		   		try
 		   		{
-		   			ctx.beginPath();
-					ctx.rect(0, 0, w, h);
-					ctx.fillStyle = bg;
-					ctx.fill();
+		   			var canvas = document.createElement('canvas');
+					var w = parseInt(svgRoot.getAttribute('width'));
+					var h = parseInt(svgRoot.getAttribute('height'));
+					scale = (scale != null) ? scale : 1;
+					
+					if (width != null)
+					{
+						scale = (!limitHeight) ? width / w : Math.min(1, Math.min((width * 3) / (h * 4), width / w));
+					}
+					
+					w = Math.ceil(scale * w) + 2 * border;
+					h = Math.ceil(scale * h) + 2 * border;
+					
+					canvas.setAttribute('width', w);
+			   		canvas.setAttribute('height', h);
+			   		var ctx = canvas.getContext('2d');
+			   		
+			   		if (bg != null)
+			   		{
+			   			ctx.beginPath();
+						ctx.rect(0, 0, w, h);
+						ctx.fillStyle = bg;
+						ctx.fill();
+			   		}
+
+			   		ctx.scale(scale, scale);
+					ctx.drawImage(img, border / scale, border / scale);
+					callback(canvas);
+		   		}
+		   		catch (e)
+		   		{
+		   			if (error != null)
+					{
+						error(e);
+					}
 		   		}
-				
-		   		ctx.scale(scale, scale);
-				ctx.drawImage(img, border / scale, border / scale);
-				callback(canvas);
 			});
 			
 			img.onerror = function(e)
@@ -5684,6 +5699,12 @@
 	var editorUiInit = EditorUi.prototype.init;
 	EditorUi.prototype.init = function()
 	{
+		// Must be set before UI is created in superclass
+		if (typeof window.mxSettings !== 'undefined')
+		{
+			this.formatWidth = mxSettings.getFormatWidth();
+		}
+		
 		var ui = this;
 		var graph = this.editor.graph;
 		
@@ -6412,8 +6433,114 @@
 		{
 			this.initializeEmbedMode();
 		}
+		
+		if (typeof window.mxSettings !== 'undefined')
+		{
+			this.installSettings();
+		}
 	};
 
+	/**
+	 * Creates the format panel and adds overrides.
+	 */
+	EditorUi.prototype.installSettings = function()
+	{
+		if (isLocalStorage || mxClient.IS_CHROMEAPP)
+		{
+			// Gets recent colors from settings
+			ColorDialog.recentColors = mxSettings.getRecentColors();
+
+			/**
+			 * Persists current edge style.
+			 */
+			this.editor.graph.currentEdgeStyle = mxSettings.getCurrentEdgeStyle();
+			this.editor.graph.currentVertexStyle = mxSettings.getCurrentVertexStyle();
+			
+			// Updates UI to reflect current edge style
+			this.fireEvent(new mxEventObject('styleChanged', 'keys', [], 'values', [], 'cells', []));
+			
+			this.addListener('styleChanged', mxUtils.bind(this, function(sender, evt)
+			{
+				mxSettings.setCurrentEdgeStyle(this.editor.graph.currentEdgeStyle);
+				mxSettings.setCurrentVertexStyle(this.editor.graph.currentVertexStyle);
+				mxSettings.save();
+			}));
+
+			/**
+			 * Persists copy on connect switch.
+			 */
+			this.editor.graph.connectionHandler.setCreateTarget(mxSettings.isCreateTarget());
+			this.fireEvent(new mxEventObject('copyConnectChanged'));
+			
+			this.addListener('copyConnectChanged', mxUtils.bind(this, function(sender, evt)
+			{
+				mxSettings.setCreateTarget(this.editor.graph.connectionHandler.isCreateTarget());
+				mxSettings.save();
+			}));
+			
+			/**
+			 * Persists default page format.
+			 */
+			this.editor.graph.pageFormat = mxSettings.getPageFormat();
+			
+			this.addListener('pageFormatChanged', mxUtils.bind(this, function(sender, evt)
+			{
+				mxSettings.setPageFormat(this.editor.graph.pageFormat);
+				mxSettings.save();
+			}));
+			
+			/**
+			 * Persists default grid color.
+			 */
+			this.editor.graph.view.gridColor = mxSettings.getGridColor();
+			
+			this.addListener('gridColorChanged', mxUtils.bind(this, function(sender, evt)
+			{
+				mxSettings.setGridColor(this.editor.graph.view.gridColor);
+				mxSettings.save();
+			}));
+
+			/**
+			 * Persists autosave switch in Chrome app.
+			 */
+			if (mxClient.IS_CHROMEAPP)
+			{
+				this.editor.addListener('autosaveChanged', mxUtils.bind(this, function(sender, evt)
+				{
+					mxSettings.setAutosave(this.editor.autosave);
+					mxSettings.save();
+				}));
+				
+				this.editor.autosave = mxSettings.getAutosave();
+			}
+			
+			/**
+			 * 
+			 */
+			if (this.sidebar != null)
+			{
+				this.sidebar.showPalette('search', mxSettings.settings.search);
+			}
+			
+			/**
+			 * Shows scratchpad if never shown.
+			 */
+			if (!this.editor.chromeless && this.sidebar != null && (mxSettings.settings.isNew ||
+				parseInt(mxSettings.settings.version || 0) <= 8))
+			{
+				this.toggleScratchpad();
+				mxSettings.save();
+			}
+
+			// Saves app defaults for UI
+			this.addListener('formatWidthChanged', function()
+			{
+				mxSettings.setFormatWidth(this.formatWidth);
+				mxSettings.save();
+			});
+		}
+	};
+	
 	/**
 	 * Creates the format panel and adds overrides.
 	 */
@@ -8543,7 +8670,7 @@
 							html = '<img title="draw.io is up to date." border="0" src="' + IMAGE_PATH + '/checkmark.gif"/>';
 							break;
 						case appCache.DOWNLOADING: // DOWNLOADING == 3
-							html = '<img title="Downloading new version" border="0" src="' + IMAGE_PATH + '/spin.gif"/>';
+							html = '<img title="Downloading new version..." border="0" src="' + IMAGE_PATH + '/spin.gif"/>';
 							break;
 						case appCache.UPDATEREADY:  // UPDATEREADY == 4
 							html = '<img title="' + mxUtils.htmlEntities(mxResources.get('restartForChangeRequired')) +

+ 113 - 90
war/js/diagramly/Settings.js

@@ -3,89 +3,84 @@
  * Copyright (c) 2006-2017, Gaudenz Alder
  */
 /**
- * Utility class for working with persisted application settings
+ * Contains current settings.
  */
 var mxSettings =
 {
+	/**
+	 * Defines current version of settings.
+	 */
+	currentVersion: 14,
+	
+	defaultFormatWidth: (screen.width < 600) ? '0' : '240',
+	
 	// NOTE: Hardcoded in index.html due to timing of JS loading
 	key: '.drawio-config',
 
-	settings:
-	{
-		language: '',
-		libraries: Sidebar.prototype.defaultEntries,
-		customLibraries: [],
-		plugins: [],
-		recentColors: [],
-		formatWidth: '240',
-		currentEdgeStyle: Graph.prototype.defaultEdgeStyle,
-		currentVertexStyle: Graph.prototype.defaultVertexStyle,
-		createTarget: false,
-		pageFormat: mxGraph.prototype.pageFormat,
-		search: true,
-		showStartScreen: true,
-		gridColor: mxGraphView.prototype.gridColor,
-		autosave: true,
-		version: 13,
-		// Only defined and true for new settings which haven't been saved
-		isNew: true
-	},
 	getLanguage: function()
 	{
-		return this.settings.language;
+		return mxSettings.settings.language;
 	},
 	setLanguage: function(lang)
 	{
-		this.settings.language = lang;
+		mxSettings.settings.language = lang;
 	},
 	getUi: function()
 	{
-		return this.settings.ui;
+		return mxSettings.settings.ui;
 	},
 	setUi: function(ui)
 	{
-		this.settings.ui = ui;
+		mxSettings.settings.ui = ui;
 	},
 	getShowStartScreen: function()
 	{
-		return this.settings.showStartScreen;
+		return mxSettings.settings.showStartScreen;
 	},
 	setShowStartScreen: function(showStartScreen)
 	{
-		this.settings.showStartScreen = showStartScreen;
+		mxSettings.settings.showStartScreen = showStartScreen;
 	},
 	getGridColor: function()
 	{
-		return this.settings.gridColor;
+		return mxSettings.settings.gridColor;
 	},
 	setGridColor: function(gridColor)
 	{
-		this.settings.gridColor = gridColor;
+		mxSettings.settings.gridColor = gridColor;
 	},
 	getAutosave: function()
 	{
-		return this.settings.autosave;
+		return mxSettings.settings.autosave;
 	},
 	setAutosave: function(autosave)
 	{
-		this.settings.autosave = autosave;
+		mxSettings.settings.autosave = autosave;
 	},
 	getLibraries: function()
 	{
-		return this.settings.libraries;
+		return mxSettings.settings.libraries;
 	},
 	setLibraries: function(libs)
 	{
-		this.settings.libraries = libs;
+		mxSettings.settings.libraries = libs;
 	},
 	addCustomLibrary: function(id)
 	{
 		// Makes sure to update the latest data from the localStorage
 		mxSettings.load();
 		
-		if (mxUtils.indexOf(this.settings.customLibraries, id) < 0)
+		if (mxUtils.indexOf(mxSettings.settings.customLibraries, id) < 0)
 		{
-			this.settings.customLibraries.push(id);
+			// Makes sure scratchpad is below search in sidebar
+			if (id === 'L.scratchpad')
+			{
+				mxSettings.settings.customLibraries.splice(0, 0, id);
+			}
+			else
+			{
+				mxSettings.settings.customLibraries.push(id);
+			}
 		}
 		
 		mxSettings.save();
@@ -94,68 +89,91 @@ var mxSettings =
 	{
 		// Makes sure to update the latest data from the localStorage
 		mxSettings.load();
-		mxUtils.remove(id, this.settings.customLibraries);
+		mxUtils.remove(id, mxSettings.settings.customLibraries);
 		mxSettings.save();
 	},
 	getCustomLibraries: function()
 	{
-		return this.settings.customLibraries;
+		return mxSettings.settings.customLibraries;
 	},
 	getPlugins: function()
 	{
-		return this.settings.plugins;
+		return mxSettings.settings.plugins;
 	},
 	setPlugins: function(plugins)
 	{
-		this.settings.plugins = plugins;
+		mxSettings.settings.plugins = plugins;
 	},
 	getRecentColors: function()
 	{
-		return this.settings.recentColors;
+		return mxSettings.settings.recentColors;
 	},
 	setRecentColors: function(recentColors)
 	{
-		this.settings.recentColors = recentColors;
+		mxSettings.settings.recentColors = recentColors;
 	},
 	getFormatWidth: function()
 	{
-		return parseInt(this.settings.formatWidth);
+		return parseInt(mxSettings.settings.formatWidth);
 	},
 	setFormatWidth: function(formatWidth)
 	{
-		this.settings.formatWidth = formatWidth;
+		mxSettings.settings.formatWidth = formatWidth;
 	},
 	getCurrentEdgeStyle: function()
 	{
-		return this.settings.currentEdgeStyle;
+		return mxSettings.settings.currentEdgeStyle;
 	},
 	setCurrentEdgeStyle: function(value)
 	{
-		this.settings.currentEdgeStyle = value;
+		mxSettings.settings.currentEdgeStyle = value;
 	},
 	getCurrentVertexStyle: function()
 	{
-		return this.settings.currentVertexStyle;
+		return mxSettings.settings.currentVertexStyle;
 	},
 	setCurrentVertexStyle: function(value)
 	{
-		this.settings.currentVertexStyle = value;
+		mxSettings.settings.currentVertexStyle = value;
 	},
 	isCreateTarget: function()
 	{
-		return this.settings.createTarget;
+		return mxSettings.settings.createTarget;
 	},
 	setCreateTarget: function(value)
 	{
-		this.settings.createTarget = value;
+		mxSettings.settings.createTarget = value;
 	},
 	getPageFormat: function()
 	{
-		return this.settings.pageFormat;
+		return mxSettings.settings.pageFormat;
 	},
 	setPageFormat: function(value)
 	{
-		this.settings.pageFormat = value;
+		mxSettings.settings.pageFormat = value;
+	},
+	init: function()
+	{
+		mxSettings.settings = 
+		{
+			language: '',
+			libraries: Sidebar.prototype.defaultEntries,
+			customLibraries: Editor.defaultCustomLibraries,
+			plugins: [],
+			recentColors: [],
+			formatWidth: mxSettings.defaultFormatWidth,
+			currentEdgeStyle: Graph.prototype.defaultEdgeStyle,
+			currentVertexStyle: Graph.prototype.defaultVertexStyle,
+			createTarget: false,
+			pageFormat: mxGraph.prototype.pageFormat,
+			search: true,
+			showStartScreen: true,
+			gridColor: mxGraphView.prototype.gridColor,
+			autosave: true,
+			version: mxSettings.currentVersion,
+			// Only defined and true for new settings which haven't been saved
+			isNew: true
+		};
 	},
 	save: function()
 	{
@@ -163,9 +181,9 @@ var mxSettings =
 		{
 			try
 			{
-				delete this.settings.isNew;
-				this.settings.version = 12;
-				localStorage.setItem(mxSettings.key, JSON.stringify(this.settings));
+				delete mxSettings.settings.isNew;
+				mxSettings.settings.version = mxSettings.currentVersion;
+				localStorage.setItem(mxSettings.key, JSON.stringify(mxSettings.settings));
 			}
 			catch (e)
 			{
@@ -179,97 +197,102 @@ var mxSettings =
 		{
 			mxSettings.parse(localStorage.getItem(mxSettings.key));
 		}
+
+		if (mxSettings.settings == null)
+		{
+			mxSettings.init();
+		}
 	},
 	parse: function(value)
 	{
 		if (value != null)
 		{
-			this.settings = JSON.parse(value);
+			mxSettings.settings = JSON.parse(value);
 
-			if (this.settings.plugins == null)
+			if (mxSettings.settings.plugins == null)
 			{
-				this.settings.plugins = [];
+				mxSettings.settings.plugins = [];
 			}
 			
-			if (this.settings.recentColors == null)
+			if (mxSettings.settings.recentColors == null)
 			{
-				this.settings.recentColors = [];
+				mxSettings.settings.recentColors = [];
 			}
 			
-			if (this.settings.libraries == null)
+			if (mxSettings.settings.libraries == null)
 			{
-				this.settings.libraries = Sidebar.prototype.defaultEntries;
+				mxSettings.settings.libraries = Sidebar.prototype.defaultEntries;
 			}
 			
-			if (this.settings.customLibraries == null)
+			if (mxSettings.settings.customLibraries == null)
 			{
-				this.settings.customLibraries = [];
+				mxSettings.settings.customLibraries = Editor.defaultCustomLibraries;
 			}
 			
-			if (this.settings.ui == null)
+			if (mxSettings.settings.ui == null)
 			{
-				this.settings.ui = '';
+				mxSettings.settings.ui = '';
 			}
 			
-			if (this.settings.formatWidth == null)
+			if (mxSettings.settings.formatWidth == null)
 			{
-				this.settings.formatWidth = '240';
+				mxSettings.settings.formatWidth = mxSettings.defaultFormatWidth;
 			}
 			
-			if (this.settings.lastAlert != null)
+			if (mxSettings.settings.lastAlert != null)
 			{
-				delete this.settings.lastAlert;
+				delete mxSettings.settings.lastAlert;
 			}
 			
-			if (this.settings.currentEdgeStyle == null)
+			if (mxSettings.settings.currentEdgeStyle == null)
 			{
-				this.settings.currentEdgeStyle = Graph.prototype.defaultEdgeStyle;
+				mxSettings.settings.currentEdgeStyle = Graph.prototype.defaultEdgeStyle;
 			}
-			else if (this.settings.version <= 10)
+			else if (mxSettings.settings.version <= 10)
 			{
 				// Adds new defaults for jetty size and loop routing
-				this.settings.currentEdgeStyle['orthogonalLoop'] = 1;
-				this.settings.currentEdgeStyle['jettySize'] = 'auto';
+				mxSettings.settings.currentEdgeStyle['orthogonalLoop'] = 1;
+				mxSettings.settings.currentEdgeStyle['jettySize'] = 'auto';
 			}
 			
-			if (this.settings.currentVertexStyle == null)
+			if (mxSettings.settings.currentVertexStyle == null)
 			{
-				this.settings.currentVertexStyle = Graph.prototype.defaultEdgeStyle;
+				mxSettings.settings.currentVertexStyle = Graph.prototype.defaultVertexStyle;
 			}
 			
-			if (this.settings.createTarget == null)
+			if (mxSettings.settings.createTarget == null)
 			{
-				this.settings.createTarget = false;
+				mxSettings.settings.createTarget = false;
 			}
 			
-			if (this.settings.pageFormat == null)
+			if (mxSettings.settings.pageFormat == null)
 			{
-				this.settings.pageFormat = mxGraph.prototype.pageFormat;
+				mxSettings.settings.pageFormat = mxGraph.prototype.pageFormat;
 			}
 			
-			if (this.settings.search == null)
+			if (mxSettings.settings.search == null)
 			{
-				this.settings.search = true;
+				mxSettings.settings.search = true;
 			}
 			
-			if (this.settings.showStartScreen == null)
+			if (mxSettings.settings.showStartScreen == null)
 			{
-				this.settings.showStartScreen = true;
+				mxSettings.settings.showStartScreen = true;
 			}		
 			
-			if (this.settings.gridColor == null)
+			if (mxSettings.settings.gridColor == null)
 			{
-				this.settings.gridColor = mxGraphView.prototype.gridColor;
+				mxSettings.settings.gridColor = mxGraphView.prototype.gridColor;
 			}
 			
-			if (this.settings.autosave == null)
+			if (mxSettings.settings.autosave == null)
 			{
-				this.settings.autosave = true;
+				mxSettings.settings.autosave = true;
 			}
 			
-			if (this.settings.scratchpadSeen != null)
+			if (mxSettings.settings.scratchpadSeen != null)
 			{
-				delete this.settings.scratchpadSeen;
+				delete mxSettings.settings.scratchpadSeen;
 			}
 		}
 	},

+ 6 - 5
war/js/diagramly/vsdx/VsdxExport.js

@@ -372,6 +372,7 @@ function VsdxExport(editorUi, resDir)
 		shape.setAttribute("FillStyle", "0");
 		shape.setAttribute("TextStyle", "0");
 		
+		var s = vsdxCanvas.state;
 		var points = state.absolutePoints;
 		var bounds = state.cellBounds;
 		
@@ -384,13 +385,13 @@ function VsdxExport(editorUi, resDir)
 		shape.appendChild(createCellElemScaled("LocPinX", hw, xmlDoc));
 		shape.appendChild(createCellElemScaled("LocPinY", hh, xmlDoc));
 
-		var s = vsdxCanvas.state;
+		vsdxCanvas.newEdge(shape, state, xmlDoc);
 		
 		var calcVsdxPoint = function(p, noHeight) 
 		{
 			var x = p.x, y = p.y;
-			x = (x - bounds.x + s.dx) * s.scale;
-			y = ((noHeight? 0 : bounds.height) - y + bounds.y - s.dy) * s.scale;
+			x = (x * s.scale - bounds.x + s.dx) ;
+			y = ((noHeight? 0 : bounds.height) - y * s.scale + bounds.y - s.dy) ;
 			return {x: x, y: y};
 		};
 
@@ -832,8 +833,8 @@ VsdxExport.prototype.PART_NAME = "PartName";
 VsdxExport.prototype.CONTENT_TYPES_XML = "[Content_Types].xml";
 VsdxExport.prototype.VISIO_PAGES_RELS = "visio/pages/_rels/";
 VsdxExport.prototype.ARROWS_MAP = {
-	"none|1": 0, "none|0": 0, "open|1": 1, "open|0": 1, "block|0": 4, "block|1": 14, "classic|1": 5, "classic|0": 17,
-	"oval|1": 10, "oval|0": 20, "diamond|1": 11, "diamond|0": 22, "blockThin|1": 2, "blockThin|0": 2, "dash|1": 23, "dash|0": 23,
+	"none|1": 0, "none|0": 0, "open|1": 1, "open|0": 1, "block|1": 4, "block|0": 14, "classic|1": 5, "classic|0": 17,
+	"oval|1": 10, "oval|0": 20, "diamond|1": 11, "diamond|0": 22, "blockThin|1": 2, "blockThin|0": 15, "dash|1": 23, "dash|0": 23,
 	"ERone|1": 24, "ERone|0": 24, "ERmandOne|1": 25, "ERmandOne|0": 25, "ERmany|1": 27, "ERmany|0": 27, "ERoneToMany|1": 28, "ERoneToMany|0": 28,
 	"ERzeroToMany|1": 29, "ERzeroToMany|0": 29, "ERzeroToOne|1": 30, "ERzeroToOne|0": 30, "openAsync|1": 9, "openAsync|0": 9
 };

+ 47 - 34
war/js/diagramly/vsdx/mxVsdxCanvas2D.js

@@ -82,6 +82,21 @@ mxVsdxCanvas2D.prototype.newShape = function (shape, cellState, xmlDoc)
 	this.createGeoSec();
 };
 
+
+/**
+ * Function: newEdge
+ *  
+ * Create a new edge.
+ */
+mxVsdxCanvas2D.prototype.newEdge = function (shape, cellState, xmlDoc)
+{
+	this.shape = shape;
+	this.cellState = cellState;
+	this.xmGeo = cellState.cellBounds;
+	var s = this.state;
+	this.xmlDoc = xmlDoc;
+};
+
 /**
  * Function: endShape
  *  
@@ -256,6 +271,9 @@ mxVsdxCanvas2D.prototype.ellipse = function(x, y, w, h)
  */
 mxVsdxCanvas2D.prototype.moveTo = function(x, y)
 {
+	//MoveTo inside a geo usually produce incorrect fill
+	if (this.geoStepIndex > 1)	this.createGeoSec();
+	
 	this.lastMoveToX = x;
 	this.lastMoveToY = y;
 	this.lastX = x;
@@ -578,16 +596,19 @@ mxVsdxCanvas2D.prototype.text = function(x, y, w, h, str, align, valign, wrap, f
 		var s = this.state;
 		var geo = this.xmGeo;
 
-		var strRect = mxUtils.getSizeForString(str, null, null, w > 0? w : null);
+		var fontSize = this.cellState.style["fontSize"];
+		var fontFamily = this.cellState.style["fontFamily"];
+
+		var strRect = mxUtils.getSizeForString(str, fontSize, fontFamily);
 
 		var wShift = 0;
 		var hShift = 0;
 		
 		switch(align) 
 		{
-			case "right": wShift = strRect.width/4; break;
+			case "right": wShift = strRect.width/2; break;
 			//case "center": wShift = 0; break;
-			case "left": wShift = -strRect.width/4; break;
+			case "left": wShift = -strRect.width/2; break;
 		}
 		
 		switch(valign) 
@@ -597,14 +618,12 @@ mxVsdxCanvas2D.prototype.text = function(x, y, w, h, str, align, valign, wrap, f
 			case "bottom": hShift = -strRect.height/2; break;
 		}
 
-		h = h > 0 ? h : strRect.height; 
-		w = w > 0 ? w : strRect.width;
-			
-//		h = h > 0 ? h : geo.height; 
-//		w = w > 0 ? w : geo.width;
 		w = w * s.scale;
 		h = h * s.scale;
-		
+
+		h = Math.max(h, strRect.height); 
+		w = Math.max(w, strRect.width);
+			
 		x = (x - geo.x + s.dx) * s.scale;
 		y = (geo.height - y + geo.y - s.dy) * s.scale;
 
@@ -618,28 +637,29 @@ mxVsdxCanvas2D.prototype.text = function(x, y, w, h, str, align, valign, wrap, f
 
 		if (rotation != 0)
 			this.shape.appendChild(this.createCellElemScaled("TxtAngle", (360 - rotation) * Math.PI / 180));
+		//TODO Currently, we support a single text block formatting. Later, HTML label should be analysed and split into parts
+		var charSect = this.xmlDoc.createElement("Section");
+		charSect.setAttribute('N', 'Character');
+		var charRow = this.xmlDoc.createElement("Row");
+		charRow.setAttribute('IX', 0);
+		
+		var fontColor = this.cellState.style["fontColor"];
+		if (fontColor)	charRow.appendChild(this.createCellElem("Color", fontColor));
+		
+		if (fontSize)	charRow.appendChild(this.createCellElemScaled("Size", fontSize * 0.97)); //the magic number 0.97 is needed such that text do not overflow
+		
+		if (fontFamily)	charRow.appendChild(this.createCellElem("Font", fontFamily));
+		
+		charSect.appendChild(charRow);
+		this.shape.appendChild(charSect);
 		
 		var text = this.xmlDoc.createElement("Text");
+		var cp = this.xmlDoc.createElement("cp");
+		cp.setAttribute('IX', 0);
+		text.appendChild(cp);
 		text.textContent = str;
 		this.shape.appendChild(text);
-//		
-//		var elem = this.createElement('text');
-//		elem.setAttribute('x', this.format(x));
-//		elem.setAttribute('y', this.format(y));
-//		elem.setAttribute('w', this.format(w));
-//		elem.setAttribute('h', this.format(h));
-//		elem.setAttribute('str', str);
-//		
-//		if (align != null)
-//		{
-//			elem.setAttribute('align', align);
-//		}
-//		
-//		if (valign != null)
-//		{
-//			elem.setAttribute('valign', valign);
-//		}
-//		
+		
 //		elem.setAttribute('wrap', (wrap) ? '1' : '0');
 //		
 //		if (format == null)
@@ -659,17 +679,10 @@ mxVsdxCanvas2D.prototype.text = function(x, y, w, h, str, align, valign, wrap, f
 //			elem.setAttribute('clip', (clip) ? '1' : '0');
 //		}
 //		
-//		if (rotation != null)
-//		{
-//			elem.setAttribute('rotation', rotation);
-//		}
-//		
 //		if (dir != null)
 //		{
 //			elem.setAttribute('dir', dir);
 //		}
-//		
-//		this.root.appendChild(elem);
 	}
 };
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7 - 7
war/js/embed-static.min.js


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

@@ -3717,7 +3717,7 @@ if (typeof mxVertexHandler != 'undefined')
 		/**
 		 * Contains the default style for edges.
 		 */
-		Graph.prototype.defaultEdgeStyle = {'edgeStyle': 'orthogonalEdgeStyle', 'rounded': '0', 'html': '1',
+		Graph.prototype.defaultEdgeStyle = {'edgeStyle': 'orthogonalEdgeStyle', 'rounded': '0',
 			'jettySize': 'auto', 'orthogonalLoop': '1'};
 
 		/**

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 7 - 7
war/js/reader.min.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 161 - 156
war/js/viewer.min.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 222 - 222
war/js/vsdx.min.js