Selaa lähdekoodia

15.8.0 release

David Benson 3 vuotta sitten
vanhempi
commit
ff1313abf3

+ 12 - 0
ChangeLog

@@ -1,3 +1,15 @@
+17-NOV-2021: 15.8.0
+
+- Switches to command line deployment script
+- Uses API for inline styles
+- Fixes chrome extension link color
+- Replaces inline CSS styles with DOM API
+- Uses larger handles for line end https://github.com/jgraph/drawio/issues/1683
+- [conf cloud] Allows page ids import to continue when Confluence fails to list all pages
+- Fixes event handling for Chrome on Linux https://github.com/jgraph/drawio/issues/2392
+- Fixes clear waypoints keyboard shortcut https://github.com/jgraph/drawio/issues/2420
+- Fixes handling of PNG data URL with charset
+
 15-NOV-2021: 15.7.4
 
 - Adds titlebar to desktop sketch mode

+ 1 - 1
VERSION

@@ -1 +1 @@
-15.7.4
+15.8.0

+ 2 - 2
etc/build/build.xml

@@ -466,7 +466,7 @@
 		<fileset dir="${war.dir}/WEB-INF/lib" />
 	</path>
 
-	<target name="javac" depends="app" description="Java compilation">
+	<target name="javac" description="Java compilation">
 		<mkdir dir="${javac.dir}"/>
 		<javac includeantruntime="false" srcdir="${src.dir}" excludes="**/EmbedServlet2.java" destdir="${javac.dir}">
 			<classpath refid="javac.class.path" />
@@ -481,7 +481,7 @@
 		<delete file="${basedir}/base-viewer.min.js"/>
 	</target>
 	
-	<target name="war" depends="javac" description="Create the stand-alone war file">
+	<target name="war" depends="app, javac" description="Create the stand-alone war file">
 		<zip destfile="${build.dir}/${war.name}" basedir="${war.dir}" >
 		</zip>
 	</target>

+ 0 - 42
src/main/java/com/mxgraph/online/AppShortcutServlet.java

@@ -1,42 +0,0 @@
-/**
- * $Id: ErrorServlet.java,v 1.6 2014/02/21 12:01:30 gaudenz Exp $
- * Copyright (c) 2014, JGraph Ltd
- */
-package com.mxgraph.online;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-/**
- * Servlet implementation class OpenServlet
- */
-public class AppShortcutServlet extends HttpServlet
-{
-	/**
-	 * 
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * @see HttpServlet#HttpServlet()
-	 */
-	public AppShortcutServlet()
-	{
-		super();
-	}
-
-	/**
-	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
-	 */
-	protected void doGet(HttpServletRequest request,
-			HttpServletResponse response) throws ServletException, IOException
-	{
-		response.setHeader("Location", "index.html?offline=1");
-		response.setStatus(HttpServletResponse.SC_FOUND);
-	}
-
-}

BIN
src/main/webapp/WEB-INF/lib/appengine-api-1.0-sdk-1.9.92.jar


BIN
src/main/webapp/WEB-INF/lib/javax.servlet-api-3.1.0.jar


+ 0 - 10
src/main/webapp/WEB-INF/web.xml

@@ -66,16 +66,6 @@
     <servlet-name>GitHubAuthServlet</servlet-name>
     <url-pattern>/github2</url-pattern>
   </servlet-mapping>
-  <servlet>
-    <description/>
-    <display-name>AppShortcutServlet</display-name>
-    <servlet-name>AppShortcutServlet</servlet-name>
-    <servlet-class>com.mxgraph.online.AppShortcutServlet</servlet-class>
-  </servlet>
-  <servlet-mapping>
-    <servlet-name>AppShortcutServlet</servlet-name>
-    <url-pattern>/app</url-pattern>
-  </servlet-mapping>
   <servlet>
     <display-name>LogServlet</display-name>
     <servlet-name>LogServlet</servlet-name>

BIN
src/main/webapp/images/handle-fixed.png


BIN
src/main/webapp/images/handle-main.png


BIN
src/main/webapp/images/handle-rotate.png


BIN
src/main/webapp/images/handle-secondary.png


BIN
src/main/webapp/images/handle-terminal.png


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1534 - 1530
src/main/webapp/js/app.min.js


