Selaa lähdekoodia

20.2.8 release

David Benson 3 vuotta sitten
vanhempi
commit
59887e45b3
40 muutettua tiedostoa jossa 5680 lisäystä ja 5638 poistoa
  1. 18 0
      ChangeLog
  2. 1 1
      VERSION
  3. BIN
      etc/build/Xml2Js.class
  4. 5 88
      etc/build/Xml2Js.java
  5. 12 8
      src/main/java/com/mxgraph/online/ProxyServlet.java
  6. 30 5
      src/main/java/com/mxgraph/online/Utils.java
  7. 1551 1553
      src/main/webapp/js/app.min.js
  8. 9 59
      src/main/webapp/js/diagramly/App.js
  9. 27 15
      src/main/webapp/js/diagramly/EditorUi.js
  10. 49 40
      src/main/webapp/js/diagramly/GraphViewer.js
  11. 2 2
      src/main/webapp/js/diagramly/Menus.js
  12. 45 64
      src/main/webapp/js/diagramly/Minimal.js
  13. 1 1
      src/main/webapp/js/diagramly/sidebar/Sidebar-ArchiMate.js
  14. 1 1
      src/main/webapp/js/diagramly/sidebar/Sidebar-ArchiMate3.js
  15. 1 1
      src/main/webapp/js/diagramly/sidebar/Sidebar-Arrows2.js
  16. 10 0
      src/main/webapp/js/diagramly/sidebar/Sidebar-BPMN.js
  17. 1 1
      src/main/webapp/js/diagramly/sidebar/Sidebar-C4.js
  18. 3 3
      src/main/webapp/js/diagramly/sidebar/Sidebar-Electrical.js
  19. 8 8
      src/main/webapp/js/diagramly/sidebar/Sidebar-Floorplan.js
  20. 1 1
      src/main/webapp/js/diagramly/sidebar/Sidebar-FluidPower.js
  21. 5 5
      src/main/webapp/js/diagramly/sidebar/Sidebar-Infographic.js
  22. 1 1
      src/main/webapp/js/diagramly/sidebar/Sidebar-LeanMapping.js
  23. 2 4
      src/main/webapp/js/diagramly/sidebar/Sidebar-Rack.js
  24. 31 30
      src/main/webapp/js/diagramly/sidebar/Sidebar-Sysml.js
  25. 6 6
      src/main/webapp/js/diagramly/sidebar/Sidebar-UML25.js
  26. 45 41
      src/main/webapp/js/grapheditor/EditorUi.js
  27. 2 2
      src/main/webapp/js/grapheditor/Sidebar.js
  28. 1184 1181
      src/main/webapp/js/integrate.min.js
  29. 13 7
      src/main/webapp/js/shapes-14-6-5.min.js
  30. 196 197
      src/main/webapp/js/stencils.min.js
  31. 1110 1104
      src/main/webapp/js/viewer-static.min.js
  32. 1097 1097
      src/main/webapp/js/viewer.min.js
  33. 4 4
      src/main/webapp/mxgraph/mxClient.js
  34. 0 38
      src/main/webapp/package.json
  35. 1 1
      src/main/webapp/service-worker.js
  36. 1 1
      src/main/webapp/service-worker.js.map
  37. 123 0
      src/main/webapp/shapes/mxC4.js
  38. 31 15
      src/main/webapp/shapes/rack/mxRack.js
  39. 34 34
      src/main/webapp/stencils/electrical/electro-mechanical.xml
  40. 19 19
      src/main/webapp/stencils/mockup/misc.xml

+ 18 - 0
ChangeLog

@@ -1,3 +1,21 @@
+01-SEP-2022: 20.2.8
+
+- Fixes importing plain SVG images by drag and drop [DS-902]
+- Adds createToolbarButton helper function [3007]
+- Sets current stroke color and width independently [DS-903]
+- Fixes layout for CSV import in lightbox mode [DS-904]
+- Fixes repeated set default style not working [DS-905]
+- [conf cloud] Catches errors in diagram text extraction to not break re-indexing process [DS-908]
+- Applies fillColor=strokeColor for shapes where appropriate [DS-903]
+- Makes format window closable in min ui [DS-906]
+- Fixes file pattern for workbox [2977]
+- Smaller stencils.min, uses built-in base64 encoder [DS-907]
+- Allows for close icon in minimized format window [DS-906]
+- Adds support for stroke and fill color in stencils [DS-903]
+- Restricts proxy servlet, java disabled by default, all errors are 500 (not distinguishable), allow ports only by config [CSP-633]
+- Conf Cloud: Fixed error of renaming/changing view settings not published if no modification done to the diagram [DID-6141]
+- Adds custom starting unit number to Rack Cabinet shape [2967]
+
 22-AUG-2022: 20.2.7
 
 - Reduces cursor update frequency to reduce DO request count [DS-899]

+ 1 - 1
VERSION

@@ -1 +1 @@
-20.2.7
+20.2.8

BIN
etc/build/Xml2Js.class


+ 5 - 88
etc/build/Xml2Js.java

@@ -15,6 +15,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 import java.util.zip.Deflater;
+import java.util.Base64;
 
 public class Xml2Js
 {
@@ -73,12 +74,8 @@ public class Xml2Js
 	 */
 	public static String processFile(File file) throws IOException
 	{
-		System.out.println("Processing " + file.getCanonicalPath() + "...");
-
-		Deflater deflater = new Deflater(Deflater.DEFAULT_COMPRESSION, true);
-		byte[] inBytes = encodeURIComponent(
-				readInputStream(new FileInputStream(file)),
-				CHARSET_FOR_URL_ENCODING).getBytes("UTF-8");
+		Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, true);
+		byte[] inBytes = readInputStream(new FileInputStream(file)).getBytes("UTF-8");
 		deflater.setInput(inBytes);
 
 		ByteArrayOutputStream outputStream = new ByteArrayOutputStream(
@@ -94,7 +91,7 @@ public class Xml2Js
 
 		outputStream.close();
 
-		return encodeToString(outputStream.toByteArray(), false);
+		return Base64.getEncoder().encodeToString(outputStream.toByteArray());
 	}
 
 	/**
@@ -160,85 +157,6 @@ public class Xml2Js
 		IA['='] = 0;
 	}
 
-	// ****************************************************************************************
-	// *  char[] version
-	// ****************************************************************************************
-
-	/** Encodes a raw byte array into a BASE64 <code>char[]</code> representation i accordance with RFC 2045.
-	 * @param sArr The bytes to convert. If <code>null</code> or length 0 an empty array will be returned.
-	 * @param lineSep Optional "\r\n" after 76 characters, unless end of file.<br>
-	 * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a
-	 * little faster.
-	 * @return A BASE64 encoded array. Never <code>null</code>.
-	 */
-	public final static char[] encodeToChar(byte[] sArr, boolean lineSep)
-	{
-		// Check special case
-		int sLen = sArr != null ? sArr.length : 0;
-		if (sLen == 0)
-			return new char[0];
-
-		int eLen = (sLen / 3) * 3; // Length of even 24-bits.
-		int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count
-		int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array
-		char[] dArr = new char[dLen];
-
-		// Encode even 24-bits
-		for (int s = 0, d = 0, cc = 0; s < eLen;)
-		{
-			// Copy next three bytes into lower 24 bits of int, paying attension to sign.
-			int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8
-					| (sArr[s++] & 0xff);
-
-			// Encode the int into four chars
-			dArr[d++] = CA[(i >>> 18) & 0x3f];
-			dArr[d++] = CA[(i >>> 12) & 0x3f];
-			dArr[d++] = CA[(i >>> 6) & 0x3f];
-			dArr[d++] = CA[i & 0x3f];
-
-			// Add optional line separator
-			if (lineSep && ++cc == 19 && d < dLen - 2)
-			{
-				dArr[d++] = '\r';
-				dArr[d++] = '\n';
-				cc = 0;
-			}
-		}
-
-		// Pad and encode last bits if source isn't even 24 bits.
-		int left = sLen - eLen; // 0 - 2.
-		if (left > 0)
-		{
-			// Prepare the int
-			int i = ((sArr[eLen] & 0xff) << 10)
-					| (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0);
-
-			// Set last four chars
-			dArr[dLen - 4] = CA[i >> 12];
-			dArr[dLen - 3] = CA[(i >>> 6) & 0x3f];
-			dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : '=';
-			dArr[dLen - 1] = '=';
-		}
-		return dArr;
-	}
-
-	// ****************************************************************************************
-	// * String version
-	// ****************************************************************************************
-
-	/** Encodes a raw byte array into a BASE64 <code>String</code> representation i accordance with RFC 2045.
-	 * @param sArr The bytes to convert. If <code>null</code> or length 0 an empty array will be returned.
-	 * @param lineSep Optional "\r\n" after 76 characters, unless end of file.<br>
-	 * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a
-	 * little faster.
-	 * @return A BASE64 encoded array. Never <code>null</code>.
-	 */
-	public final static String encodeToString(byte[] sArr, boolean lineSep)
-	{
-		// Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower.
-		return new String(encodeToChar(sArr, lineSep));
-	}
-
 	/**
 	 * Main
 	 */
@@ -275,10 +193,9 @@ public class Xml2Js
 				result.append("  var t = f[filename.substring(STENCIL_PATH.length + 1)];\n");
 				result.append("  var s = null;\n");
 				result.append("  if (t != null) {\n");
-				result.append("    t = pako.inflateRaw(Uint8Array.from(atob(t), function (c) {\n");
+				result.append("    s = pako.inflateRaw(Uint8Array.from(atob(t), function (c) {\n");
 				result.append("      return c.charCodeAt(0);\n");
 				result.append("    }), {to: 'string'});\n");
-				result.append("    s = decodeURIComponent(t);\n");
 				result.append("  }\n");
 				result.append("  if (fn != null && s != null) {\n");
 				result.append(

+ 12 - 8
src/main/java/com/mxgraph/online/ProxyServlet.java

@@ -64,7 +64,11 @@ public class ProxyServlet extends HttpServlet
 	{
 		String urlParam = request.getParameter("url");
 
-		if (Utils.sanitizeUrl(urlParam))
+		if (!"1".equals(System.getenv("ENABLE_DRAWIO_PROXY")))
+		{
+			response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+		}
+		else if (Utils.sanitizeUrl(urlParam))
 		{
 			// build the UML source from the compressed request parameter
 			String ref = request.getHeader("referer");
@@ -152,12 +156,12 @@ public class ProxyServlet extends HttpServlet
 					}
 					else
 					{
-						response.setStatus(HttpURLConnection.HTTP_PRECON_FAILED);
+						response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 					}
 				}
 				else
 				{
-					response.setStatus(HttpURLConnection.HTTP_UNSUPPORTED_TYPE);
+					response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 				}
 
 				out.flush();
@@ -169,16 +173,16 @@ public class ProxyServlet extends HttpServlet
 			}
 			catch (DeadlineExceededException e)
 			{
-				response.setStatus(HttpServletResponse.SC_REQUEST_TIMEOUT);
+				response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 			}
 			catch (UnknownHostException | FileNotFoundException e)
 			{
 				// do not log 404 and DNS errors
-				response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+				response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 			}
 			catch (UnsupportedContentException e)
 			{
-				response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+				response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 				log.log(Level.SEVERE, "proxy request with invalid content: url="
 						+ ((urlParam != null) ? urlParam : "[null]")
 						+ ", referer=" + ((ref != null) ? ref : "[null]")
@@ -186,7 +190,7 @@ public class ProxyServlet extends HttpServlet
 			}
 			catch (SizeLimitExceededException e)
 			{
-				response.setStatus(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE);
+				response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 
 				throw e;
 			}
@@ -205,7 +209,7 @@ public class ProxyServlet extends HttpServlet
 		}
 		else
 		{
-			response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 			log.log(Level.SEVERE,
 					"proxy request with invalid URL parameter: url="
 							+ ((urlParam != null) ? urlParam : "[null]"));

+ 30 - 5
src/main/java/com/mxgraph/online/Utils.java

@@ -18,13 +18,11 @@ import java.net.URL;
 import java.net.URLEncoder;
 import java.net.UnknownHostException;
 import java.security.SecureRandom;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.zip.Deflater;
 import java.util.zip.Inflater;
 import java.util.zip.InflaterInputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.UnknownHostException;
-import java.net.InetAddress;
 
 /**
  * 
@@ -56,6 +54,32 @@ public class Utils
 	 */
 	public static final String TOKEN_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_";
 
+	private static Set<Integer> allowedPorts = new HashSet<>();
+	
+	static {
+		// -1 is for no port urls (ports 80, 443)
+		allowedPorts.add(-1);
+
+		String allowedPortsStr = System.getenv("DRAWIO_PROXY_ALLOWED_PORTS");
+		
+		if (allowedPortsStr != null) 
+		{
+			String[] ports = allowedPortsStr.split(",");
+			
+			for (String port : ports) 
+			{
+				try 
+				{
+					allowedPorts.add(Integer.parseInt(port));
+				} 
+				catch (NumberFormatException e) 
+				{
+					System.out.println("Invalid DRAWIO_PROXY_ALLOWED_PORTS port: " + port);
+				}
+			}
+		}
+	}
+
 	/**
 	 * Returns a random string of the given length.
 	 */
@@ -553,11 +577,12 @@ public class Utils
 				InetAddress address = InetAddress.getByName(host);
 				String hostAddress = address.getHostAddress();
 				host = host.toLowerCase();
-
+				
 				return (protocol.equals("http") || protocol.equals("https"))
 						&& !address.isAnyLocalAddress()
 						&& !address.isLoopbackAddress()
 						&& !address.isLinkLocalAddress()
+						&& allowedPorts.contains(parsedUrl.getPort())
 						&& !host.endsWith(".internal") // Redundant
 						&& !host.endsWith(".local") // Redundant
 						&& !host.contains("localhost") // Redundant

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


+ 9 - 59
src/main/webapp/js/diagramly/App.js

@@ -7596,60 +7596,6 @@ App.prototype.updateUserElement = function()
 						}), mxResources.get('trello'));
 					}
 					
-					if (!connected)
-					{
-						var div = document.createElement('div');
-						div.style.textAlign = 'center';
-						div.style.padding = '10px';
-						div.innerHTML = mxResources.get('notConnected');
-						
-						this.userPanel.appendChild(div);
-					}
-					
-					var div = document.createElement('div');
-					div.style.textAlign = 'center';
-					div.style.padding = '10px';
-					div.style.background = Editor.isDarkMode() ? '' : 'whiteSmoke';
-					div.style.borderTop = '1px solid #e0e0e0';
-					div.style.whiteSpace = 'nowrap';
-					
-					if (urlParams['sketch'] == '1')
-					{
-						var btn = mxUtils.button(mxResources.get('share'), mxUtils.bind(this, function()
-						{
-							this.actions.get('share').funct();
-						}));
-						btn.className = 'geBtn';
-						div.appendChild(btn);
-				
-						if (this.commentsSupported())
-						{
-							btn = mxUtils.button(mxResources.get('comments'), mxUtils.bind(this, function()
-							{
-								this.actions.get('comments').funct();
-							}));
-							btn.className = 'geBtn';
-							div.appendChild(btn);
-							this.userPanel.appendChild(div);
-						}
-
-						this.userPanel.appendChild(div);
-					}
-					else
-					{
-						var btn = mxUtils.button(mxResources.get('close'), mxUtils.bind(this, function()
-						{
-							if (!mxEvent.isConsumed(evt) && this.userPanel != null && this.userPanel.parentNode != null)
-							{
-								this.userPanel.parentNode.removeChild(this.userPanel);
-							}
-						}));
-
-						btn.className = 'geBtn';
-						div.appendChild(btn);
-						this.userPanel.appendChild(div);
-					}
-
 					if (uiTheme == 'min')
 					{
 						var file = this.getCurrentFile();
@@ -7657,15 +7603,19 @@ App.prototype.updateUserElement = function()
 						if (file != null && file.isRealtimeEnabled() && file.isRealtimeSupported())
 						{
 							div = div.cloneNode(false);
+							div.style.textAlign = 'center';
+							div.style.padding = '10px';
 							div.style.fontSize = '9pt';
 							var err = file.getRealtimeError();
 							var state = file.getRealtimeState();
 
-							mxUtils.write(div, mxResources.get('realtimeCollaboration') + ': ' +
-								(state == 1 ? mxResources.get('online') :
-									((err != null && err.message != null) ?
-									err.message : mxResources.get('disconnected'))));
-							this.userPanel.appendChild(div);
+							if (state != 1)
+							{
+								mxUtils.write(div, mxResources.get('realtimeCollaboration') + ': ' +
+										((err != null && err.message != null) ?
+										err.message : mxResources.get('disconnected')));
+								this.userPanel.appendChild(div);
+							}
 						}
 					}
 

+ 27 - 15
src/main/webapp/js/diagramly/EditorUi.js

@@ -8558,7 +8558,7 @@
 				done(importedCells);
 			}
 		});
-		
+
 		if (mimeType.substring(0, 5) == 'image')
 		{
 			var containsModel = false;
@@ -8664,7 +8664,7 @@
 			cells = this.insertTextAt(this.validateFileData(data), dx, dy, true,
 				null, crop, null, (evt != null) ? mxEvent.isControlDown(evt) : null);
 		}
-		
+
 		if (!async && done != null)
 		{
 			done(cells);
@@ -8723,6 +8723,15 @@
 		    			
 		    			return null;
 					}
+					else if (this.isCompatibleString(data) && files.length == 1 &&
+						this.isBlankFile() && !this.canUndo())
+					{
+						// Opens as diagram if current file is blank with no undoable changes
+						this.spinner.stop();
+						this.fileLoaded(new LocalFile(this, data, filename, true));
+
+						return null;
+					}
 					else
 					{
 						return this.importFile(data, mimeType, x, y, w, h, filename,
@@ -10115,16 +10124,10 @@
 					
 				    if (files.length > 0)
 				    {
-						// Closes current file if blank and no undoable changes
-						// LATER: Check if file contains diagram data
-						var noImport = files.length == 1 && this.isBlankFile() && !this.canUndo() &&
-							(files[0].type.substring(0, 9) === 'image/svg' ||
-							files[0].type.substring(0, 6) !== 'image/' ||
-							/(\.drawio.png)$/i.test(files[0].name));
-
-						if (urlParams['embed'] != '1' && (mxEvent.isShiftDown(evt) || noImport))
+						if (urlParams['embed'] != '1' && mxEvent.isShiftDown(evt))
 						{
-							if (!mxEvent.isShiftDown(evt) && noImport &&
+							// Closes current file if blank and no undoable changes
+							if (this.isBlankFile() && !this.canUndo() &&
 								this.getCurrentFile() != null)
 							{
 								this.fileLoaded(null);
@@ -10141,7 +10144,8 @@
 							}
 							
 							this.importFiles(files, x, y, this.maxImageSize, null, null, null,
-								null, mxEvent.isControlDown(evt), null, null, mxEvent.isShiftDown(evt), evt);
+								null, mxEvent.isControlDown(evt), null, null,
+								mxEvent.isShiftDown(evt), evt);
 				    	}
 		    		}
 				    else
@@ -13597,7 +13601,7 @@
         		var padding = 0;
 
 				// Delayed after optional layout
-    			var afterInsert = function()
+    			var afterInsert = mxUtils.bind(this, function()
     			{
     				if (done != null)
     				{
@@ -13608,7 +13612,15 @@
     					graph.setSelectionCells(select);
     					graph.scrollCellToVisible(graph.getSelectionCell());
     				}
-    			};
+					
+					if (this.chromelessResize != null)
+					{
+						window.setTimeout(mxUtils.bind(this, function()
+						{
+							this.chromelessResize(true);
+						}), 0);
+					}
+    			});
     				
     			// Computes unscaled, untranslated graph bounds
     			var pt = graph.getFreeInsertPoint();
@@ -14637,7 +14649,7 @@
 		var findReplace = this.actions.get('findReplace');
 		findReplace.setEnabled(this.diagramContainer.style.visibility != 'hidden');
 		findReplace.label = mxResources.get('find') + ((graph.isEnabled()) ?
-			'/' + mxResources.get('replace') : '') + '...';
+			'/' + mxResources.get('replace') : '');
 		
 		var state = graph.view.getState(graph.getSelectionCell());
 		this.actions.get('editShape').setEnabled(active && state != null &&

+ 49 - 40
src/main/webapp/js/diagramly/GraphViewer.js

@@ -1124,7 +1124,6 @@ GraphViewer.prototype.showLayers = function(graph, sourceGraph)
 GraphViewer.prototype.addToolbar = function()
 {
 	var container = this.graph.container;
-	var initialCursor = this.graph.container.style.cursor;
 	
 	if (this.graphConfig['toolbar-position'] == 'bottom')
 	{
@@ -1278,51 +1277,15 @@ GraphViewer.prototype.addToolbar = function()
 	var tokens = this.toolbarItems;
 	var buttonCount = 0;
 	
-	function addButton(fn, imgSrc, tip, enabled)
+	var addButton = mxUtils.bind(this, function(fn, imgSrc, tip, enabled)
 	{
-		var a = document.createElement('div');
-		a.style.borderRight = '1px solid #d0d0d0';
-		a.style.padding = '3px 6px 3px 6px';
-		mxEvent.addListener(a, 'click', fn);
-
-		if (tip != null)
-		{
-			a.setAttribute('title', tip);
-		}
-		
-		a.style.display = 'inline-block';
-		var img = document.createElement('img');
-		img.setAttribute('border', '0');
-		img.setAttribute('src', imgSrc);
-		img.style.width = '18px';
-
-		if (enabled == null || enabled)
-		{
-			mxEvent.addListener(a, 'mouseenter', function()
-			{
-				a.style.backgroundColor = '#ddd';
-			});
-			
-			mxEvent.addListener(a, 'mouseleave', function()
-			{
-				a.style.backgroundColor = '#eee';
-			});
-
-			mxUtils.setOpacity(img, 60);
-			a.style.cursor = 'pointer';
-		}
-		else
-		{
-			mxUtils.setOpacity(a, 30);
-		}
-		
-		a.appendChild(img);
+		var a = this.createToolbarButton(fn, imgSrc, tip, enabled);
 		toolbar.appendChild(a);
 		
 		buttonCount++;
 		
 		return a;
-	};
+	});
 
 	var layersDialog = null;
 	var tagsComponent = null;
@@ -1693,6 +1656,52 @@ GraphViewer.prototype.addToolbar = function()
 	}
 };
 