+ 2 - 2
src/main/webapp/js/diagramly/App.js

@@ -3175,9 +3175,9 @@ App.prototype.start = function()
 					var doLoadFile = mxUtils.bind(this, function(xml)
 					{
 						// Extracts graph model from PNG
-						if (xml.substring(0, 22) == 'data:image/png;base64,')
+						if (Editor.isPngDataUrl(xml))
 						{
-							xml = this.extractGraphModelFromPng(xml);
+							xml = Editor.extractGraphModelFromPng(xml);
 						}
 						
 						var title = urlParams['title'];

+ 51 - 9
src/main/webapp/js/diagramly/Dialogs.js

@@ -3241,10 +3241,32 @@ var NewDialog = function(editorUi, compact, showName, callback, createOnly, canc
 			
 			if (title != null)
 			{
-				elt.innerHTML = '<table width="100%" height="100%" style="line-height:1.3em;' + (Editor.isDarkMode() ? '' : 'background:rgba(255,255,255,0.85);') +
-					'border:inherit;"><tr><td align="center" valign="middle"><span style="display:inline-block;padding:4px 8px 4px 8px;user-select:none;' +
-					'border-radius:3px;background:rgba(255,255,255,0.85);overflow:hidden;text-overflow:ellipsis;max-width:' + (w - 34) + 'px;">' +
-					mxUtils.htmlEntities(mxResources.get(title, null, title)) + '</span></td></tr></table>';
+				var table = document.createElement('table');
+				table.setAttribute('width', '100%');
+				table.setAttribute('height', '100%');
+				table.style.background = Editor.isDarkMode() ? 'transparent' : 'rgba(255,255,255,0.85)';
+				table.style.lineHeight = '1.3em';
+				table.style.border = 'inherit';
+				var tbody = document.createElement('tbody');
+				var row = document.createElement('tr');
+				var td = document.createElement('td');
+				td.setAttribute('align', 'center');
+				td.setAttribute('valign', 'middle');
+				var span = document.createElement('span');
+				span.style.display = 'inline-block';
+				span.style.padding = '4px 8px 4px 8px';
+				span.style.userSelect = 'none';
+				span.style.borderRadius = '3px';
+				span.style.background = 'rgba(255,255,255,0.85)';
+				span.style.overflow = 'hidden';
+				span.style.textOverflow = 'ellipsis';
+				span.style.maxWidth = (w - 34) + 'px';
+				mxUtils.write(span, mxResources.get(title, null, title));
+				td.appendChild(span);
+				row.appendChild(td);
+				tbody.appendChild(row);
+				table.appendChild(tbody);
+				elt.appendChild(table);
 			}
 			
 			function activate(doCreate)
@@ -3283,11 +3305,31 @@ var NewDialog = function(editorUi, compact, showName, callback, createOnly, canc
 		}
 		else
 		{
-			elt.innerHTML = '<table width="100%" height="100%" style="line-height:1.3em;"><tr>' +
-				'<td align="center" valign="middle"><span style="display:inline-block;padding:4px 8px 4px 8px;user-select:none;' +
-				'border-radius:3px;background:#ffffff;overflow:hidden;text-overflow:ellipsis;max-width:' + (w - 34) + 'px;">' +
-				mxUtils.htmlEntities(mxResources.get(title, null, title)) + '</span></td></tr></table>';
-			
+			var table = document.createElement('table');
+			table.setAttribute('width', '100%');
+			table.setAttribute('height', '100%');
+			table.style.lineHeight = '1.3em';
+			var tbody = document.createElement('tbody');
+			var row = document.createElement('tr');
+			var td = document.createElement('td');
+			td.setAttribute('align', 'center');
+			td.setAttribute('valign', 'middle');
+			var span = document.createElement('span');
+			span.style.display = 'inline-block';
+			span.style.padding = '4px 8px 4px 8px';
+			span.style.userSelect = 'none';
+			span.style.borderRadius = '3px';
+			span.style.background = '#ffffff';
+			span.style.overflow = 'hidden';
+			span.style.textOverflow = 'ellipsis';
+			span.style.maxWidth = (w - 34) + 'px';
+			mxUtils.write(span, mxResources.get(title, null, title));
+			td.appendChild(span);
+			row.appendChild(td);
+			tbody.appendChild(row);
+			table.appendChild(tbody);
+			elt.appendChild(table);
+
 			if (select)
 			{
 				selectElement(elt);

+ 0 - 73
src/main/webapp/js/diagramly/Editor.js

@@ -1690,79 +1690,6 @@
 		
 		return result;
 	};
-	
-	/**
-	 * Extracts the XML from the compressed or non-compressed text chunk.
-	 */
-	Editor.extractGraphModelFromPng = function(data)
-	{
-		var result = null;
-		
-		try
-		{
-			var base64 = data.substring(data.indexOf(',') + 1);
-
-			// Workaround for invalid character error in Safari
-			var binary = (window.atob && !mxClient.IS_SF) ? atob(base64) : Base64.decode(base64, true);
-			
-			EditorUi.parsePng(binary, mxUtils.bind(this, function(pos, type, length)
-			{
-				var value = binary.substring(pos + 8, pos + 8 + length);
-				
-				if (type == 'zTXt')
-				{
-					var idx = value.indexOf(String.fromCharCode(0));
-					
-					if (value.substring(0, idx) == 'mxGraphModel')
-					{
-						// Workaround for Java URL Encoder using + for spaces, which isn't compatible with JS
-						var xmlData = pako.inflateRaw(Graph.stringToArrayBuffer(
-							value.substring(idx + 2)), {to: 'string'}).replace(/\+/g,' ');
-						
-						if (xmlData != null && xmlData.length > 0)
-						{
-							result = xmlData;
-						}
-					}
-				}
-				// Uncompressed section is normally not used
-				else if (type == 'tEXt')
-				{
-					var vals = value.split(String.fromCharCode(0));
-					
-					if (vals.length > 1 && (vals[0] == 'mxGraphModel' ||
-						vals[0] == 'mxfile'))
-					{
-						result = vals[1];
-					}
-				}
-				
-				if (result != null || type == 'IDAT')
-				{
-					// Stops processing the file as our text chunks
-					// are always placed before the data section
-					return true;
-				}
-			}));
-		}
-		catch (e)
-		{
-			// ignores decoding errors
-		}
-		
-		if (result != null && result.charAt(0) == '%')
-		{
-			result = decodeURIComponent(result);
-		}
-		
-		// Workaround for double encoded content
-		if (result != null && result.charAt(0) == '%')
-		{
-			result = decodeURIComponent(result);
-		}
-		
-		return result;
-	};
 
 	/**
 	 * Extracts any parsers errors in the given XML.

+ 25 - 85
src/main/webapp/js/diagramly/EditorUi.js

@@ -279,80 +279,6 @@
 		}
 	};
 
-	/**
-	 * Static method for pasing PNG files.
-	 */
-	EditorUi.parsePng = function(f, fn, error)
-	{
-		var pos = 0;
-		
-		function fread(d, count)
-		{
-			var start = pos;
-			pos += count;
-			
-			return d.substring(start, pos);
-		};
-		
-		// Reads unsigned long 32 bit big endian
-		function _freadint(d)
-		{
-			var bytes = fread(d, 4);
-			
-			return bytes.charCodeAt(3) + (bytes.charCodeAt(2) << 8) +
-				(bytes.charCodeAt(1) << 16) + (bytes.charCodeAt(0) << 24);
-		};
-		
-		// Checks signature
-		if (fread(f,8) != String.fromCharCode(137) + 'PNG' + String.fromCharCode(13, 10, 26, 10))
-		{
-			if (error != null)
-			{
-				error();
-			}
-			
-			return;
-		}
-		
-		// Reads header chunk
-		fread(f,4);
-		
-		if (fread(f,4) != 'IHDR')
-		{
-			if (error != null)
-			{
-				error();
-			}
-			
-			return;
-		}
-		
-		fread(f, 17);
-		
-		do
-		{
-			var n = _freadint(f);
-			var type = fread(f,4);
-			
-			if (fn != null)
-			{
-				if (fn(pos - 8, type, n))
-				{
-					break;
-				}
-			}
-			
-			value = fread(f,n);
-			fread(f,4);
-			
-			if (type == 'IEND')
-			{
-				break;
-			}
-		}
-		while (n);
-	};
-	
 	/**
 	 * Removes any values, styles and geometries from the given XML node.
 	 */
@@ -5386,11 +5312,25 @@
 		
 		function updateLinkColor()
 		{
-			linkButton.innerHTML = '<div style="width:100%;height:100%;box-sizing:border-box;' +
-				((linkColor != null && linkColor != mxConstants.NONE) ?
-				'border:1px solid black;background-color:' + linkColor :
-				'background-position:center center;background-repeat:no-repeat;' +
-				'background-image:url(\'' + Dialog.prototype.closeImage + '\')') + ';"></div>';
+			var div = document.createElement('div');
+			div.style.width = '100%';
+			div.style.height = '100%';
+			div.style.boxSizing = 'border-box';
+
+			if (linkColor != null && linkColor != mxConstants.NONE)
+			{
+				div.style.border = '1px solid black';
+				div.style.backgroundColor = linkColor;
+			}
+			else
+			{
+				div.style.backgroundPosition = 'center center';
+				div.style.backgroundRepeat = 'no-repeat';
+				div.style.backgroundImage = 'url(\'' + Dialog.prototype.closeImage + '\')';
+			}
+
+			linkButton.innerHTML = '';
+			linkButton.appendChild(div);
 		};
 		
 		linkButton = mxUtils.button('', mxUtils.bind(this, function(evt)
@@ -7851,9 +7791,9 @@
 	    		}
 				
 				// Checks for embedded XML in PNG
-				if (text.substring(0, 22) == 'data:image/png;base64,')
+				if (Editor.isPngDataUrl(text))
 				{
-					var xml = this.extractGraphModelFromPng(text);
+					var xml = Editor.extractGraphModelFromPng(text);
 					
 					if (xml != null && xml.length > 0)
 					{
@@ -11008,9 +10948,9 @@
 									if (data != null)
 									{
 										// Checks for embedded XML in PNG
-										if (data.substring(0, 22) == 'data:image/png;base64,')
+										if (Editor.isPngDataUrl(data))
 										{
-											var xml = this.extractGraphModelFromPng(data);
+											var xml = Editor.extractGraphModelFromPng(data);
 											
 											if (xml != null && xml.length > 0)
 											{
@@ -11778,9 +11718,9 @@
 				{
 					try
 					{
-						if (data.substring(0, 22) == 'data:image/png;base64,')
+						if (Editor.isPngDataUrl(data))
 						{
-							data = this.extractGraphModelFromPng(data);
+							data = Editor.extractGraphModelFromPng(data);
 						}
 						else if (data.substring(0, 26) == 'data:image/svg+xml;base64,')
 						{

+ 4 - 1
src/main/webapp/js/diagramly/Menus.js

@@ -2148,13 +2148,16 @@
 			footer.style.width = '100%';
 			footer.style.left = '0px';
 			var link = document.createElement('a');
+			link.setAttribute('href', 'javascript:void(0);');
+			link.setAttribute('target', '_blank');
 			link.style.cursor = 'pointer';
 			mxUtils.write(link, mxResources.get('getNotionChromeExtension'));
 			footer.appendChild(link);
 
-			mxEvent.addListener(link, 'click', function()
+			mxEvent.addListener(link, 'click', function(evt)
 			{
 				editorUi.openLink('https://chrome.google.com/webstore/detail/drawio-for-notion/plhaalebpkihaccllnkdaokdoeaokmle');
+				mxEvent.consume(evt);
 			});
 			
 			editorUi.showPublishLinkDialog(mxResources.get('notion'), null, null, null,

+ 5 - 1
src/main/webapp/js/diagramly/Minimal.js

@@ -136,7 +136,11 @@ EditorUi.initMinimalTheme = function()
 				div.style.cssText = 'position:absolute;left:0;right:0;border-top:1px solid lightgray;' +
 					'height:24px;bottom:31px;text-align:center;cursor:pointer;padding:6px 0 0 0;';
 				div.className = 'geTitle';
-				div.innerHTML = '<span style="font-size:18px;margin-right:5px;">+</span>';
+				var span = document.createElement('span');
+				span.style.fontSize = '18px';
+				span.style.marginRight = '5px';
+				span.innerHTML = '+';
+				div.appendChild(span);
 				mxUtils.write(div, mxResources.get('moreShapes'));
 				container.appendChild(div);
 				

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

@@ -1547,7 +1547,7 @@ Actions.prototype.init = function()
 						var geo = graph.getCellGeometry(cell);
 			
 						// Resets fixed connection point
-						if (mxEvent.isShiftDown(evt))
+						if (trigger != null && mxEvent.isShiftDown(evt))
 						{
 							graph.setCellStyles(mxConstants.STYLE_EXIT_X, null, [cell]);
 							graph.setCellStyles(mxConstants.STYLE_EXIT_Y, null, [cell]);

+ 81 - 0
src/main/webapp/js/grapheditor/Editor.js

@@ -235,6 +235,87 @@ Editor.darkColor = '#2a2a2a';
  */
 Editor.lightColor = '#f0f0f0';
 
+/**
+ * Returns true if the given URL is a PNG data URL.
+ */
+Editor.isPngDataUrl = function(url)
+{
+	return url != null && url.substring(0, 15) == 'data:image/png;'
+};
+
+/**
+ * Extracts the XML from the compressed or non-compressed text chunk.
+ */
+Editor.extractGraphModelFromPng = function(data)
+{
+	var result = null;
+	
+	try
+	{
+		var base64 = data.substring(data.indexOf(';base64,') + 8);
+
+		// Workaround for invalid character error in Safari
+		var binary = (window.atob && !mxClient.IS_SF) ? atob(base64) : Base64.decode(base64, true);
+		
+		EditorUi.parsePng(binary, mxUtils.bind(this, function(pos, type, length)
+		{
+			var value = binary.substring(pos + 8, pos + 8 + length);
+			
+			if (type == 'zTXt')
+			{
+				var idx = value.indexOf(String.fromCharCode(0));
+				
+				if (value.substring(0, idx) == 'mxGraphModel')
+				{
+					// Workaround for Java URL Encoder using + for spaces, which isn't compatible with JS
+					var xmlData = pako.inflateRaw(Graph.stringToArrayBuffer(
+						value.substring(idx + 2)), {to: 'string'}).replace(/\+/g,' ');
+					
+					if (xmlData != null && xmlData.length > 0)
+					{
+						result = xmlData;
+					}
+				}
+			}
+			// Uncompressed section is normally not used
+			else if (type == 'tEXt')
+			{
+				var vals = value.split(String.fromCharCode(0));
+				
+				if (vals.length > 1 && (vals[0] == 'mxGraphModel' ||
+					vals[0] == 'mxfile'))
+				{
+					result = vals[1];
+				}
+			}
+			
+			if (result != null || type == 'IDAT')
+			{
+				// Stops processing the file as our text chunks
+				// are always placed before the data section
+				return true;
+			}
+		}));
+	}
+	catch (e)
+	{
+		// ignores decoding errors
+	}
+	
+	if (result != null && result.charAt(0) == '%')
+	{
+		result = decodeURIComponent(result);
+	}
+	
+	// Workaround for double encoded content
+	if (result != null && result.charAt(0) == '%')
+	{
+		result = decodeURIComponent(result);
+	}
+	
+	return result;
+};
+
 /**
  * Dynamic change of dark mode.
  */

+ 82 - 8
src/main/webapp/js/grapheditor/EditorUi.js

@@ -1036,13 +1036,87 @@ EditorUi = function(editor, container, lightbox)
 	}
 };
 
-// Extends mxEventSource
-mxUtils.extend(EditorUi, mxEventSource);
-
 /**
  * Global config that specifies if the compact UI elements should be used.
  */
-EditorUi.compactUi = true;
+ EditorUi.compactUi = true;
+
+ /**
+  * Static method for pasing PNG files.
+  */
+ EditorUi.parsePng = function(f, fn, error)
+ {
+	 var pos = 0;
+	 
+	 function fread(d, count)
+	 {
+		 var start = pos;
+		 pos += count;
+		 
+		 return d.substring(start, pos);
+	 };
+	 
+	 // Reads unsigned long 32 bit big endian
+	 function _freadint(d)
+	 {
+		 var bytes = fread(d, 4);
+		 
+		 return bytes.charCodeAt(3) + (bytes.charCodeAt(2) << 8) +
+			 (bytes.charCodeAt(1) << 16) + (bytes.charCodeAt(0) << 24);
+	 };
+	 
+	 // Checks signature
+	 if (fread(f,8) != String.fromCharCode(137) + 'PNG' + String.fromCharCode(13, 10, 26, 10))
+	 {
+		 if (error != null)
+		 {
+			 error();
+		 }
+		 
+		 return;
+	 }
+	 
+	 // Reads header chunk
+	 fread(f,4);
+	 
+	 if (fread(f,4) != 'IHDR')
+	 {
+		 if (error != null)
+		 {
+			 error();
+		 }
+		 
+		 return;
+	 }
+	 
+	 fread(f, 17);
+	 
+	 do
+	 {
+		 var n = _freadint(f);
+		 var type = fread(f,4);
+		 
+		 if (fn != null)
+		 {
+			 if (fn(pos - 8, type, n))
+			 {
+				 break;
+			 }
+		 }
+		 
+		 value = fread(f,n);
+		 fread(f,4);
+		 
+		 if (type == 'IEND')
+		 {
+			 break;
+		 }
+	 }
+	 while (n);
+ };
+ 
+// Extends mxEventSource
+mxUtils.extend(EditorUi, mxEventSource);
 
 /**
  * Specifies the size of the split bar.
@@ -4670,9 +4744,9 @@ EditorUi.prototype.parseHtmlData = function(data)
 			
 			if (temp != null)
 			{
-				if (temp.substring(0, 22) == 'data:image/png;base64,')
+				if (Editor.isPngDataUrl(temp))
 				{
-					var xml = this.extractGraphModelFromPng(temp);
+					var xml = Editor.extractGraphModelFromPng(temp);
 					
 					if (xml != null && xml.length > 0)
 					{
@@ -4696,9 +4770,9 @@ EditorUi.prototype.parseHtmlData = function(data)
 				
 				if (temp != null && img.parentNode == elt && elt.children.length == 1)
 				{
-					if (temp.substring(0, 22) == 'data:image/png;base64,')
+					if (Editor.isPngDataUrl(temp))
 					{
-						var xml = this.extractGraphModelFromPng(temp);
+						var xml = Editor.extractGraphModelFromPng(temp);
 						
 						if (xml != null && xml.length > 0)
 						{

+ 4 - 2
src/main/webapp/js/grapheditor/Format.js

@@ -2117,10 +2117,12 @@ ArrangePanel.prototype.addGroupOps = function(div)
 		
 		btn = mxUtils.button(mxResources.get('clearWaypoints'), mxUtils.bind(this, function(evt)
 		{
-			this.editorUi.actions.get('clearWaypoints').funct(evt);
+			this.editorUi.actions.get('clearWaypoints').funct(evt, evt);
 		}));
 		
-		btn.setAttribute('title', mxResources.get('clearWaypoints') + ' (' + this.editorUi.actions.get('clearWaypoints').shortcut + ')');
+		btn.setAttribute('title', mxResources.get('clearWaypoints') +
+			' (' + this.editorUi.actions.get('clearWaypoints').shortcut + ')' +
+			' Shift+Click to Clear Anchor Points');
 		btn.style.width = '210px';
 		btn.style.marginBottom = '2px';
 		div.appendChild(btn);

+ 31 - 23
src/main/webapp/js/grapheditor/Graph.js

@@ -12403,34 +12403,41 @@ if (typeof mxVertexHandler != 'undefined')
 		/**
 		 * Defines the handles for the UI. Uses data-URIs to speed-up loading time where supported.
 		 */
-		// TODO: Increase handle padding
-		HoverIcons.prototype.mainHandle = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/handle-main.png', 17, 17) :
-			Graph.createSvgImage(18, 18, '<circle cx="9" cy="9" r="5" stroke="#fff" fill="' + HoverIcons.prototype.arrowFill + '" stroke-width="1"/>');
-		HoverIcons.prototype.secondaryHandle = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/handle-secondary.png', 17, 17) :
-			Graph.createSvgImage(16, 16, '<path d="m 8 3 L 13 8 L 8 13 L 3 8 z" stroke="#fff" fill="#fca000"/>');
-		HoverIcons.prototype.fixedHandle = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/handle-fixed.png', 17, 17) :
-			Graph.createSvgImage(22, 22, '<circle cx="11" cy="11" r="6" stroke="#fff" fill="#01bd22" stroke-width="1"/><path d="m 8 8 L 14 14M 8 14 L 14 8" stroke="#fff"/>');
-		HoverIcons.prototype.terminalHandle = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/handle-terminal.png', 17, 17) :
-			Graph.createSvgImage(22, 22, '<circle cx="11" cy="11" r="6" stroke="#fff" fill="' + HoverIcons.prototype.arrowFill + '" stroke-width="1"/><circle cx="11" cy="11" r="3" stroke="#fff" fill="transparent"/>');
-		HoverIcons.prototype.rotationHandle = (!mxClient.IS_SVG) ? new mxImage(IMAGE_PATH + '/handle-rotate.png', 16, 16) :
-			Graph.createSvgImage(16, 16, '<path stroke="' + HoverIcons.prototype.arrowFill +
-				'" fill="' + HoverIcons.prototype.arrowFill +
+		// TODO: Remove non-svg cases
+		HoverIcons.prototype.mainHandle = Graph.createSvgImage(18, 18, '<circle cx="9" cy="9" r="5" stroke="#fff" fill="' + HoverIcons.prototype.arrowFill + '"/>');
+		HoverIcons.prototype.endMainHandle = Graph.createSvgImage(18, 18, '<circle cx="9" cy="9" r="6" stroke="#fff" fill="' + HoverIcons.prototype.arrowFill + '"/>');
+		HoverIcons.prototype.secondaryHandle = Graph.createSvgImage(16, 16, '<path d="m 8 3 L 13 8 L 8 13 L 3 8 z" stroke="#fff" fill="#fca000"/>');
+		HoverIcons.prototype.fixedHandle = Graph.createSvgImage(22, 22,
+			'<circle cx="11" cy="11" r="6" stroke="#fff" fill="#01bd22"/>' +
+			'<path d="m 8 8 L 14 14M 8 14 L 14 8" stroke="#fff"/>');
+		HoverIcons.prototype.endFixedHandle = Graph.createSvgImage(22, 22,
+			'<circle cx="11" cy="11" r="7" stroke="#fff" fill="#01bd22"/>' +
+			'<path d="m 8 8 L 14 14M 8 14 L 14 8" stroke="#fff"/>');
+		HoverIcons.prototype.terminalHandle = Graph.createSvgImage(22, 22,
+			'<circle cx="11" cy="11" r="6" stroke="#fff" fill="' + HoverIcons.prototype.arrowFill +
+			'"/><circle cx="11" cy="11" r="3" stroke="#fff" fill="transparent"/>');
+		HoverIcons.prototype.endTerminalHandle = Graph.createSvgImage(22, 22,
+			'<circle cx="11" cy="11" r="7" stroke="#fff" fill="' + HoverIcons.prototype.arrowFill +
+			'"/><circle cx="11" cy="11" r="3" stroke="#fff" fill="transparent"/>');
+		HoverIcons.prototype.rotationHandle = Graph.createSvgImage(16, 16,
+			'<path stroke="' + HoverIcons.prototype.arrowFill + '" fill="' + HoverIcons.prototype.arrowFill +
 				'" d="M15.55 5.55L11 1v3.07C7.06 4.56 4 7.92 4 12s3.05 7.44 7 7.93v-2.02c-2.84-.48-5-2.94-5-5.91s2.16-5.43 5-5.91V10l4.55-4.45zM19.93 11c-.17-1.39-.72-2.73-1.62-3.89l-1.42 1.42c.54.75.88 1.6 1.02 2.47h2.02zM13 17.9v2.02c1.39-.17 2.74-.71 3.9-1.61l-1.44-1.44c-.75.54-1.59.89-2.46 1.03zm3.89-2.42l1.42 1.41c.9-1.16 1.45-2.5 1.62-3.89h-2.02c-.14.87-.48 1.72-1.02 2.48z"/>',
 				24, 24);
-		
-		if (mxClient.IS_SVG)
-		{
-			mxConstraintHandler.prototype.pointImage = Graph.createSvgImage(5, 5,
-				'<path d="m 0 0 L 5 5 M 0 5 L 5 0" stroke-width="2" style="stroke-opacity:0.4" stroke="#ffffff"/>' +
-				'<path d="m 0 0 L 5 5 M 0 5 L 5 0" stroke="' + HoverIcons.prototype.arrowFill + '"/>');
-		}
-		
+	
+		mxConstraintHandler.prototype.pointImage = Graph.createSvgImage(5, 5,
+			'<path d="m 0 0 L 5 5 M 0 5 L 5 0" stroke-width="2" style="stroke-opacity:0.4" stroke="#ffffff"/>' +
+			'<path d="m 0 0 L 5 5 M 0 5 L 5 0" stroke="' + HoverIcons.prototype.arrowFill + '"/>');
+
 		mxVertexHandler.TABLE_HANDLE_COLOR = '#fca000';
 		mxVertexHandler.prototype.handleImage = HoverIcons.prototype.mainHandle;
 		mxVertexHandler.prototype.secondaryHandleImage = HoverIcons.prototype.secondaryHandle;
 		mxEdgeHandler.prototype.handleImage = HoverIcons.prototype.mainHandle;
+		mxEdgeHandler.prototype.endHandleImage = HoverIcons.prototype.endMainHandle;
 		mxEdgeHandler.prototype.terminalHandleImage = HoverIcons.prototype.terminalHandle;
+		mxEdgeHandler.prototype.endTerminalHandleImage = HoverIcons.prototype.endTerminalHandle;
 		mxEdgeHandler.prototype.fixedHandleImage = HoverIcons.prototype.fixedHandle;
+
+		mxEdgeHandler.prototype.endFixedHandleImage = HoverIcons.prototype.endFixedHandle;
 		mxEdgeHandler.prototype.labelHandleImage = HoverIcons.prototype.secondaryHandle;
 		mxOutline.prototype.sizerImage = HoverIcons.prototype.mainHandle;
 		
@@ -12811,7 +12818,7 @@ if (typeof mxVertexHandler != 'undefined')
 		};
 		
 		// Shows secondary handle for fixed connection points
-		mxEdgeHandler.prototype.createHandleShape = function(index, virtual)
+		mxEdgeHandler.prototype.createHandleShape = function(index, virtual, target)
 		{
 			var source = index != null && index == 0;
 			var terminalState = this.state.getVisibleTerminalState(source);
@@ -12819,8 +12826,9 @@ if (typeof mxVertexHandler != 'undefined')
 				(this.constructor == mxElbowEdgeHandler && index == 2))) ?
 				this.graph.getConnectionConstraint(this.state, terminalState, source) : null;
 			var pt = (c != null) ? this.graph.getConnectionPoint(this.state.getVisibleTerminalState(source), c) : null;
-			var img = (pt != null) ? this.fixedHandleImage : ((c != null && terminalState != null) ?
-				this.terminalHandleImage : this.handleImage);
+			var img = (pt != null) ? (!target ? this.fixedHandleImage : this.endFixedHandleImage) :
+				((c != null && terminalState != null) ? (!target ? this.terminalHandleImage : this.endTerminalHandleImage) :
+					(!target ? this.handleImage : this.endHandleImage));
 			
 			if (img != null)
 			{

+ 4 - 2
src/main/webapp/js/grapheditor/Shapes.js

@@ -292,13 +292,15 @@
 						for (var j = 0; j < rowData.length; j++)
 						{
 							var data = rowData[j];
-							var colspan = (i == 1) ? parseInt(data.styles[i - 1]['colspan'] || 1) :
+							var colspan = (i == 1) ? (data.styles[i - 1] != null ?
+								parseInt(data.styles[i - 1]['colspan'] || 1) : 1) :
 								rowData[j].colspans[i - 1];
 							data.colspans[i] = colspan - 1;
 
 							if (data.colspans[i] < 1)
 							{
-								data.colspans[i] = parseInt(data.styles[i]['colspan'] || 1);
+								data.colspans[i] = data.styles[i] != null ?
+									parseInt(data.styles[i]['colspan'] || 1 ) : 1;
 								th = data.y;
 							}
 							else

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1308 - 1306
src/main/webapp/js/viewer-static.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1308 - 1306
src/main/webapp/js/viewer.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 19 - 19
src/main/webapp/mxgraph/mxClient.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
src/main/webapp/service-worker.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1 - 1
src/main/webapp/service-worker.js.map