+/**
+ * 
+ */
+GraphViewer.prototype.createToolbarButton = function(fn, imgSrc, tip, enabled)
+{
+	var a = document.createElement('div');
+	a.style.borderRight = '1px solid #d0d0d0';
+	a.style.padding = '3px 6px 3px 6px';
+	mxEvent.addListener(a, 'click', fn);
+
+	if (tip != null)
+	{
+		a.setAttribute('title', tip);
+	}
+	
+	a.style.display = 'inline-block';
+	var img = document.createElement('img');
+	img.setAttribute('border', '0');
+	img.setAttribute('src', imgSrc);
+	img.style.width = '18px';
+
+	if (enabled == null || enabled)
+	{
+		mxEvent.addListener(a, 'mouseenter', function()
+		{
+			a.style.backgroundColor = '#ddd';
+		});
+		
+		mxEvent.addListener(a, 'mouseleave', function()
+		{
+			a.style.backgroundColor = '#eee';
+		});
+
+		mxUtils.setOpacity(img, 60);
+		a.style.cursor = 'pointer';
+	}
+	else
+	{
+		mxUtils.setOpacity(a, 30);
+	}
+	
+	a.appendChild(img);
+
+	return a;
+};
+
 GraphViewer.prototype.disableButton = function(token)
 {
 	var def = this.graphConfig['toolbar-buttons']? this.graphConfig['toolbar-buttons'][token] : null;

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

@@ -983,7 +983,7 @@
 		action.setToggleAction(true);
 		action.setSelectedCallback(mxUtils.bind(this, function() { return this.tagsWindow != null && this.tagsWindow.window.isVisible(); }));
 
-		action = editorUi.actions.addAction('findReplace...', mxUtils.bind(this, function(arg1, evt)
+		action = editorUi.actions.addAction('findReplace', mxUtils.bind(this, function(arg1, evt)
 		{
 			var findReplace = graph.isEnabled() && (evt == null || !mxEvent.isShiftDown(evt));
 			var evtName = (findReplace) ? 'findReplace' : 'find';
@@ -1530,7 +1530,7 @@
 			}), parent);
 			
 			menu.addSeparator(parent);
-			editorUi.menus.addMenuItem(menu, 'runLayout', parent, null, null, mxResources.get('apply') + '...');
+			editorUi.menus.addMenuItem(menu, 'runLayout', parent, null, null, mxResources.get('custom') + '...');
 		};
 		
 		this.put('help', new Menu(mxUtils.bind(this, function(menu, parent)

+ 45 - 64
src/main/webapp/js/diagramly/Minimal.js

@@ -772,21 +772,6 @@ EditorUi.initMinimalTheme = function()
         var ui = this.editorUi;
         var graph = ui.editor.graph;
 
-        ui.actions.get('editDiagram').label = mxResources.get('formatXml') + '...';
-        ui.actions.get('createShape').label = mxResources.get('shape') + '...';
-        ui.actions.get('outline').label = mxResources.get('outline') + '...';
-        ui.actions.get('layers').label = mxResources.get('layers') + '...';
-        ui.actions.get('tags').label = mxResources.get('tags') + '...';
-		ui.actions.get('comments').label = mxResources.get('comments') + '...';
-
-        var toggleSketchModeAction = ui.actions.put('toggleSketchMode', new Action(mxResources.get('sketch'), function(e)
-        {
-			ui.setSketchMode(!Editor.sketchMode);
-        }));
-
-		toggleSketchModeAction.setToggleAction(true);
-		toggleSketchModeAction.setSelectedCallback(function() { return Editor.sketchMode; });
-				
         var togglePagesAction = ui.actions.put('togglePagesVisible', new Action(mxResources.get('pages'), function(e)
         {
             ui.setPagesVisible(!Editor.pagesVisible);
@@ -819,11 +804,17 @@ EditorUi.initMinimalTheme = function()
         	toggleShapes(ui);
         }, null, null, Editor.ctrlKey + '+Shift+K'));
 
-        var action = ui.actions.put('toggleFormat', new Action(mxResources.get('format') + '...', function()
+        var action = ui.actions.put('toggleFormat', new Action(mxResources.get('format'), function()
         {
         	toggleFormat(ui);
         }));
-		action.shortcut = ui.actions.get('formatPanel').shortcut;        
+
+		action.shortcut = ui.actions.get('formatPanel').shortcut;
+		action.setToggleAction(true);
+		action.setSelectedCallback(mxUtils.bind(this, function()
+		{
+			return ui.formatWindow != null && ui.formatWindow.window.isVisible();
+		}));
 
         if (EditorUi.enablePlantUml && !ui.isOffline())
         {
@@ -881,14 +872,27 @@ EditorUi.initMinimalTheme = function()
 			
 			menu.addSeparator(parent);
 
+			ui.menus.addMenuItems(menu, ['-', 'save'], parent);
+
+			if (file == null || file.constructor != DriveFile)
+			{
+				ui.menus.addMenuItems(menu, ['saveAs'], parent);
+			}
+
+			if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp &&
+				(file.constructor != LocalFile || file.fileHandle != null))
+			{
+				ui.menus.addMenuItems(menu, ['synchronize'], parent);
+			}
+
 			if (file != null && file.constructor == DriveFile)
 			{
-				ui.menus.addMenuItems(menu, ['save', 'rename',
-					'makeCopy', 'moveToFolder'], parent);
+				ui.menus.addMenuItems(menu, ['-', 'rename', 'makeCopy',
+					'-', 'moveToFolder', 'openFolder'], parent);
 			}
 			else
 			{
-				ui.menus.addMenuItems(menu, ['save', 'saveAs', '-', 'rename'], parent);
+				ui.menus.addMenuItems(menu, ['-', 'rename'], parent);
 				
 				if (ui.isOfflineApp())
 				{
@@ -903,38 +907,13 @@ EditorUi.initMinimalTheme = function()
 				}
 			}
 
-			menu.addSeparator(parent);
-
-			if (file != null)
+			if (file != null && file.isRevisionHistorySupported())
 			{
-				if (file.isRevisionHistorySupported())
-				{
-					ui.menus.addMenuItems(menu, ['revisionHistory'], parent);
-				}
-
-				if (file.constructor == DriveFile)
-				{
-					ui.menus.addMenuItems(menu, ['openFolder'], parent);
-				}
-
-				if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp &&
-					(file.constructor != LocalFile || file.fileHandle != null))
-				{
-					ui.menus.addMenuItems(menu, ['synchronize'], parent);
-				}
+				ui.menus.addMenuItems(menu, ['-', 'revisionHistory'], parent);
 			}
 
-			ui.menus.addMenuItems(menu, ['autosave'], parent);
-
 			if (file != null)
 			{
-				menu.addSeparator(parent);
-				
-				if (urlParams['sketch'] == '1' && ui.commentsSupported())
-				{
-					ui.menus.addMenuItems(menu, ['comments'], parent);
-				}
-
 				if (ui.fileNode != null && urlParams['embedInline'] != '1')
 				{
 					var filename = (file.getTitle() != null) ?
@@ -953,6 +932,8 @@ EditorUi.initMinimalTheme = function()
 					ui.menus.addMenuItems(menu, ['share'], parent);
 				}
 			}
+
+			ui.menus.addMenuItems(menu, ['-', 'autosave'], parent);
 		})));
 
         this.put('diagram', new Menu(mxUtils.bind(this, function(menu, parent)
@@ -1028,9 +1009,9 @@ EditorUi.initMinimalTheme = function()
 					ui.menus.addSubmenu('file', menu, parent);
 				}
 			}
-		
+			
 			ui.menus.addSubmenu('exportAs', menu, parent);
-				
+			
 			if (mxClient.IS_CHROMEAPP || EditorUi.isElectronApp)
 			{
 				ui.menus.addMenuItems(menu, ['import'], parent);
@@ -1040,14 +1021,14 @@ EditorUi.initMinimalTheme = function()
 				ui.menus.addSubmenu('importFrom', menu, parent);
 			}
 
-			if ((urlParams['embed'] == '1' || urlParams['sketch'] != '1' ||
-				urlParams['noFileMenu'] == '1') && ui.commentsSupported())
+			ui.menus.addMenuItems(menu, ['-',  'findReplace'], parent);
+
+			if (ui.commentsSupported())
 			{
-				ui.menus.addMenuItems(menu, ['-', 'comments'], parent);
+				ui.menus.addMenuItems(menu, ['comments', '-'], parent);
 			}
 
-			ui.menus.addMenuItems(menu, ['-', 'findReplace',
-				'layers', 'tags', '-', 'pageSetup'], parent);
+			ui.menus.addMenuItems(menu, ['toggleFormat', 'layers', 'tags', '-', 'pageSetup'], parent);
 
 			// Cannot use print in standalone mode on iOS as we cannot open new windows
 			if (urlParams['noFileMenu'] != '1' && (!mxClient.IS_IOS || !navigator.standalone))
@@ -1152,7 +1133,7 @@ EditorUi.initMinimalTheme = function()
 		this.put('units', new Menu(mxUtils.bind(this, function(menu, parent)
 		{
 			unitsMenu.funct(menu, parent);
-			this.addMenuItems(menu, ['-', 'pageScale', '-', 'ruler'], parent);
+			this.addMenuItems(menu, ['-', 'ruler', '-', 'pageScale'], parent);
 		})));
 		
         // Extras menu is labelled preferences but keeps ID for extensions
@@ -1325,9 +1306,9 @@ EditorUi.initMinimalTheme = function()
 		if (!formatWindowInitialized && this.formatWindow != null)
 		{
 			formatWindowInitialized = true;
-			this.formatWindow.window.setClosable(false);
 
 			var toggleMinimized = this.formatWindow.window.toggleMinimized;
+			var w = 240;
 			
 			this.formatWindow.window.toggleMinimized = function()
 			{
@@ -1335,16 +1316,16 @@ EditorUi.initMinimalTheme = function()
 				
 				if (this.minimized)
 				{
-					this.div.style.width = '90px';
-					this.table.style.width = '90px';
-					this.div.style.left = parseInt(this.div.style.left) + 150 + 'px';
+					w = parseInt(this.div.style.width);
+					this.div.style.width = '140px';
+					this.table.style.width = '140px';
+					this.div.style.left = (parseInt(this.div.style.left) + w - 140) + 'px';
 				}
 				else
 				{
-					
-					this.div.style.width = '240px';
-					this.table.style.width = '240px';
-					this.div.style.left = Math.max(0, parseInt(this.div.style.left) - 150) + 'px';
+					this.div.style.width = w + 'px';
+					this.table.style.width = this.div.style.width;
+					this.div.style.left = (Math.max(0, parseInt(this.div.style.left) - w + 140)) + 'px';
 				}
 				
 				this.fit();
@@ -1752,7 +1733,7 @@ EditorUi.initMinimalTheme = function()
 		viewZoomMenu.funct = function(menu, parent)
 		{
 			viewZoomMenuFunct.apply(this, arguments);
-			ui.menus.addMenuItems(menu, ['outline', '-', 'fullscreen', 'toggleDarkMode'], parent);
+			ui.menus.addMenuItems(menu, ['-', 'outline', 'fullscreen'], parent);
 		};
 		
 		var insertImage = (urlParams['sketch'] != '1') ? Editor.plusImage : Editor.shapesImage;

+ 1 - 1
src/main/webapp/js/diagramly/sidebar/Sidebar-ArchiMate.js

@@ -118,7 +118,7 @@
 					w, h, '', 'Triggering', null, this.getTagsForStencil(gn, '', dt + 'triggering').join(' ')),
 			this.createVertexTemplateEntry('swimlane;html=1;fillColor=#ffffff;whiteSpace=wrap', 
 					w, h, '', 'Grouping', null, this.getTagsForStencil(gn, '', dt + 'grouping').join(' ')),
-			this.createVertexTemplateEntry('ellipse;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;fillColor=#000000', 
+			this.createVertexTemplateEntry('ellipse;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;fillColor=strokeColor', 
 					10, 10, '', 'Junction', null, this.getTagsForStencil(gn, '', dt + 'junction').join(' ')),
 			this.createEdgeTemplateEntry('endArrow=block;html=1;endFill=0;edgeStyle=elbowEdgeStyle;elbow=vertical',
 					w, h, '', 'Specialization', null, this.getTagsForStencil(gn, '', dt + 'specialization').join(' ')),

+ 1 - 1
src/main/webapp/js/diagramly/sidebar/Sidebar-ArchiMate3.js

@@ -356,7 +356,7 @@
 					w * 160, 0, '', 'Specialization', null, this.getTagsForStencil(gn, '', dt + 'specialization').join(' ')),
 			this.createEdgeTemplateEntry('edgeStyle=elbowEdgeStyle;html=1;endArrow=none;elbow=vertical;',
 					w * 160, 0, '', 'Association', null, this.getTagsForStencil(gn, '', dt + 'association').join(' ')),
-			this.createVertexTemplateEntry('ellipse;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;fillColor=#000000', 
+			this.createVertexTemplateEntry('ellipse;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;fillColor=strokeColor', 
 					10, 10, '', 'And Junction', null, this.getTagsForStencil(gn, '', dt + 'junction').join(' ')),
 			this.createVertexTemplateEntry('ellipse;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;fillColor=#ffffff', 
 					10, 10, '', 'Or Junction', null, this.getTagsForStencil(gn, '', dt + 'junction').join(' '))

+ 1 - 1
src/main/webapp/js/diagramly/sidebar/Sidebar-Arrows2.js

@@ -69,7 +69,7 @@
 					100, 100, '', 'Jump-In Arrow', null, null, this.getTagsForStencil(gn, 'arrow', dt + 'jump in').join(' ')),
 			this.createVertexTemplateEntry(s + 'uTurnArrow;dy=11;arrowHead=43;dx2=25;', 
 					100, 100, '', 'U Turn Arrow', null, null, this.getTagsForStencil(gn, 'arrow', dt + 'u turn uturn').join(' ')),
-		    this.createEdgeTemplateEntry('shape=mxgraph.arrows2.wedgeArrow;html=1;bendable=0;startWidth=50;fillColor=default;defaultFillColor=invert;defaultGradientColor=invert;', 100, 100, '', 'Wedge Arrow', null, this.getTagsForStencil(gn, 'wedge arrow', dt).join(' ')),
+		    this.createEdgeTemplateEntry('shape=mxgraph.arrows2.wedgeArrow;html=1;bendable=0;startWidth=50;fillColor=strokeColor;defaultFillColor=invert;defaultGradientColor=invert;', 100, 100, '', 'Wedge Arrow', null, this.getTagsForStencil(gn, 'wedge arrow', dt).join(' ')),
 		    this.createEdgeTemplateEntry('shape=mxgraph.arrows2.wedgeArrowDashed2;html=1;bendable=0;startWidth=50;stepSize=15;', 100, 100, '', 'Wedge Arrow Dashed', null, this.getTagsForStencil(gn, 'wedge arrow dashed', dt).join(' '))
 		];
 			   	

+ 10 - 0
src/main/webapp/js/diagramly/sidebar/Sidebar-BPMN.js

@@ -459,6 +459,16 @@
 			   	return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'Sub-Choreography, Expanded');
 			}),
 
+			this.addEntry(dt + 'call choreography activity calling global task', function()
+		   	{
+			    var bg = new mxCell('', new mxGeometry(0, 0, 120, 100), 
+//				'rounded=1;whiteSpace=wrap;html=1;container=1;collapsible=0;absoluteArcSize=1;');
+				'rounded=1;whiteSpace=wrap;html=1;container=1;collapsible=0;absoluteArcSize=1;arcSize=20;childLayout=stackLayout;horizontal=1;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;');
+		    	bg.vertex = true;
+		    	
+			   	return sb.createVertexTemplateFromCells([bg], bg.geometry.width, bg.geometry.height, 'bzzzzt');
+			}),
+
 			this.addEntry(dt + 'call choreography activity calling global task', function()
 		   	{
 			    var bg = new mxCell('', new mxGeometry(0, 0, 120, 100), 

+ 1 - 1
src/main/webapp/js/diagramly/sidebar/Sidebar-C4.js

@@ -130,7 +130,7 @@
 			this.addEntry(dt + 'web browser container', function()
 		   	{
 			    var bg = new mxCell('', 
-			    		new mxGeometry(0, 0, w * 2.4, h * 1.6), 'shape=mxgraph.c4.webBrowserContainer;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;fillColor=#118ACD;fontSize=12;fontColor=#ffffff;align=center;strokeColor=#0E7DAD;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;');
+			    		new mxGeometry(0, 0, w * 2.4, h * 1.6), 'shape=mxgraph.c4.webBrowserContainer2;whiteSpace=wrap;html=1;boundedLbl=1;rounded=0;labelBackgroundColor=none;strokeColor=#118ACD;fillColor=#23A2D9;strokeColor=#118ACD;strokeColor2=#0E7DAD;fontSize=12;fontColor=#ffffff;align=center;metaEdit=1;points=[[0.5,0,0],[1,0.25,0],[1,0.5,0],[1,0.75,0],[0.5,1,0],[0,0.75,0],[0,0.5,0],[0,0.25,0]];resizable=0;');
 		    	bg.vertex = true;
 		    	bg.setValue(mxUtils.createXmlDocument().createElement('object'));
 		    	bg.setAttribute('placeholders', '1');

+ 3 - 3
src/main/webapp/js/diagramly/sidebar/Sidebar-Electrical.js

@@ -218,7 +218,7 @@
 					100, 42, '', 'Inductor', null, null, this.getTagsForStencil(gnmei, 'inductor', dtmei).join(' ')),
 			this.createVertexTemplateEntry(mei + 'choke;', 
 					100, 200, '', 'Choke', null, null, this.getTagsForStencil(gnmei, 'choke', dtmei).join(' ')),
-			this.createVertexTemplateEntry('verticalLabelPosition=top;shadow=0;dashed=0;align=center;fillColor=#000000;html=1;verticalAlign=bottom;strokeWidth=1;shape=mxgraph.electrical.inductors.variometer;', 
+			this.createVertexTemplateEntry('verticalLabelPosition=top;shadow=0;dashed=0;align=center;fillColor=strokeColor;html=1;verticalAlign=bottom;strokeWidth=1;shape=mxgraph.electrical.inductors.variometer;', 
 					150, 88, '', 'Variometer', null, null, this.getTagsForStencil(gnmei, 'variometer', dtmei).join(' ')),
 			this.createVertexTemplateEntry(mei + 'coaxial_choke;', 
 					300, 50, '', 'Coaxial Choke', null, null, this.getTagsForStencil(gnmei, 'coaxial choke', dtmei).join(' ')),
@@ -498,11 +498,11 @@
 					40, 60, '', 'Current', null, null, this.getTagsForStencil(gnmess, 'current_source', dtmess).join(' ')),
 			this.createVertexTemplateEntry(mess + 'dc_source_1;', 
 					70, 75, '', 'DC', null, null, this.getTagsForStencil(gnmess, 'dc_source_1', dtmess).join(' ')),
-			this.createVertexTemplateEntry('verticalLabelPosition=bottom;shadow=0;dashed=0;align=center;fillColor=#000000;html=1;verticalAlign=top;strokeWidth=1;shape=mxgraph.electrical.miscellaneous.monocell_battery;', 
+			this.createVertexTemplateEntry('verticalLabelPosition=bottom;shadow=0;dashed=0;align=center;fillColor=strokeColor;html=1;verticalAlign=top;strokeWidth=1;shape=mxgraph.electrical.miscellaneous.monocell_battery;', 
 					100, 60, '', 'Accumulator / Monocell Battery', null, null, this.getTagsForStencil(gnmess, 'accumulator monocell battery single cell', dtmem).join(' ')),
 			this.createVertexTemplateEntry(mem + 'batteryStack;', 
 					100, 60, '', 'Battery Stack', null, null, this.getTagsForStencil(gnmess, 'battery stack', dtmess).join(' ')),
-			this.createVertexTemplateEntry('pointerEvents=1;verticalLabelPosition=bottom;shadow=0;dashed=0;align=center;fillColor=#000000;html=1;verticalAlign=top;strokeWidth=1;shape=mxgraph.electrical.miscellaneous.multicell_battery_tapped;', 
+			this.createVertexTemplateEntry('pointerEvents=1;verticalLabelPosition=bottom;shadow=0;dashed=0;align=center;fillColor=strokeColor;html=1;verticalAlign=top;strokeWidth=1;shape=mxgraph.electrical.miscellaneous.multicell_battery_tapped;', 
 					100, 70, '', 'Multicell Battery Tapped', null, null, this.getTagsForStencil(gnmess, 'accumulator multicell battery tapped multi multiple cell', dtmem).join(' ')),
 			this.createVertexTemplateEntry(mess + 'source;aspect=fixed;points=[[0.5,0,0],[1,0.5,0],[0.5,1,0],[0,0.5,0]];elSignalType=square;', 
 					60, 60, '', 'Source, Square', null, null, this.getTagsForStencil(gnmess, 'source square', dtmess).join(' ')),

+ 8 - 8
src/main/webapp/js/diagramly/sidebar/Sidebar-Floorplan.js

@@ -13,21 +13,21 @@
 
 		var fns =
 			[
-			this.createVertexTemplateEntry(s + 'wall;fillColor=#000000;', 
+			this.createVertexTemplateEntry(s + 'wall;fillColor=strokeColor;', 
 					w, 10, '', 'Wall (Horizontal)', null, null, this.getTagsForStencil(gn, 'wall', dt).join(' ')),
-			this.createVertexTemplateEntry(s + 'wall;fillColor=#000000;direction=south;', 
+			this.createVertexTemplateEntry(s + 'wall;fillColor=strokeColor;direction=south;', 
 					10, h, '', 'Wall (Vertical)', null, null, this.getTagsForStencil(gn, 'wall', dt).join(' ')),
-			this.createVertexTemplateEntry(s + 'wallCorner;fillColor=#000000;', 
+			this.createVertexTemplateEntry(s + 'wallCorner;fillColor=strokeColor;', 
 					w, h, '', 'Wall (Corner NW)', null, null, this.getTagsForStencil(gn, 'wallCorner', dt).join(' ')),
-			this.createVertexTemplateEntry(s + 'wallCorner;fillColor=#000000;direction=south;', 
+			this.createVertexTemplateEntry(s + 'wallCorner;fillColor=strokeColor;direction=south;', 
 					w, h, '', 'Wall (Corner NE)', null, null, this.getTagsForStencil(gn, 'wallCorner', dt).join(' ')),
-			this.createVertexTemplateEntry(s + 'wallCorner;fillColor=#000000;direction=west', 
+			this.createVertexTemplateEntry(s + 'wallCorner;fillColor=strokeColor;direction=west', 
 					w, h, '', 'Wall (Corner SE)', null, null, this.getTagsForStencil(gn, 'wallCorner', dt).join(' ')),
-			this.createVertexTemplateEntry(s + 'wallCorner;fillColor=#000000;direction=north', 
+			this.createVertexTemplateEntry(s + 'wallCorner;fillColor=strokeColor;direction=north', 
 					w, h, '', 'Wall (Corner SW)', null, null, this.getTagsForStencil(gn, 'wallCorner', dt).join(' ')),
-			this.createVertexTemplateEntry(s + 'wallU;fillColor=#000000;', 
+			this.createVertexTemplateEntry(s + 'wallU;fillColor=strokeColor;', 
 					w, h, '', 'Wall (U)', null, null, this.getTagsForStencil(gn, 'wallU', dt).join(' ')),
-			this.createVertexTemplateEntry(s + 'room;fillColor=#000000;', 
+			this.createVertexTemplateEntry(s + 'room;fillColor=strokeColor;', 
 					w, h, '', 'Room', null, null, this.getTagsForStencil(gn, 'room', dt).join(' ')),
 		 	this.createVertexTemplateEntry('shape=dimension;whiteSpace=wrap;html=1;align=center;points=[];verticalAlign=bottom;spacingBottom=-5;labelBackgroundColor=#ffffff', 100, 40, 'Label', 'Horizontal Dimension', null, null, 'horizontal dimension measure distance unit'),
 		 	this.createVertexTemplateEntry('shape=dimension;direction=west;whiteSpace=wrap;html=1;align=center;points=[];verticalAlign=top;spacingTop=-8;labelBackgroundColor=#ffffff', 100, 40, 'Label', 'Vertical Dimension', null, null, 'vertical dimension measure distance unit'),

+ 1 - 1
src/main/webapp/js/diagramly/sidebar/Sidebar-FluidPower.js

@@ -4,7 +4,7 @@
 	{
 		var w = 2;
 		var h = 2;
-		var s = mxConstants.STYLE_VERTICAL_LABEL_POSITION + '=bottom;aspect=fixed;html=1;' + mxConstants.STYLE_VERTICAL_ALIGN + '=top;strokeColor=#000000;fillColor=#000000;align=center;outlineConnect=0;shape=mxgraph.fluid_power.';
+		var s = mxConstants.STYLE_VERTICAL_LABEL_POSITION + '=bottom;aspect=fixed;html=1;' + mxConstants.STYLE_VERTICAL_ALIGN + '=top;fillColor=strokeColor;align=center;outlineConnect=0;shape=mxgraph.fluid_power.';
 		var gn = 'mxgraph.fluid_power';
 		var dt = '';
 		this.setCurrentSearchEntryLibrary('fluid_power');

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

@@ -823,7 +823,7 @@
 			   	var arrow1 = new mxCell('', new mxGeometry(3, 30, 24, 70), 'shape=mxgraph.arrows2.arrow;dy=0.4;dx=16;notch=0;direction=north;fillColor=#1699D3;strokeColor=none;');
 			   	arrow1.vertex = true;
 			   	part1.insert(arrow1);
-			   	var text1 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;');
+			   	var text1 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;strokeColor=none;fillColor=none;');
 			   	text1.vertex = true;
 			   	part1.insert(text1);
 			   	
@@ -832,7 +832,7 @@
 			   	var arrow2 = new mxCell('', new mxGeometry(3, 0, 24, 80), 'shape=mxgraph.arrows2.arrow;dy=0.4;dx=16;notch=0;direction=south;fillColor=#F5AB50;strokeColor=none;');
 			   	arrow2.vertex = true;
 			   	part2.insert(arrow2);
-			   	var text2 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;');
+			   	var text2 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;strokeColor=none;fillColor=none;');
 			   	text2.vertex = true;
 			   	part2.insert(text2);
 			   	
@@ -841,7 +841,7 @@
 			   	var arrow3 = new mxCell('', new mxGeometry(3, 80, 24, 50), 'shape=mxgraph.arrows2.arrow;dy=0.4;dx=16;notch=0;direction=north;fillColor=#E85642;strokeColor=none;');
 			   	arrow3.vertex = true;
 			   	part3.insert(arrow3);
-			   	var text3 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;');
+			   	var text3 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;strokeColor=none;fillColor=none;');
 			   	text3.vertex = true;
 			   	part3.insert(text3);
 			   	
@@ -850,7 +850,7 @@
 			   	var arrow4 = new mxCell('', new mxGeometry(3, 0, 24, 30), 'shape=mxgraph.arrows2.arrow;dy=0.4;dx=16;notch=0;direction=south;fillColor=#64BBE2;strokeColor=none;');
 			   	arrow4.vertex = true;
 			   	part4.insert(arrow4);
-			   	var text4 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;');
+			   	var text4 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;strokeColor=none;fillColor=none;');
 			   	text4.vertex = true;
 			   	part4.insert(text4);
 			   	
@@ -859,7 +859,7 @@
 			   	var arrow5 = new mxCell('', new mxGeometry(3, 10, 24, 60), 'shape=mxgraph.arrows2.arrow;dy=0.4;dx=16;notch=0;direction=north;fillColor=#2F5B7C;strokeColor=none;');
 			   	arrow5.vertex = true;
 			   	part5.insert(arrow5);
-			   	var text5 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;');
+			   	var text5 = new mxCell('Label', new mxGeometry(0, 0, 30, 20), 'text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;fontColor=#FFFFFF;fontSize=10;strokeColor=none;fillColor=none;');
 			   	text5.vertex = true;
 			   	part5.insert(text5);
 			   	

+ 1 - 1
src/main/webapp/js/diagramly/sidebar/Sidebar-LeanMapping.js

@@ -71,7 +71,7 @@
 			{
 			   	var bg = new mxCell('', new mxGeometry(0, 0, 90, 40), s2 + 'kaizen_lightening_burst;');
 			   	bg.vertex = true;
-			   	var text1 = new mxCell('', new mxGeometry(8, 8, 74, 24), 'rect;fillColor=#000000;strokeColor=none;');
+			   	var text1 = new mxCell('', new mxGeometry(8, 8, 74, 24), 'rect;fillColor=strokeColor;');
 			   	text1.vertex = true;
 			   	bg.insert(text1);
 

+ 2 - 4
src/main/webapp/js/diagramly/sidebar/Sidebar-Rack.js

@@ -55,10 +55,8 @@
 		
 		this.addPaletteFunctions('rackGeneral', 'Rack / General', false,
 		[
-			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.container;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=9;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=off;', 180, 228.6, '', 'Rack Cabinet', null, null, dt + 'cabinet'),
-			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.container;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=33;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=ascend;', 210, 228.6, '', 'Numbered Rack Cabinet', null, null, dt + 'cabinet numbered'),
-			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.container;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=9;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=off;', 180, 228.6, '', 'Rack Cabinet', null, null, dt + 'cabinet'),
-			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.container;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=33;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=ascend;', 210, 228.6, '', 'Numbered Rack Cabinet', null, null, dt + 'cabinet numbered'),
+			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.rackCabinet;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=9;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=off;', 180, 219, '', 'Rack Cabinet', null, null, dt + 'cabinet'),
+			this.createVertexTemplateEntry(s + 'shape=mxgraph.rackGeneral.rackCabinet;fillColor2=#f4f4f4;container=1;collapsible=0;childLayout=rack;allowGaps=1;marginLeft=33;marginRight=9;marginTop=21;marginBottom=22;textColor=#666666;numDisp=ascend;', 204, 219, '', 'Numbered Rack Cabinet', null, null, dt + 'cabinet numbered'),
 			this.createVertexTemplateEntry(sr + 'text;', 160, 15, '', 'Spacing', null, null, dt + 'spacing'),
 			this.createVertexTemplateEntry(sr + 'shape=mxgraph.rackGeneral.plate;fillColor=#e8e8e8;', 160, 15, '', 'Cover Plate', null, null, dt + 'cover plate'),
 			this.createVertexTemplateEntry(sr + 'shape=mxgraph.rack.general.1u_rack_server;', 160, 15, '', 'Server', null, null, dt + 'server'),

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 31 - 30
src/main/webapp/js/diagramly/sidebar/Sidebar-Sysml.js


+ 6 - 6
src/main/webapp/js/diagramly/sidebar/Sidebar-UML25.js

@@ -440,7 +440,7 @@
 			}),
 			this.createVertexTemplateEntry('ellipse;fillColor=#000000;strokeColor=none;', 30, 30,
 				   	'', 'Initial preudostate / node', null, null, dt + 'initial pseudostate'),
-			this.createVertexTemplateEntry('ellipse;html=1;shape=endState;fillColor=#000000;strokeColor=#000000;', 30, 30,
+			this.createVertexTemplateEntry('ellipse;html=1;shape=endState;fillColor=strokeColor;', 30, 30,
 				   	'', 'Final state / node', null, null, dt + 'final state'),
 			this.createVertexTemplateEntry('ellipse;fillColor=#ffffff;strokeColor=#000000;', 30, 30,
 				   	'H', 'Shallow History', null, null, dt + 'shallow history pseudostate'),
@@ -887,7 +887,7 @@
 			{
 		    	var cell1 = new mxCell('InformationItem1', new mxGeometry(0, 0, 200, 50), 'align=left;spacingLeft=10;html=1;dashed=0;');
 		    	cell1.vertex = true;
-		    	var cell2 = new mxCell('', new mxGeometry(1, 0.5, 30, 20), 'shape=triangle;fillColor=#000000;');
+		    	var cell2 = new mxCell('', new mxGeometry(1, 0.5, 30, 20), 'shape=triangle;fillColor=strokeColor;');
 		    	cell2.geometry.relative = true;
 		    	cell2.geometry.offset = new mxPoint(-45, -10);
 		    	cell2.vertex = true;
@@ -930,7 +930,7 @@
 			}),
 			this.addEntry('dependency', function()
 			{
-		    	var cell1 = new mxCell('', new mxGeometry(68, 38, 4, 4), 'ellipse;resizable=0;aspect=fixed;fillColor=#000000;');
+		    	var cell1 = new mxCell('', new mxGeometry(68, 38, 4, 4), 'ellipse;resizable=0;aspect=fixed;fillColor=strokeColor;');
 		    	cell1.vertex = true;
 				var edge1 = new mxCell('&lt;&lt;keyword&gt;&gt;', new mxGeometry(0, 0, 0, 0), 'endArrow=open;html=1;rounded=0;align=center;verticalAlign=bottom;dashed=1;endFill=0;labelBackgroundColor=none;spacingBottom=35;');
 				edge1.geometry.setTerminalPoint(new mxPoint(0, 0), true);
@@ -1005,7 +1005,7 @@
 			}),
 			this.addEntry('association instance specification connector', function()
 			{
-		    	var cell1 = new mxCell('', new mxGeometry(65, 0, 6, 12), 'triangle;aspect=fixed;fillColor=#000000;');
+		    	var cell1 = new mxCell('', new mxGeometry(65, 0, 6, 12), 'triangle;aspect=fixed;fillColor=strokeColor;');
 		    	cell1.vertex = true;
 				var edge1 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'endArrow=none;html=1;rounded=0;align=center;verticalAlign=bottom;labelBackgroundColor=none;');
 				edge1.geometry.setTerminalPoint(new mxPoint(0, 22), true);
@@ -1232,7 +1232,7 @@
 		 	this.createEdgeTemplateEntry('html=1;verticalAlign=bottom;labelBackgroundColor=none;endArrow=open;endFill=0;dashed=1;', 160, 0, '', 'Message, create', null, 'message create'),
 			this.addEntry('message lost', function()
 			{
-		    	var cell1 = new mxCell('', new mxGeometry(160, 0, 4, 4), 'ellipse;html=1;fillColor=#000000;');
+		    	var cell1 = new mxCell('', new mxGeometry(160, 0, 4, 4), 'ellipse;html=1;fillColor=strokeColor;');
 		    	cell1.vertex = true;
 				var edge1 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'endArrow=open;html=1;rounded=0;align=center;verticalAlign=top;endFill=0;labelBackgroundColor=none;endSize=6;');
 				edge1.geometry.setTerminalPoint(new mxPoint(0, 2), true);
@@ -1244,7 +1244,7 @@
 			}),
 			this.addEntry('message found', function()
 			{
-		    	var cell1 = new mxCell('', new mxGeometry(0, 0, 4, 4), 'ellipse;html=1;fillColor=#000000;');
+		    	var cell1 = new mxCell('', new mxGeometry(0, 0, 4, 4), 'ellipse;html=1;fillColor=strokeColor;');
 		    	cell1.vertex = true;
 				var edge1 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'endArrow=open;html=1;rounded=0;align=center;verticalAlign=top;endFill=0;labelBackgroundColor=none;endSize=6;');
 				edge1.geometry.setTerminalPoint(new mxPoint(164, 2), false);

+ 45 - 41
src/main/webapp/js/grapheditor/EditorUi.js

@@ -92,7 +92,7 @@ EditorUi = function(editor, container, lightbox)
 		var styles = ['rounded', 'shadow', 'glass', 'dashed', 'dashPattern', 'labelBackgroundColor',
 			'labelBorderColor', 'comic', 'sketch', 'fillWeight', 'hachureGap', 'hachureAngle', 'jiggle',
 			'disableMultiStroke', 'disableMultiStrokeFill', 'fillStyle', 'curveFitting',
-			'simplification', 'sketchStyle', 'pointerEvents'];
+			'simplification', 'sketchStyle', 'pointerEvents', 'strokeColor', 'strokeWidth'];
 		var connectStyles = ['shape', 'edgeStyle', 'curved', 'rounded', 'elbow', 'jumpStyle', 'jumpSize',
 			'comic', 'sketch', 'fillWeight', 'hachureGap', 'hachureAngle', 'jiggle',
 			'disableMultiStroke', 'disableMultiStrokeFill', 'fillStyle', 'curveFitting',
@@ -108,6 +108,15 @@ EditorUi = function(editor, container, lightbox)
 		{
 			try
 			{
+				if (graph.getModel().isEdge(cell))
+				{
+					edgeStyleIgnored = false;
+				}
+				else
+				{
+					vertexStyleIgnored = false;
+				}
+
 				var style = graph.getCellStyle(cell, false);
 				var values = [];
 				var keys = [];
@@ -132,6 +141,8 @@ EditorUi = function(editor, container, lightbox)
 					'keys', keys, 'values', values,
 					'cells', [cell]));
 				
+				// Blocks update of default style with style changes
+				// once the it was set using this function
 				if (graph.getModel().isEdge(cell))
 				{
 					edgeStyleIgnored = true;
@@ -176,12 +187,11 @@ EditorUi = function(editor, container, lightbox)
 		
 		// Keys that are ignored together (if one appears all are ignored)
 		var keyGroups = [['startArrow', 'startFill', 'endArrow', 'endFill'],
-						 ['startSize', 'endSize'],
-						 ['sourcePerimeterSpacing', 'targetPerimeterSpacing'],
-		                 ['strokeColor', 'strokeWidth'],
-		                 ['fillColor', 'gradientColor', 'gradientDirection'],
-		                 ['opacity'],
-		                 ['html']];
+						['startSize', 'endSize'],
+						['sourcePerimeterSpacing', 'targetPerimeterSpacing'],
+						['fillColor', 'gradientColor', 'gradientDirection'],
+						['opacity'],
+						['html']];
 		
 		// Adds all keys used above to the styles array
 		for (var i = 0; i < keyGroups.length; i++)
@@ -755,9 +765,9 @@ EditorUi = function(editor, container, lightbox)
 			for (var i = 0; i < keys.length; i++)
 			{
 				var common = mxUtils.indexOf(valueStyles, keys[i]) >= 0;
-				
+
 				// Ignores transparent stroke colors
-				if (keys[i] != 'strokeColor' || values[i] != null && values[i] != 'none')
+				if (keys[i] != 'strokeColor' || (values[i] != null && values[i] != 'none'))
 				{
 					// Special case: Edge style and shape
 					if (mxUtils.indexOf(connectStyles, keys[i]) >= 0)
@@ -5355,40 +5365,23 @@ EditorUi.prototype.executeLayouts = function(layouts, post)
 EditorUi.prototype.executeLayout = function(exec, animate, post)
 {
 	var graph = this.editor.graph;
-
-	if (graph.isEnabled())
+	graph.getModel().beginUpdate();
+	try
 	{
-		graph.getModel().beginUpdate();
-		try
-		{
-			exec();
-		}
-		catch (e)
-		{
-			throw e;
-		}
-		finally
+		exec();
+	}
+	catch (e)
+	{
+		throw e;
+	}
+	finally
+	{
+		// Animates the changes in the graph model
+		if (this.allowAnimation && animate && graph.isEnabled())
 		{
-			// Animates the changes in the graph model except
-			// for Camino, where animation is too slow
-			if (this.allowAnimation && animate && (navigator.userAgent == null ||
-				navigator.userAgent.indexOf('Camino') < 0))
-			{
-				// New API for animating graph layout results asynchronously
-				var morph = new mxMorphing(graph);
-				morph.addListener(mxEvent.DONE, mxUtils.bind(this, function()
-				{
-					graph.getModel().endUpdate();
-					
-					if (post != null)
-					{
-						post();
-					}
-				}));
-				
-				morph.startAnimation();
-			}
-			else
+			// New API for animating graph layout results asynchronously
+			var morph = new mxMorphing(graph);
+			morph.addListener(mxEvent.DONE, mxUtils.bind(this, function()
 			{
 				graph.getModel().endUpdate();
 				
@@ -5396,6 +5389,17 @@ EditorUi.prototype.executeLayout = function(exec, animate, post)
 				{
 					post();
 				}
+			}));
+			
+			morph.startAnimation();
+		}
+		else
+		{
+			graph.getModel().endUpdate();
+			
+			if (post != null)
+			{
+				post();
 			}
 		}
 	}

+ 2 - 2
src/main/webapp/js/grapheditor/Sidebar.js

@@ -1624,7 +1624,7 @@ Sidebar.prototype.addUmlPalette = function(expand)
 	var field = new mxCell('+ field: type', new mxGeometry(0, 0, 100, 26), 'text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;');
 	field.vertex = true;
 
-	var divider = new mxCell('', new mxGeometry(0, 0, 40, 8), 'line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;');
+	var divider = new mxCell('', new mxGeometry(0, 0, 40, 8), 'line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;strokeColor=inherit;');
 	divider.vertex = true;
 	
 	// Default tags
@@ -1877,7 +1877,7 @@ Sidebar.prototype.addUmlPalette = function(expand)
 		this.createVertexTemplateEntry('shape=umlLifeline;participant=umlControl;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;verticalAlign=top;spacingTop=36;outlineConnect=0;',
 				40, 300, '', 'Control Lifeline', null, null, 'uml sequence participant lifeline control'),
 		this.createVertexTemplateEntry('shape=umlFrame;whiteSpace=wrap;html=1;', 300, 200, 'frame', 'Frame', null, null, 'uml sequence frame'),
-		this.createVertexTemplateEntry('shape=umlDestroy;whiteSpace=wrap;html=1;strokeWidth=3;', 30, 30, '', 'Destruction', null, null, 'uml sequence destruction destroy'),
+		this.createVertexTemplateEntry('shape=umlDestroy;whiteSpace=wrap;html=1;strokeWidth=3;strokeColor=default;', 30, 30, '', 'Destruction', null, null, 'uml sequence destruction destroy'),
 		this.addEntry('uml sequence invoke invocation call activation', function()
 		{
 	    	var cell = new mxCell('', new mxGeometry(0, 0, 10, 80), 'html=1;points=[];perimeter=orthogonalPerimeter;');

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 1184 - 1181
src/main/webapp/js/integrate.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 13 - 7
src/main/webapp/js/shapes-14-6-5.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 196 - 197
src/main/webapp/js/stencils.min.js


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


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


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


+ 0 - 38
src/main/webapp/package.json

@@ -1,38 +0,0 @@
-{
-  "name": "draw.io",
-  "version": "20.0.4",
-  "description": "diagrams.net desktop",
-  "main": "electron.js",
-  "scripts": {
-    "start": "electron ."
-  },
-  "repository": {
-    "type": "git",
-    "url": "git+https://github.com/jgraph/drawio.git"
-  },
-  "keywords": [
-    "draw.io",
-    "diagram",
-    "flowchart",
-    "UML"
-  ],
-  "author": "JGraph",
-  "license": "Apache-2.0",
-  "bugs": {
-    "url": "https://github.com/jgraph/drawio-desktop/issues"
-  },
-  "homepage": "https://github.com/jgraph/drawio",
-  "dependencies": {
-    "commander": "^9.4.0",
-    "compression": "^1.7.4",
-    "crc": "^4.1.1",
-    "electron-log": "^4.4.8",
-    "electron-progressbar": "^2.0.1",
-    "electron-store": "^8.1.0",
-    "electron-updater": "^5.2.1",
-    "pdf-lib": "^1.17.1"
-  },
-  "devDependencies": {
-    "electron": "^19.0.10"
-  }
-}

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


+ 123 - 0
src/main/webapp/shapes/mxC4.js

@@ -242,3 +242,126 @@ mxShapeC4WebBrowserContainer.prototype.paintVertexShape = function(c, x, y, w, h
 
 mxCellRenderer.registerShape(mxShapeC4WebBrowserContainer.prototype.cst.WEB_BROWSER_CONTAINER_SHAPE, mxShapeC4WebBrowserContainer);
 
+//**********************************************************************************************************************************************************
+// Web Browser Container v2
+//**********************************************************************************************************************************************************
+/**
+* Extends mxShape.
+*/
+function mxShapeC4WebBrowserContainer2(bounds, fill, stroke, strokewidth)
+{
+	mxShape.call(this);
+	this.bounds = bounds;
+	this.fill = fill;
+	this.stroke = stroke;
+	this.strokewidth = (strokewidth != null) ? strokewidth : 1;
+};
+
+/**
+* Extends mxShape.
+*/
+mxUtils.extend(mxShapeC4WebBrowserContainer2, mxShape);
+
+mxShapeC4WebBrowserContainer2.prototype.cst = {WEB_BROWSER_CONTAINER2_SHAPE : 'mxgraph.c4.webBrowserContainer2'};
+
+mxShapeC4WebBrowserContainer2.prototype.customProperties = [
+	{name: 'strokeColor2', dispName: 'Outline color', type: 'color', defVal: '#0E7DAD'}
+];
+
+/**
+* Function: paintVertexShape
+* 
+* Paints the vertex shape.
+*/
+mxShapeC4WebBrowserContainer2.prototype.paintVertexShape = function(c, x, y, w, h)
+{
+	c.translate(x, y);
+	var r = 8;
+	var fillColor = mxUtils.getValue(this.state.style, 'fillColor', '#ffffff');
+	var strokeColor = mxUtils.getValue(this.state.style, 'strokeColor', '#000000');
+	var strokeColor2 = mxUtils.getValue(this.state.style, 'strokeColor2', '#0E7DAD');
+
+	c.setStrokeColor(strokeColor2);
+	c.setFillColor(strokeColor);
+	
+	c.begin();
+	c.moveTo(0, r);
+	c.arcTo(r, r, 0, 0, 1, r, 0);
+	c.lineTo(w - r, 0);
+	c.arcTo(r, r, 0, 0, 1, w, r);
+	c.lineTo(w, h - r);
+	c.arcTo(r, r, 0, 0, 1, w - r, h);
+	c.lineTo(r, h);
+	c.arcTo(r, r, 0, 0, 1, 0, h - r);
+	c.close();
+	c.fillAndStroke();
+
+	c.setShadow(false);
+	
+	var ins = 5;
+	var r2 = 3;
+	var h2 = 12;
+	
+	if (w > (ins * 5 + h2 * 3) && h > (2 * h2 + 3 * ins))
+	{
+		//set fill color to fill color
+		c.setFillColor(fillColor);
+		
+		c.begin();
+		c.moveTo(ins, ins + r2);
+		c.arcTo(r2, r2, 0, 0, 1, ins + r2, ins);
+		c.lineTo(w - 3 * h2 - 4 * ins - r2, ins);
+		c.arcTo(r2, r2, 0, 0, 1, w - 3 * h2 - 4 * ins, ins + r2);
+		c.lineTo(w - 3 * h2 - 4 * ins, ins + h2 - r2);
+		c.arcTo(r2, r2, 0, 0, 1, w - 3 * h2 - 4 * ins - r2, ins + h2);
+		c.lineTo(ins + r2, ins + h2);
+		c.arcTo(r2, r2, 0, 0, 1, ins, ins + h2 - r2);
+		c.close();
+	
+		c.moveTo(w - 3 * h2 - 3 * ins, ins + r2);
+		c.arcTo(r2, r2, 0, 0, 1, w - 3 * h2 - 3 * ins + r2, ins);
+		c.lineTo(w - 2 * h2 - 3 * ins - r2, ins);
+		c.arcTo(r2, r2, 0, 0, 1, w - 2 * h2 - 3 * ins, ins + r2);
+		c.lineTo(w - 2 * h2 - 3 * ins, ins + h2 - r2);
+		c.arcTo(r2, r2, 0, 0, 1, w - 2 * h2 - 3 * ins - r2, ins + h2);
+		c.lineTo(w - 3 * h2 - 3 * ins + r2, ins + h2);
+		c.arcTo(r2, r2, 0, 0, 1, w - 3 * h2 - 3 * ins, ins + h2 - r2);
+		c.close();
+	
+		c.moveTo(w - 2 * h2 - 2 * ins, ins + r2);
+		c.arcTo(r2, r2, 0, 0, 1, w - 2 * h2 - 2 * ins + r2, ins);
+		c.lineTo(w - h2 - 2 * ins - r2, ins);
+		c.arcTo(r2, r2, 0, 0, 1, w - h2 - 2 * ins, ins + r2);
+		c.lineTo(w - h2 - 2 * ins, ins + h2 - r2);
+		c.arcTo(r2, r2, 0, 0, 1, w - h2 - 2 * ins - r2, ins + h2);
+		c.lineTo(w - 2 * h2 - 2 * ins + r2, ins + h2);
+		c.arcTo(r2, r2, 0, 0, 1, w - 2 * h2 - 2 * ins, ins + h2 - r2);
+		c.close();
+	
+		c.moveTo(w - h2 - ins, ins + r2);
+		c.arcTo(r2, r2, 0, 0, 1, w - h2 - ins + r2, ins);
+		c.lineTo(w - ins - r2, ins);
+		c.arcTo(r2, r2, 0, 0, 1, w - ins, ins + r2);
+		c.lineTo(w - ins, ins + h2 - r2);
+		c.arcTo(r2, r2, 0, 0, 1, w - ins - r2, ins + h2);
+		c.lineTo(w - h2 - ins + r2, ins + h2);
+		c.arcTo(r2, r2, 0, 0, 1, w - h2 - ins, ins + h2 - r2);
+		c.close();
+
+		c.moveTo(ins, h2 + 2 * ins + r);
+		c.arcTo(r, r, 0, 0, 1, ins + r, h2 + 2 * ins);
+		c.lineTo(w - r - ins, h2 + 2 * ins);
+		c.arcTo(r, r, 0, 0, 1, w - ins, h2 + 2 * ins + r);
+		c.lineTo(w - ins, h - r - ins);
+		c.arcTo(r, r, 0, 0, 1, w - r - ins, h - ins);
+		c.lineTo(ins + r, h - ins);
+		c.arcTo(r, r, 0, 0, 1, ins, h - r - ins);
+		c.close();
+		c.fill();
+		
+		c.fill();
+	}
+};
+
+mxCellRenderer.registerShape(mxShapeC4WebBrowserContainer2.prototype.cst.WEB_BROWSER_CONTAINER2_SHAPE, mxShapeC4WebBrowserContainer2);
+

+ 31 - 15
src/main/webapp/shapes/rack/mxRack.js

@@ -546,6 +546,22 @@ mxRackRackCabinet.prototype.cst =
 		TEXT_SIZE : 'textSize'
 };
 
+mxRackRackCabinet.prototype.customProperties = [
+	{name: 'unitNum', dispName: 'Number of units', type: 'int', defVal: 12},
+	{name: 'startUnit', dispName: 'Starting unit', type: 'int', defVal: 1},
+	{name: 'unitHeight', dispName: 'Unit height', type: 'float', defVal: 14.8},
+	{name: 'textColor', dispName: 'Number text color', type: 'color', defVal: '#666666'},
+	{name: 'textSize', dispName: 'Text size', type: 'float', defVal: '12'},
+	{name: 'numDisp', dispName: 'Display Numbers', type: 'enum', defVal: 'descend',
+		enumList: [{val: 'off', dispName: 'Off'}, {val: 'ascend', dispName: 'Ascending'}, {val: 'descend', dispName: 'Descending'}],
+		onChange: function(graph, newValue)
+		{
+			graph.setCellStyles('marginLeft', (newValue == 'off') ? 9 : 33, graph.getSelectionCells());
+		}
+	}
+];
+
+
 /**
  * Function: paintVertexShape
  * 
@@ -556,9 +572,9 @@ mxRackRackCabinet.prototype.paintVertexShape = function(c, x, y, w, h)
 	var unitNum = parseFloat(mxUtils.getValue(this.style, mxRackRackCabinet.prototype.cst.UNIT_NUM, '12'));
 	var unitH = parseFloat(mxUtils.getValue(this.style, mxRackRackCabinet.prototype.cst.UNIT_HEIGHT, '14.8'));
 	var fontSize = parseFloat(mxUtils.getValue(this.style, mxRackRackCabinet.prototype.cst.TEXT_SIZE, '12'));
-	var numDis = mxUtils.getValue(this.style, mxRackRackCabinet.prototype.cst.NUMBER_DISPLAY, mxRackRackCabinet.prototype.cst.ON);
+	var numDisp = mxUtils.getValue(this.style, mxRackRackCabinet.prototype.cst.NUMBER_DISPLAY, mxRackRackCabinet.prototype.cst.ON);
 
-	if (numDis === mxRackRackCabinet.prototype.cst.ON)
+	if (numDisp !== mxRackRackCabinet.prototype.cst.OFF)
 	{
 		c.translate(x + fontSize * 2, y);
 	}
@@ -568,24 +584,24 @@ mxRackRackCabinet.prototype.paintVertexShape = function(c, x, y, w, h)
 	};
 
 	var h = unitNum * unitH + 42;
-	this.background(c, w, h, fontSize);
+	this.background(c, h);
 	c.setShadow(false);
-	this.foreground(c, w, h, fontSize);
+	this.foreground(c, h);
 
-	if (numDis === mxRackRackCabinet.prototype.cst.ON)
+	if (numDisp !== mxRackRackCabinet.prototype.cst.OFF)
 	{
-		this.sideText(c, w, h, unitNum, unitH, fontSize);
+		this.sideText(c, h, unitNum, unitH, fontSize, numDisp);
 	};
 };
 
-mxRackRackCabinet.prototype.background = function(c, w, h, fontSize)
+mxRackRackCabinet.prototype.background = function(c, h)
 {
 	c.setFillColor('#ffffff');
 	c.rect(0, 0, 180, h);
 	c.fillAndStroke();
 };
 
-mxRackRackCabinet.prototype.foreground = function(c, w, h, fontSize)
+mxRackRackCabinet.prototype.foreground = function(c, h)
 {
 	c.setFillColor('#f4f4f4');
 	c.rect(0, 0, 180, 21);
@@ -606,29 +622,29 @@ mxRackRackCabinet.prototype.foreground = function(c, w, h, fontSize)
 	c.stroke();
 };
 
-mxRackRackCabinet.prototype.sideText = function(c, w, h, unitNum, unitH, fontSize)
+mxRackRackCabinet.prototype.sideText = function(c, h, unitNum, unitH, fontSize, numDisp)
 {
 	var fontColor = mxUtils.getValue(this.style, mxRackRackCabinet.prototype.cst.TEXT_COLOR, '#666666');
-	var numDir = mxUtils.getValue(this.style, mxRackRackCabinet.prototype.cst.NUM_DIR, mxRackRackCabinet.prototype.cst.DIR_DESC);
+	var startUnit = mxUtils.getValue(this.style, 'startUnit', 1);
 	c.setFontSize(fontSize);
 	c.setFontColor(fontColor);
 
-	if (numDir === mxRackRackCabinet.prototype.cst.DIR_ASC)
+	if (numDisp === mxRackRackCabinet.prototype.cst.DIR_ASC)
 	{
 		for (var i = 0; i < unitNum; i++)
 		{
-			c.text(-fontSize, 21 + unitH * 0.5 + i * unitH, 0, 0, (i + 1).toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
+			c.text(-fontSize, 21 + unitH * 0.5 + i * unitH, 0, 0, (i + startUnit).toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
 		};
 	}
-	else
+	else if (numDisp === mxRackRackCabinet.prototype.cst.DIR_DESC || numDisp === mxRackRackCabinet.prototype.cst.DIR_ON)
 	{
 		for (var i = 0; i < unitNum; i++)
 		{
-			c.text(-fontSize, h - 21 - unitH * 0.5 - i * unitH, 0, 0, (i + 1).toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
+			c.text(-fontSize, h - 21 - unitH * 0.5 - i * unitH, 0, 0, (i + startUnit).toString(), mxConstants.ALIGN_CENTER, mxConstants.ALIGN_MIDDLE, 0, null, 0, 0, 0);
 		};
 	};
 
-	c.setStrokeColor('#dddddd');
+	c.setStrokeColor(fontColor);
 
 	c.begin();
 

+ 34 - 34
src/main/webapp/stencils/electrical/electro-mechanical.xml

@@ -1375,7 +1375,7 @@
         <fillstroke/>
     </foreground>
 </shape>
-<shape aspect="variable" h="46" name="Selector Switch 3 position" strokewidth="inherit" w="75.006">
+<shape aspect="variable" h="46" name="Selector Switch 3 position" strokewidth="inherit" w="75">
     <connections>
         <constraint name="W" perimeter="0" x="0" y="0.5"/>
         <constraint name="NE" perimeter="0" x="1" y="0.065"/>
@@ -1384,10 +1384,10 @@
     </connections>
     <foreground>
         <path>
-            <move x="0" y="23.003"/>
-            <line x="15" y="23.003"/>
-            <move x="55.4" y="23.003"/>
-            <line x="75.006" y="23.003"/>
+            <move x="0" y="23"/>
+            <line x="15" y="23"/>
+            <move x="55.4" y="23"/>
+            <line x="75" y="23"/>
             <move x="51" y="3"/>
             <line x="75" y="3"/>
             <move x="51" y="43"/>
@@ -1396,13 +1396,13 @@
             <line x="46.465" y="3.877"/>
         </path>
         <stroke/>
-        <ellipse h="6" w="6" x="50.005" y="20.003"/>
+        <ellipse h="6" w="6" x="50" y="20"/>
         <fillstroke/>
         <ellipse h="6" w="6" x="45" y="0"/>
         <fillstroke/>
         <ellipse h="6" w="6" x="45" y="40"/>
         <fillstroke/>
-        <ellipse h="6" w="6" x="15" y="20.003"/>
+        <ellipse h="6" w="6" x="15" y="20"/>
         <fillstroke/>
         <fillcolor color="#000000"/>
         <path>
@@ -1414,7 +1414,7 @@
         <fill/>
     </foreground>
 </shape>
-<shape aspect="variable" h="105.993" name="Selector Switch 6 position" strokewidth="inherit" w="74.853">
+<shape aspect="variable" h="106" name="Selector Switch 6 position" strokewidth="inherit" w="74.85">
     <connections>
         <constraint name="W" perimeter="0" x="0" y="0.5"/>
         <constraint name="NE" perimeter="0" x="1" y="0.025"/>
@@ -1426,45 +1426,45 @@
     </connections>
     <background>
         <path>
-            <move x="0" y="53.003"/>
-            <line x="15" y="53.003"/>
-            <move x="60" y="63.003"/>
-            <line x="74.853" y="63.003"/>
-            <move x="60" y="43.003"/>
-            <line x="74.853" y="43.003"/>
-            <move x="51" y="23.003"/>
-            <line x="74.853" y="23.003"/>
-            <move x="28.993" y="2.999"/>
-            <line x="74.852" y="2.999"/>
-            <move x="28.992" y="102.993"/>
-            <line x="74.853" y="102.993"/>
-            <move x="51" y="83.003"/>
-            <line x="74.853" y="83.003"/>
-            <move x="18" y="53.003"/>
-            <line x="47" y="24.003"/>
+            <move x="0" y="53"/>
+            <line x="15" y="53"/>
+            <move x="60" y="63"/>
+            <line x="74.85" y="63"/>
+            <move x="60" y="43"/>
+            <line x="74.85" y="43"/>
+            <move x="51" y="23"/>
+            <line x="74.85" y="23"/>
+            <move x="28.99" y="3"/>
+            <line x="74.85" y="3"/>
+            <move x="28.99" y="103"/>
+            <line x="74.85" y="103"/>
+            <move x="51" y="83"/>
+            <line x="74.85" y="83"/>
+            <move x="18" y="53"/>
+            <line x="47" y="24"/>
         </path>
     </background>
     <foreground>
         <stroke/>
-        <ellipse h="6" w="6" x="54" y="60.003"/>
+        <ellipse h="6" w="6" x="54" y="60"/>
         <fillstroke/>
-        <ellipse h="6" w="6" x="54" y="40.003"/>
+        <ellipse h="6" w="6" x="54" y="40"/>
         <fillstroke/>
-        <ellipse h="6" w="6" x="45" y="20.003"/>
+        <ellipse h="6" w="6" x="45" y="20"/>
         <fillstroke/>
-        <ellipse h="6" w="6" x="22.993" y="0"/>
+        <ellipse h="6" w="6" x="23" y="0"/>
         <fillstroke/>
-        <ellipse h="6" w="6" x="22.992" y="99.993"/>
+        <ellipse h="6" w="6" x="23" y="100"/>
         <fillstroke/>
-        <ellipse h="6" w="6" x="45" y="80.003"/>
+        <ellipse h="6" w="6" x="45" y="80"/>
         <fillstroke/>
-        <ellipse h="6" w="6" x="15" y="50.003"/>
+        <ellipse h="6" w="6" x="15" y="50"/>
         <fillstroke/>
         <fillcolor color="#000000"/>
         <path>
-            <move x="47" y="24.003"/>
-            <line x="45" y="30.003"/>
-            <line x="40.667" y="26.336"/>
+            <move x="47" y="24"/>
+            <line x="45" y="30"/>
+            <line x="40.67" y="26.34"/>
             <close/>
         </path>
         <fill/>

+ 19 - 19
src/main/webapp/stencils/mockup/misc.xml

@@ -38,30 +38,30 @@
             <fillstroke/>
         </foreground>
     </shape>
-    <shape name="Cursor Hand" h="33.25" w="23.893" aspect="1">
+    <shape name="Cursor Hand" h="33.25" w="23.89" aspect="1">
         <foreground>
             <strokecolor color="#000000"/>
             <fillcolor color="#ffffff"/>
             <linejoin join="round"/>
             <path>
-                <move x="7.393" y="33.25"/>
-                <arc rx="20" ry="20" x-axis-rotation="0" large-arc-flag="0" sweep-flag="0" x="5.393" y="25.25"/>
-                <arc rx="40" ry="40" x-axis-rotation="0" large-arc-flag="0" sweep-flag="0" x="0.393" y="17.25"/>
-                <arc rx="2" ry="2" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="2.393" y="14.25"/>
-                <arc rx="10" ry="10" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="5.893" y="17.75"/>
-                <line x="5.893" y="2.25"/>
-                <arc rx="2" ry="2" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="10.393" y="2.25"/>
-                <line x="10.393" y="14.75"/>
-                <line x="10.393" y="10.25"/>
-                <arc rx="2.5" ry="2.5" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="14.893" y="10.25"/>
-                <line x="14.893" y="14.75"/>
-                <line x="14.893" y="11.25"/>
-                <arc rx="2.5" ry="2.5" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="19.393" y="11.25"/>
-                <line x="19.393" y="16.25"/>
-                <line x="19.393" y="11.75"/>
-                <arc rx="5" ry="4" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="23.893" y="15.25"/>
-                <arc rx="50" ry="50" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="21.393" y="29.25"/>
-                <line x="21.393" y="33.25"/>
+                <move x="7.39" y="33.25"/>
+                <arc rx="20" ry="20" x-axis-rotation="0" large-arc-flag="0" sweep-flag="0" x="5.39" y="25.25"/>
+                <arc rx="40" ry="40" x-axis-rotation="0" large-arc-flag="0" sweep-flag="0" x="0.39" y="17.25"/>
+                <arc rx="2" ry="2" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="2.39" y="14.25"/>
+                <arc rx="10" ry="10" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="5.89" y="17.75"/>
+                <line x="5.89" y="2.25"/>
+                <arc rx="2" ry="2" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="10.39" y="2.25"/>
+                <line x="10.39" y="14.75"/>
+                <line x="10.39" y="10.25"/>
+                <arc rx="2.5" ry="2.5" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="14.89" y="10.25"/>
+                <line x="14.89" y="14.75"/>
+                <line x="14.89" y="11.25"/>
+                <arc rx="2.5" ry="2.5" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="19.39" y="11.25"/>
+                <line x="19.39" y="16.25"/>
+                <line x="19.39" y="11.75"/>
+                <arc rx="5" ry="4" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="23.89" y="15.25"/>
+                <arc rx="50" ry="50" x-axis-rotation="0" large-arc-flag="0" sweep-flag="1" x="21.39" y="29.25"/>
+                <line x="21.39" y="33.25"/>
                 <close/>
             </path>
             <fillstroke/>