Bläddra i källkod

20.8.0 release

David Benson 3 år sedan
förälder
incheckning
8490debebe
39 ändrade filer med 11223 tillägg och 10162 borttagningar
  1. 43 0
      ChangeLog
  2. 1 1
      VERSION
  3. 2927 2912
      src/main/webapp/js/app.min.js
  4. 52 3
      src/main/webapp/js/diagramly/App.js
  5. 25 17
      src/main/webapp/js/diagramly/Dialogs.js
  6. 32 4
      src/main/webapp/js/diagramly/Editor.js
  7. 129 59
      src/main/webapp/js/diagramly/EditorUi.js
  8. 8 7
      src/main/webapp/js/diagramly/Init.js
  9. 98 78
      src/main/webapp/js/diagramly/Menus.js
  10. 9 2
      src/main/webapp/js/diagramly/Minimal.js
  11. 28 26
      src/main/webapp/js/diagramly/Pages.js
  12. 142 144
      src/main/webapp/js/diagramly/Trees.js
  13. 11 7
      src/main/webapp/js/diagramly/sidebar/Sidebar-Advanced.js
  14. 3 0
      src/main/webapp/js/diagramly/sidebar/Sidebar-Electrical.js
  15. 9 5
      src/main/webapp/js/diagramly/sidebar/Sidebar.js
  16. 4 4
      src/main/webapp/js/grapheditor/Actions.js
  17. 11 3
      src/main/webapp/js/grapheditor/Editor.js
  18. 24 9
      src/main/webapp/js/grapheditor/EditorUi.js
  19. 120 61
      src/main/webapp/js/grapheditor/Format.js
  20. 15 3
      src/main/webapp/js/grapheditor/Graph.js
  21. 32 12
      src/main/webapp/js/grapheditor/Menus.js
  22. 20 0
      src/main/webapp/js/grapheditor/Shapes.js
  23. 106 32
      src/main/webapp/js/grapheditor/Sidebar.js
  24. 9 2
      src/main/webapp/js/grapheditor/Toolbar.js
  25. 2899 2884
      src/main/webapp/js/integrate.min.js
  26. 1831 1825
      src/main/webapp/js/viewer-static.min.js
  27. 1831 1825
      src/main/webapp/js/viewer.min.js
  28. 84 84
      src/main/webapp/mxgraph/mxClient.js
  29. 556 0
      src/main/webapp/plugins/nextcloud.js
  30. 3 9
      src/main/webapp/plugins/props.js
  31. 2 9
      src/main/webapp/plugins/trees/trees.js
  32. 1 1
      src/main/webapp/resources/dia_ar.txt
  33. 33 33
      src/main/webapp/resources/dia_ca.txt
  34. 76 76
      src/main/webapp/resources/dia_it.txt
  35. 22 22
      src/main/webapp/resources/dia_ja.txt
  36. 1 1
      src/main/webapp/service-worker.js
  37. 1 1
      src/main/webapp/service-worker.js.map
  38. 1 1
      src/main/webapp/shortcuts.svg
  39. 24 0
      src/main/webapp/styles/grapheditor.css

+ 43 - 0
ChangeLog

@@ -1,3 +1,46 @@
+02-JAN-2023: 20.8.0
+
+- Fixes possible NPE for window widths below 360px
+- Fixes NPE [DS-935]
+- Shows keyboard shortcuts as tooltips when disabled
+- Decreases tap and hold delay for marquee selection
+- Fixes keyboard shortcuts conflicts
+- Hides no unread notification icon in simple theme
+- Adds background color, shadow, sketch view options
+- Add selection count in simple UI delete popup menu
+- Adds dashed wire shape [3249]
+- Fixes Cloudflare workers deployment scripts to prevent removing KV bindings and dashboard configurations [DS-938]
+- Fixes ignored dark UI theme in embed mode [3172]
+- Fixes edge styles in Advanced sidebar containers
+- Fixes order after split edge and size of waypoint
+- Fixes direct moving of segment edge end points
+- Fixes moving edge segments with segment connector
+- Fixes drag from sidebar and popup on touch devices
+- Fixes ignored final rounding for fast zoom preview
+- Updates zoom label in UI during fast zoom preview
+- Enables line jump format option for wire shapes
+- Fixes dash pattern dropdown for current selection
+- Changes default edge style in simple theme
+- Fixes sketch URL parameter default and host checks
+- Removes redirect for drive button in splash [3260]
+- Fixes possible DOM error in obsolete plugin
+- Attempt to fix possible NPE in TextFormatPanel
+- Moves page actions to submenu in pages menu
+- Adds animation for sidebar and shape picker items
+- Adds live preview for drag and drop from sidebar
+- Fixes hardcoded title font color for process bar
+- Fixes scratchpad and entry background in dark mode
+- Adds native scrolling for page tabs [3265]
+- Fixes preview for edge cases where height is 0
+- Fixes sidebar live preview item count check
+- Adds select option in tags dialog
+- Fixes focus handling with props plugin [3264]
+- Fixes NPE in vsdx import, hiddenTags is null
+- Removes undo/redo from context menu in simple UI
+- Fixes border for predefined colors in dark mode
+- Fixes height for inserted SQL table shapes
+- Adds outline for zoom menu in min and sketch UI
+
 16-DEC-2022: 20.7.4
 
 - Fixes notification icon CSS styles 

+ 1 - 1
VERSION

@@ -1 +1 @@
-20.7.4
+20.8.0

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2927 - 2912
src/main/webapp/js/app.min.js


+ 52 - 3
src/main/webapp/js/diagramly/App.js

@@ -317,6 +317,7 @@ App.pluginRegistry = {'4xAKTrabTpTzahoLthkwPNUn': 'plugins/explore.js',
 	'ex': 'plugins/explore.js', 'p1': 'plugins/p1.js',
 	'ac': 'plugins/connect.js', 'acj': 'plugins/connectJira.js',
 	'ac148': 'plugins/cConf-1-4-8.js', 'ac148cmnt': 'plugins/cConf-comments.js', 
+	'nxtcld': 'plugins/nextcloud.js',
 	'voice': 'plugins/voice.js',
 	'tips': 'plugins/tooltips.js', 'svgdata': 'plugins/svgdata.js',
 	'electron': 'plugins/electron.js',
@@ -1713,6 +1714,54 @@ App.prototype.init = function()
 			}));
 		}
 		
+		// if (this.isOwnDomain() && new Date().getFullYear() < 2023 &&
+		// 	Editor.currentTheme != 'sketch' && Editor.currentTheme != 'atlas' &&
+		// 	Editor.currentTheme != 'min' && Editor.currentTheme != 'simple')
+		// {
+		// 	this.editor.addListener('fileLoaded', mxUtils.bind(this, function()
+		// 	{
+		// 		if (Editor.currentTheme != 'sketch' && Editor.currentTheme != 'atlas' &&
+		// 			Editor.currentTheme != 'min' && Editor.currentTheme != 'simple')
+		// 		{
+		// 			window.setTimeout(mxUtils.bind(this, function()
+		// 			{
+		// 				var elt = this.menubar.langIcon;
+
+		// 				if (Editor.currentTheme != 'sketch' && Editor.currentTheme != 'atlas' &&
+		// 					Editor.currentTheme != 'min' && Editor.currentTheme != 'simple' &&
+		// 					elt != null)
+		// 				{
+		// 					this.showBanner('TryNewStyles', 'Try our new styles! →', mxUtils.bind(this, function()
+		// 					{
+		// 						if (elt != null)
+		// 						{
+		// 							elt.click();
+		// 						}
+		// 					}), true, true, 'top:2px;right:30px;', 'scale(0,1)', 'scale(1,1)', '100% 0');
+
+		// 					window.setTimeout(mxUtils.bind(this, function()
+		// 					{
+		// 						if (elt != null)
+		// 						{
+		// 							mxUtils.setPrefixedStyle(elt.style, 'transition', 'all 1s ease-in-out');
+		// 							mxUtils.setPrefixedStyle(elt.style, 'transform', 'rotate(360deg)');
+
+		// 							window.setTimeout(mxUtils.bind(this, function()
+		// 							{
+		// 								if (elt != null)
+		// 								{
+		// 									mxUtils.setPrefixedStyle(elt.style, 'transition', null);
+		// 									mxUtils.setPrefixedStyle(elt.style, 'transform', null);
+		// 								}
+		// 							}), 1000);
+		// 						}
+		// 					}), 1500);
+		// 				}
+		// 			}), 2000);
+		// 		}
+		// 	}));
+		// }
+		
 		if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp && !this.isOffline() &&
 			!mxClient.IS_ANDROID && !mxClient.IS_IOS && urlParams['open'] == null &&
 			(!this.editor.chromeless || this.editor.editable))
@@ -5752,7 +5801,7 @@ App.prototype.updateButtonContainer = function()
 		if (urlParams['embed'] == '1' && Editor.currentTheme != 'simple' &&
 			Editor.currentTheme != 'sketch')
 		{
-			this.buttonContainer.style.paddingRight = '8px';
+			this.buttonContainer.style.paddingRight = urlParams['atlas'] == '1' ? '32px' : '8px';
 		}
 
 		// Comments
@@ -6004,7 +6053,7 @@ App.prototype.showNotification = function(notifs, lsReadFlag)
 {
 	var newCount = notifs.length;
 
-	if (uiTheme == 'min')
+	if (Editor.currentTheme == 'min' || Editor.currentTheme == 'simple')
 	{
 		newCount = 0;
 
@@ -6016,7 +6065,7 @@ App.prototype.showNotification = function(notifs, lsReadFlag)
 			}
 		}
 	}
-
+	
 	if (newCount == 0)
 	{
 		if (this.notificationBtn != null)

+ 25 - 17
src/main/webapp/js/diagramly/Dialogs.js

@@ -104,12 +104,7 @@ var StorageDialog = function(editorUi, fn, rowLimit)
 		{
 			mxEvent.addListener(button, 'click', (clientFn != null) ? clientFn : function()
 			{
-				// Special case: Redirect all drive users to draw.io pro
-				if (mode == App.MODE_GOOGLE && !editorUi.isDriveDomain())
-				{
-					window.location.hostname = DriveClient.prototype.newAppHostname;
-				}
-				else if (mode == App.MODE_GOOGLE && editorUi.spinner.spin(document.body, mxResources.get('authorizing')))
+				if (mode == App.MODE_GOOGLE && editorUi.spinner.spin(document.body, mxResources.get('authorizing')))
 				{
 					// Tries immediate authentication
 					editorUi.drive.checkToken(mxUtils.bind(this, function()
@@ -1536,7 +1531,7 @@ CreateGraphDialog.prototype.connectImage = new mxImage((mxClient.IS_SVG) ? 'data
 /**
  * Constructs a new parse dialog.
  */
-var BackgroundImageDialog = function(editorUi, applyFn, img, color)
+var BackgroundImageDialog = function(editorUi, applyFn, img, color, showColor)
 {
 	var graph = editorUi.editor.graph;
 	var div = document.createElement('div');
@@ -1854,7 +1849,7 @@ var BackgroundImageDialog = function(editorUi, applyFn, img, color)
 	}
 
 	var bgDiv = document.createElement('div');
-	bgDiv.style.display = 'inline-flex';
+	bgDiv.style.display = (showColor) ? 'inline-flex' : 'none';
 	bgDiv.style.alignItems = 'center';
 	bgDiv.style.cursor = 'default';
 	bgDiv.style.minWidth = '40%';
@@ -2210,7 +2205,7 @@ var ParseDialog = function(editorUi, title, defaultType)
 						name = mxUtils.trim(name.substring(0, name.length - 1));
 					}
 					
-					tableCell = new mxCell(name, new mxGeometry(dx, 0, 160, 40),
+					tableCell = new mxCell(name, new mxGeometry(dx, 0, 160, 30),
 						'shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;' +
 						'fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;');
 					tableCell.vertex = true;
@@ -5585,8 +5580,11 @@ var LinkDialog = function(editorUi, initialValue, btnLabel, fn, showPages, showN
 		{
 			editorUi.oneDrive.pickFile(function(id, files)
 			{
-				linkInput.value = files.value[0].webUrl;
-				linkInput.focus();
+				if (files != null && files.value != null && files.value.length > 0)
+				{
+					linkInput.value = files.value[0].webUrl;
+					linkInput.focus();
+				}
 			}, true);
 		});
 	}
@@ -7693,7 +7691,7 @@ var FreehandWindow = function(editorUi, x, y, w, h, withBrush)
 		}
 	});
 	
-	startBtn.setAttribute('title', mxResources.get('startDrawing'));
+	startBtn.setAttribute('title', mxResources.get('startDrawing') + ' (X)');
 	startBtn.style.marginTop = withBrush? '5px' : '10px';
 	startBtn.style.width = '90%';
 	startBtn.style.boxSizing = 'border-box';
@@ -7721,7 +7719,7 @@ var FreehandWindow = function(editorUi, x, y, w, h, withBrush)
 		mxUtils.write(shortcut, 'X');
 		startBtn.appendChild(shortcut);
 
-		startBtn.setAttribute('title', mxResources.get(graph.freehand.isDrawing() ? 'stopDrawing' : 'startDrawing'));
+		startBtn.setAttribute('title', mxResources.get(graph.freehand.isDrawing() ? 'stopDrawing' : 'startDrawing') + ' (X)');
 		startBtn.className = 'geBtn' + (graph.freehand.isDrawing() ? ' gePrimaryBtn' : '');
 	}));
 	
@@ -9434,7 +9432,9 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 						
 						if (cells.length > 0)
 						{
-							editorUi.sidebar.createThumb(cells, ew, eh, wrapper, null, true, false);
+							editorUi.sidebar.createThumb(cells, ew, eh, wrapper, null,
+								true, false, null, null, (Editor.isDarkMode()) ?
+								'#2a252f' : '#ffffff');
 							
 							// Needs inline block on SVG for delete icon to appear on same line
 							wrapper.firstChild.style.display = 'inline-block';
@@ -9502,9 +9502,11 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 					label.style.bottom = '-18px';
 					label.style.left = '10px';
 					label.style.right = '10px';
-					label.style.backgroundColor = Editor.isDarkMode() ? Editor.darkColor : '#ffffff';
+					label.style.backgroundColor = Editor.isDarkMode() ?
+						'transparent' : '#ffffff';
 					label.style.overflow = 'hidden';
 					label.style.textAlign = 'center';
+					label.setAttribute('title', mxResources.get('rename'));
 					
 					var entry = null;
 					
@@ -9726,7 +9728,10 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 				}
 				catch (e)
 				{
-					// ignore
+					if (window.console != null)
+					{
+						console.log('Error in library dialog: ' + e);
+					}
 				}
 
 				if (!done)
@@ -9738,7 +9743,10 @@ var LibraryDialog = function(editorUi, name, library, initialImages, file, mode)
 		}
 		catch (e)
 		{
-			// ignore
+			if (window.console != null)
+			{
+				console.log('Error in library dialog: ' + e);
+			}
 		}
 		
 		return null;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 32 - 4
src/main/webapp/js/diagramly/Editor.js


+ 129 - 59
src/main/webapp/js/diagramly/EditorUi.js

@@ -3505,7 +3505,7 @@
 						graph.graphHandler.hint.style.visibility = 'hidden';	
 					}
 					
-					contentDiv.style.backgroundColor = '#f1f3f4';
+					contentDiv.style.backgroundColor = (Editor.isDarkMode()) ? '#000000' : '#fefefe';
 					contentDiv.style.cursor = 'copy';
 					graph.panningManager.stop();
 					graph.autoScroll = false;
@@ -3553,7 +3553,7 @@
 			{
 				mxEvent.addListener(contentDiv, 'dragover', mxUtils.bind(this, function(evt)
 				{
-					contentDiv.style.backgroundColor = '#f1f3f4';
+					contentDiv.style.backgroundColor = (Editor.isDarkMode()) ? '#000000' : '#fefefe';
 					evt.dataTransfer.dropEffect = 'copy';
 					contentDiv.style.cursor = 'copy';
 					this.sidebar.hideTooltip();
@@ -3919,25 +3919,26 @@
 	/**
 	 * Hides the current menu.
 	 */
-	EditorUi.prototype.showBackgroundImageDialog = function(apply, img, color)
+	EditorUi.prototype.showBackgroundImageDialog = function(apply, img, color, showColor)
 	{
 		apply = (apply != null) ? apply : mxUtils.bind(this, function(image, failed, color, shadowVisible)
 		{
 			if (!failed)
 			{
-				var change = new ChangePageSetup(this, color, image);
+				var change = new ChangePageSetup(this, (showColor) ? color : null, image);
+				change.ignoreColor = !showColor;
 
-				if (shadowVisible != null)
+				if (shadowVisible != null && showColor)
 				{
 					change.shadowVisible = shadowVisible;
 				}
-
+				
 				this.editor.graph.model.execute(change);
 			}
 		});
 
-		var dlg = new BackgroundImageDialog(this, apply, img, color);
-		this.showDialog(dlg.container, 400, 240, true, true);
+		var dlg = new BackgroundImageDialog(this, apply, img, color, showColor);
+		this.showDialog(dlg.container, 400, (showColor) ? 240 : 220, true, true);
 		dlg.init();
 	};
 
@@ -4275,7 +4276,7 @@
 	/**
 	 * Creates a popup banner.
 	 */
-	EditorUi.prototype.showBanner = function(id, text, onclick, doNotShowAgainOnClose)
+	EditorUi.prototype.showBanner = function(id, text, onclick, doNotShowAgainOnClose, small, positionCss, t1, t2, to)
 	{
 		var result = false;
 		
@@ -4283,34 +4284,57 @@
 			(!isLocalStorage || mxSettings.settings == null ||
 			mxSettings.settings['close' + id] == null))
 		{
+			positionCss = (positionCss != null) ? positionCss : 'bottom:10px;left:50%;';
+			t1 = (t1 != null) ? t1 : 'translate(-50%,120%)';
+			t2 = (t2 != null) ? t2 : 'translate(-50%,0%)';
+			var delay = (small) ? 500 : 1000;
+
+			var css = (!small) ? 'font-size:16px;padding:18px 34px 12px 20px;font-weight:bold;' :
+				'padding:4px;border-radius:6px;font-size:11px;height:12px;font-weight:normal;';
+
 			var banner = document.createElement('div');
-			banner.style.cssText = 'position:absolute;bottom:10px;left:50%;max-width:90%;padding:18px 34px 12px 20px;' +
-				'font-size:16px;font-weight:bold;white-space:nowrap;cursor:pointer;z-index:' + mxPopupMenu.prototype.zIndex + ';';
-			mxUtils.setPrefixedStyle(banner.style, 'box-shadow', '1px 1px 2px 0px #ddd');
-			mxUtils.setPrefixedStyle(banner.style, 'transform', 'translate(-50%,120%)');
-			mxUtils.setPrefixedStyle(banner.style, 'transition', 'all 1s ease');
-			banner.className = 'geBtn gePrimaryBtn';
-			
-			var logo = document.createElement('img');
-			logo.setAttribute('src', IMAGE_PATH + '/logo.png');
-			logo.setAttribute('border', '0');
-			logo.setAttribute('align', 'absmiddle');
-			logo.style.cssText = 'margin-top:-4px;margin-left:8px;margin-right:12px;width:26px;height:26px;';
-			banner.appendChild(logo);
-	
-			var img = document.createElement('img');
-			img.setAttribute('src', Dialog.prototype.closeImage);
-			img.setAttribute('title', mxResources.get((doNotShowAgainOnClose) ? 'doNotShowAgain' : 'close'));
-			img.setAttribute('border', '0');
-			img.style.cssText = 'position:absolute;right:10px;top:12px;filter:invert(1);padding:6px;margin:-6px;cursor:default;';
-			banner.appendChild(img);
+			banner.style.cssText = 'position:absolute;' + positionCss + ';max-width:90%;white-space:nowrap;' +
+				'cursor:pointer;z-index:' + mxPopupMenu.prototype.zIndex + ';' + css;
+			mxUtils.setPrefixedStyle(banner.style, 'transform', t1);
+			mxUtils.setPrefixedStyle(banner.style, 'transition', 'all ' + delay + 'ms ease');
+			banner.className = 'geBtn gePrimaryBtn' + ((small) ? ' geSmallBanner' : '');
+
+			if (!Editor.isDarkMode())
+			{
+				mxUtils.setPrefixedStyle(banner.style, 'box-shadow', '1px 1px 2px 0px #ddd');
+			}
+
+			if (to != null)
+			{
+				mxUtils.setPrefixedStyle(banner.style, 'transform-origin', to);
+			}
 			
+			if (!small)
+			{
+				var logo = document.createElement('img');
+				logo.setAttribute('src', IMAGE_PATH + '/logo.png');
+				logo.setAttribute('border', '0');
+				logo.setAttribute('align', 'absmiddle');
+				logo.style.cssText = 'margin-top:-4px;margin-left:8px;'+
+					'margin-right:12px;width:26px;height:26px;';
+				banner.appendChild(logo);
+
+				var img = document.createElement('img');
+				img.setAttribute('src', Dialog.prototype.closeImage);
+				img.setAttribute('title', mxResources.get((doNotShowAgainOnClose) ? 'doNotShowAgain' : 'close'));
+				img.setAttribute('border', '0');
+				img.style.cssText =  ((small) ? 'right:6px;top:9px;' :
+					'right:10px;top:12px;') + 'position:absolute;filter:invert(1);padding:6px;margin:-6px;cursor:default;';
+				banner.appendChild(img);
+			}
+
 			mxUtils.write(banner, text);
 			document.body.appendChild(banner);
 			this.bannerShowing = true;
 			
 			var div = document.createElement('div');
-			div.style.cssText = 'font-size:11px;text-align:center;font-weight:normal;';
+			div.style.cssText = 'display:flex;align-items:center;justify-content:center;' +
+				'padding-top:6px;font-size:11px;text-align:center;font-weight:normal;';
 			var chk = document.createElement('input');
 			chk.setAttribute('type', 'checkbox');
 			chk.setAttribute('id', 'geDoNotShowAgainCheckbox');
@@ -4324,7 +4348,7 @@
 				label.setAttribute('for', 'geDoNotShowAgainCheckbox');
 				mxUtils.write(label, mxResources.get('doNotShowAgain'));
 				div.appendChild(label);
-				banner.style.paddingBottom = '30px';
+				banner.style.paddingBottom = (small) ? '16px' : '30px';
 				banner.appendChild(div);
 			}
 			
@@ -4348,20 +4372,23 @@
 				}
 			});
 			
-			mxEvent.addListener(img, 'click', mxUtils.bind(this, function(e)
+			if (img != null)
 			{
-				mxEvent.consume(e);
-				onclose();
-			}));
+				mxEvent.addListener(img, 'click', mxUtils.bind(this, function(e)
+				{
+					mxEvent.consume(e);
+					onclose();
+				}));
+			}
 			
 			var hide = mxUtils.bind(this, function()
 			{
-				mxUtils.setPrefixedStyle(banner.style, 'transform', 'translate(-50%,120%)');
+				mxUtils.setPrefixedStyle(banner.style, 'transform', t1);
 				
 				window.setTimeout(mxUtils.bind(this, function()
 				{
 					onclose();
-				}), 1000);
+				}), delay);
 			});
 			
 			mxEvent.addListener(banner, 'click', mxUtils.bind(this, function(e)
@@ -4386,10 +4413,10 @@
 			
 			window.setTimeout(mxUtils.bind(this, function()
 			{
-				mxUtils.setPrefixedStyle(banner.style, 'transform', 'translate(-50%,0%)');
-			}), 500);
+				mxUtils.setPrefixedStyle(banner.style, 'transform', t2);
+			}), delay / 2);
 			
-			window.setTimeout(hide, 30000);
+			window.setTimeout(hide, (small) ? 4000 : 30000);
 			result = true;
 		}
 		
@@ -9352,26 +9379,22 @@
 	 */
 	EditorUi.prototype.getDefaultSketchMode = function()
 	{
-		var defaultValue = window.location.host == 'ac.draw.io' ? '1' : '0';
+		var defaultValue = urlParams['sketch'] == '1';
 		var roughParam = (urlParams['rough'] != null) ? urlParams['rough'] : defaultValue;
-
+		
 		return roughParam != '0';
 	};
 
-	// Initializes the user interface
-	var editorUiInit = EditorUi.prototype.init;
-	EditorUi.prototype.init = function()
+	/**
+	 * Overridden to set sketch mode before UI is created.
+	 */
+	var editorUiCreateUi = EditorUi.prototype.createUi;
+	EditorUi.prototype.createUi = function()
 	{
-		mxStencilRegistry.allowEval = mxStencilRegistry.allowEval && !this.isOfflineApp();
-		
-		// Must be set before UI is created in superclass
 		if (Editor.isSettingsEnabled())
 		{
-			if (urlParams['sketch'] == '1')
-			{
-				this.doSetSketchMode((mxSettings.settings.sketchMode != null && urlParams['rough'] == null) ?
-					mxSettings.settings.sketchMode : this.getDefaultSketchMode());
-			}
+			this.doSetSketchMode((mxSettings.settings.sketchMode != null && urlParams['rough'] == null &&
+				urlParams['sketch'] == null) ? mxSettings.settings.sketchMode : this.getDefaultSketchMode());
 
 			if (mxSettings.settings.sidebarTitles != null)
 			{
@@ -9381,6 +9404,17 @@
 			this.formatWidth = mxSettings.getFormatWidth();
 		}
 		
+		editorUiCreateUi.apply(this, arguments);
+	};
+
+	/**
+	 * Initializes the UI.
+	 */
+	var editorUiInit = EditorUi.prototype.init;
+	EditorUi.prototype.init = function()
+	{
+		mxStencilRegistry.allowEval = mxStencilRegistry.allowEval && !this.isOfflineApp();
+		
 		var ui = this;
 		var graph = this.editor.graph;
 
@@ -9807,6 +9841,13 @@
 							item.firstChild.nextSibling != null)
 						{
 							item.firstChild.nextSibling.style.color = 'red';
+
+							if (graph.getSelectionCount() > 1)
+							{
+								item.firstChild.nextSibling.innerHTML =
+									mxUtils.htmlEntities(mxResources.get('delete') +
+									' (' + graph.getSelectionCount() + ')');
+							}
 						}
 					}
 
@@ -9840,6 +9881,11 @@
 					Editor.currentTheme != 'min';
 			};
 
+			this.menus.isShowHistoryItems = function()
+			{
+				return 	Editor.currentTheme != 'simple';
+			};
+			
 			this.menus.isShowArrangeItems = this.menus.isShowStyleItems;
 			this.menus.isShowCellEditItems = this.menus.isShowStyleItems;
 		}
@@ -10475,7 +10521,8 @@
 		{
 			if (!mxClient.IS_IE && !mxClient.IS_IE11 && urlParams['dark'] != '0' &&
 				Editor.currentTheme != 'atlas' && (urlParams['embed'] != '1' ||
-				urlParams['dark'] == '1'))
+				urlParams['dark'] == '1' || urlParams['dark'] == 'auto' ||
+				Editor.currentTheme == 'dark' || urlParams['atlas'] == '1'))
 			{
 				var darkMode = false;
 
@@ -10483,12 +10530,14 @@
 				{
 					darkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
 				}
-				else if (Editor.isSettingsEnabled() && mxSettings.settings.darkMode === true)
+				else if (urlParams['dark'] == null && Editor.isSettingsEnabled() &&
+					mxSettings.settings.darkMode === true)
 				{
 					darkMode = true;
 				}
 				
-				if (darkMode || uiTheme == 'dark' || urlParams['dark'] == '1')
+				if (darkMode || urlParams['dark'] == '1' ||
+					Editor.currentTheme == 'dark')
 				{
 					this.setDarkMode(true);
 				}
@@ -11691,15 +11740,22 @@
 						}
 					}));
 
-					var updateZoom = mxUtils.bind(this, function()
+					var updateZoom = mxUtils.bind(this, function(sender, evt, f)
 					{
+						f = (f != null) ? f : 1;
 						elt.innerText = '';
-						mxUtils.write(elt, Math.round(this.editor.graph.view.scale * 100) + '%');
+						mxUtils.write(elt, Math.round(this.editor.graph.view.scale * 100 * f) + '%');
 					});
 
 					this.editor.graph.view.addListener(mxEvent.EVENT_SCALE, updateZoom);
 					this.editor.addListener('resetGraphView', updateZoom);
 					this.editor.addListener('pageSelected', updateZoom);
+
+					// Zoom Preview
+					this.editor.graph.addListener('zoomPreview', mxUtils.bind(this, function(sender, evt)
+					{
+						updateZoom(sender, evt, evt.getProperty('factor'));
+					}));
 				}))(elt);
 
 				if (value != 'simple')
@@ -12081,6 +12137,12 @@
 						'box-sizing:border-box;transform:translate(0, -50%);top:50%;user-select:none;';
 					this.sketchWrapperElt.appendChild(this.sketchPickerMenuElt);
 				}
+
+				// Disables built-in pan and zoom on touch devices
+				if (mxClient.IS_POINTER)
+				{
+					this.sketchPickerMenuElt.style.touchAction = 'none';
+				}
 			}
 		}
 	};
@@ -13344,7 +13406,15 @@
 			setStyle(graph.defaultEdgeStyle, 'fontSize', parseInt(this.menus.defaultFontSize) - 4);
 		}
 
-		if (Editor.currentTheme == 'simple' || Editor.currentTheme == 'sketch')
+		if (Editor.currentTheme == 'simple')
+		{
+			setStyle(graph.defaultEdgeStyle, 'edgeStyle', 'none');
+			setStyle(graph.defaultEdgeStyle, 'curved', '1');
+			setStyle(graph.defaultEdgeStyle, 'rounded', '0');
+			setStyle(graph.defaultEdgeStyle, 'endSize', '8');
+			setStyle(graph.defaultEdgeStyle, 'startSize', '8');
+		}
+		else if (Editor.currentTheme == 'sketch')
 		{
 			setStyle(graph.defaultEdgeStyle, 'edgeStyle', 'none');
 			setStyle(graph.defaultEdgeStyle, 'curved', '1');

+ 8 - 7
src/main/webapp/js/diagramly/Init.js

@@ -299,11 +299,11 @@ window.uiTheme = window.uiTheme || (function()
 	try
 	{
 		if (ui == null && urlParams['embed'] != '1' &&
-			(window.location.hostname == 'test.draw.io' ||
-			window.location.hostname == 'www.draw.io' ||
-			window.location.hostname == 'stage.diagrams.net' ||
-			window.location.hostname == 'app.diagrams.net' ||
-			window.location.hostname == 'jgraph.github.io'))
+			(window.location.hostname === 'test.draw.io' ||
+			window.location.hostname === 'www.draw.io' ||
+			window.location.hostname === 'stage.diagrams.net' ||
+			window.location.hostname === 'app.diagrams.net' ||
+			window.location.hostname === 'jgraph.github.io'))
 		{
 			var iw = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
 			
@@ -318,8 +318,9 @@ window.uiTheme = window.uiTheme || (function()
 		// ignore
 	}
 
-	// Redirects sketch UI to min UI with sketch URL parameter
-	if (ui == 'sketch')
+	// Activates sketch mode in Confluence Cloud sketch theme
+	if (ui == 'sketch' && urlParams['sketch'] == null &&
+		window.location.hostname === 'ac.draw.io')
 	{
 		urlParams['sketch'] = '1';
 	}

+ 98 - 78
src/main/webapp/js/diagramly/Menus.js

@@ -1246,9 +1246,9 @@
 			{
 				var menubar = menusCreateMenuBar.apply(this, arguments);
 				
-				if (menubar != null && Editor.enableSimpleTheme &&
-					editorUi.getServiceName() != 'atlassian' &&
-					urlParams['embed'] != '1')
+				if ((urlParams['embed'] != '1' || urlParams['atlas'] == '1') &&
+					menubar != null && Editor.enableSimpleTheme &&
+					editorUi.getServiceName() != 'atlassian')
 				{
 					var themeMenu = this.get('appearance');
 					
@@ -1396,10 +1396,10 @@
 		viewZoomMenu.funct = mxUtils.bind(this, function(menu, parent)
 		{
 			viewZoomMenuFunct.apply(this, arguments);
-
+			
 			if (Editor.currentTheme == 'sketch' || Editor.currentTheme == 'min')
 			{
-				this.addMenuItems(menu, ['-', 'fullscreen'], parent);
+				this.addMenuItems(menu, ['-', 'outline', 'fullscreen'], parent);
 			}
 		});
 		
@@ -2935,14 +2935,18 @@
 				}
 
 				if (iw < 360  && urlParams['embed'] != '1' &&
-					this.getServiceName() == 'draw.io')
+					editorUi.getServiceName() == 'draw.io')
 				{
 					this.addSubmenu('share', menu, parent);
 				}
 			}
 
-			this.addMenuItems(menu, ['-', 'lightMode', 'darkMode',
-					'autoMode', '-', 'toggleSimpleMode'], parent);
+			this.addMenuItems(menu, ['-', 'lightMode', 'darkMode', 'autoMode'], parent);
+
+			if (urlParams['embed'] != '1')
+			{
+				this.addMenuItems(menu, ['-', 'toggleSimpleMode'], parent);
+			}
 		})));
 
 		editorUi.actions.addAction('addToScratchpad', function(evt)
@@ -3456,7 +3460,7 @@
 		
 		this.put('insert', new Menu(mxUtils.bind(this, function(menu, parent)
 		{
-			if (urlParams['sketch'] == '1')
+			if (Editor.currentTheme == 'sketch')
 			{
 				editorUi.menus.addMenuItems(menu, ['toggleShapes'], parent);
 				editorUi.menus.addSubmenu('table', menu, parent);
@@ -4113,77 +4117,39 @@
 				'editData', 'copyData', 'pasteData', '-', 'editConnectionPoints',
 				'editGeometry', '-', 'editTooltip', 'editStyle', '-', 'edit'], parent);
 		})));
-		
-		// Pages menu
-		this.put('pages', new Menu(mxUtils.bind(this, function(menu, parent)
+				
+		// Current page menu
+		this.put('currentPage', new Menu(mxUtils.bind(this, function(menu, parent)
 		{
 			var page = editorUi.currentPage;
-			var pageName = editorUi.getShortPageName(page);
-			
-			menu.addItem(mxResources.get('insertPage'), null, mxUtils.bind(this, function()
-			{
-				editorUi.insertPage();
-			}), parent);
 
 			if (page != null)
 			{
-				menu.addItem(mxResources.get('duplicateIt', [pageName]), null, mxUtils.bind(this, function()
-				{
-					editorUi.duplicatePage(page, mxResources.get('copyOf', [page.getName()]));
-				}), parent);
-			}
-			
-			menu.addSeparator(parent);
-			
-			if (editorUi.pages != null && editorUi.pages.length > 1)
-			{
-				for (var i = 0; i < editorUi.pages.length; i++)
-				{
-					(mxUtils.bind(this, function(index)
-					{
-						var item = menu.addItem(editorUi.getShortPageName(editorUi.pages[index]),
-							null, mxUtils.bind(this, function()
-						{
-							editorUi.selectPage(editorUi.pages[index]);
-						}), parent);
-
-						var id = editorUi.pages[index].getId();
-						item.setAttribute('title', editorUi.pages[index].getName() +
-							' (' + (index + 1) + '/' + editorUi.pages.length + ')' +
-							((id != null) ? ' [' + id + ']' : ''));
-						
-						// Adds checkmark to current page
-						if (editorUi.pages[index] == editorUi.currentPage)
-						{
-							menu.addCheckmark(item, Editor.checkmarkImage);
-						}
-					}))(i);
-				}
-			}
-			
-			if (editorUi.editor.graph.isEnabled() && page != null)
-			{
-				menu.addSeparator(parent);
-				
-				menu.addItem(mxResources.get('renameIt', [pageName]) + '...', null, mxUtils.bind(this, function()
+				menu.addItem(mxResources.get('rename') + '...', null, mxUtils.bind(this, function()
 				{
 					editorUi.renamePage(page, page.getName());
 				}), parent);
 				
-				menu.addItem(mxResources.get('removeIt', [pageName]), null, mxUtils.bind(this, function()
+				menu.addItem(mxResources.get('delete'), null, mxUtils.bind(this, function()
 				{
 					editorUi.removePage(page);
 				}), parent);
 				
-				if (Editor.currentTheme == 'sketch' ||
-					Editor.currentTheme == 'simple')
+				if (editorUi.pages.length > 1)
 				{
-					if (editorUi.pages.length > 1)
-					{
-						editorUi.menus.addSubmenu('movePage', menu, parent, mxResources.get('move'));
-						menu.addSeparator(parent);
-					}
+					editorUi.menus.addSubmenu('movePage', menu, parent, mxResources.get('move'));
+					menu.addSeparator(parent);
+				}
+
+				menu.addSeparator(parent);
 
+				menu.addItem(mxResources.get('duplicate'), null, mxUtils.bind(this, function()
+				{
+					editorUi.duplicatePage(page, mxResources.get('copyOf', [page.getName()]));
+				}), parent);
+				
+				if (urlParams['embed'] != 1)
+				{
 					menu.addSeparator(parent);
 
 					if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp && editorUi.getServiceName() == 'draw.io')
@@ -4206,6 +4172,55 @@
 				}
 			}
 		})));
+
+		// Pages menu
+		this.put('pages', new Menu(mxUtils.bind(this, function(menu, parent)
+		{
+			var page = editorUi.currentPage;
+			
+			menu.addItem(mxResources.get('insertPage'), null, mxUtils.bind(this, function()
+			{
+				editorUi.insertPage();
+			}), parent);
+
+			menu.addSeparator(parent);
+			
+			if (editorUi.pages != null)
+			{
+				for (var i = 0; i < editorUi.pages.length; i++)
+				{
+					(mxUtils.bind(this, function(index)
+					{
+						var item = null;
+
+						if (editorUi.pages[index] == page)
+						{
+							item = editorUi.menus.addSubmenu('currentPage', menu, parent,
+								editorUi.getShortPageName(page));
+						}
+						else
+						{
+							item = menu.addItem(editorUi.getShortPageName(editorUi.pages[index]),
+								null, mxUtils.bind(this, function()
+							{
+								editorUi.selectPage(editorUi.pages[index]);
+							}), parent);
+						}
+
+						var id = editorUi.pages[index].getId();
+						item.setAttribute('title', editorUi.pages[index].getName() +
+							' (' + (index + 1) + '/' + editorUi.pages.length + ')' +
+							((id != null) ? ' [' + id + ']' : ''));
+						
+						// Adds checkmark to current page
+						if (editorUi.pages[index] == page)
+						{
+							menu.addCheckmark(item, Editor.checkmarkImage);
+						}
+					}))(i);
+				}
+			}
+		})));
 		
 		if (EditorUi.isElectronApp)
 		{
@@ -4265,18 +4280,22 @@
 			
 			if (sketchTheme || uiTheme == 'min')
 			{
-				if (urlParams['embed'] != '1' && urlParams['extAuth'] != '1' && editorUi.mode != App.MODE_ATLAS)
+				if ((urlParams['embed'] != '1' || urlParams['atlas'] == '1') &&
+					urlParams['extAuth'] != '1' && editorUi.mode != App.MODE_ATLAS &&
+					urlParams['embedInline'] != '1' && (Editor.isDarkMode() ||
+					(!mxClient.IS_IE && !mxClient.IS_IE11)))
 				{
-					if (urlParams['embedInline'] != '1' && Editor.isDarkMode() ||
-						(!mxClient.IS_IE && !mxClient.IS_IE11))
-					{
-						editorUi.menus.addSubmenu('appearance', menu, parent);
-					}
+					editorUi.menus.addSubmenu('appearance', menu, parent);
+				}
 
+				if (urlParams['embed'] != '1' && urlParams['extAuth'] != '1' &&
+					editorUi.mode != App.MODE_ATLAS)
+				{
 					editorUi.menus.addSubmenu('theme', menu, parent);
-					menu.addSeparator(parent);
 				}
 				
+				menu.addSeparator(parent);
+
 				if (langMenu != null && (urlParams['embed'] != '1' || urlParams['lang'] == null))
 				{
 					editorUi.menus.addSubmenu('language', menu, parent);
@@ -4325,14 +4344,15 @@
 					this.addSubmenu('language', menu, parent);
 				}
 				
-				if (urlParams['embed'] != '1')
+				if ((urlParams['embed'] != '1' || urlParams['atlas'] == '1') &&
+					Editor.currentTheme != 'atlas' && (Editor.isDarkMode() ||
+					(!mxClient.IS_IE && !mxClient.IS_IE11)))
 				{
-					if (Editor.currentTheme != 'atlas' && (Editor.isDarkMode() ||
-						(!mxClient.IS_IE && !mxClient.IS_IE11)))
-					{
-						editorUi.menus.addSubmenu('appearance', menu, parent);
-					}
+					editorUi.menus.addSubmenu('appearance', menu, parent);
+				}
 
+				if (urlParams['embed'] != '1')
+				{
 					this.addSubmenu('theme', menu, parent);
 				}
 

+ 9 - 2
src/main/webapp/js/diagramly/Minimal.js

@@ -903,15 +903,22 @@ EditorUi.initMinimalTheme = function()
 				// Adds shift+/alt+click on zoom label
 				mxEvent.addListener(elt, 'click', fitFunction);
 
-				var updateZoom = mxUtils.bind(this, function()
+				var updateZoom = mxUtils.bind(this, function(sender, evt, f)
 				{
+					f = (f != null) ? f : 1;
 					elt.innerText = '';
-					mxUtils.write(elt, Math.round(ui.editor.graph.view.scale * 100) + '%');
+					mxUtils.write(elt, Math.round(ui.editor.graph.view.scale * 100 * f) + '%');
 				});
 
 				ui.editor.graph.view.addListener(mxEvent.EVENT_SCALE, updateZoom);
 				ui.editor.addListener('resetGraphView', updateZoom);
 				ui.editor.addListener('pageSelected', updateZoom);
+
+				// Zoom Preview
+				ui.editor.graph.addListener('zoomPreview', mxUtils.bind(this, function(sender, evt)
+				{
+					updateZoom(sender, evt, evt.getProperty('factor'));
+				}));
 			})(elt);
 	    	
 	    	// Augments setGraphEnabled to update visible state

+ 28 - 26
src/main/webapp/js/diagramly/Pages.js

@@ -1809,47 +1809,49 @@ EditorUi.prototype.createPageMenu = function(page, label)
 {
 	return mxUtils.bind(this, function(menu, parent)
 	{
-		if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp && this.getServiceName() == 'draw.io')
+		if (urlParams['embed'] != 1)
 		{
-			menu.addItem(mxResources.get('openInNewWindow'), null, mxUtils.bind(this, function()
-			{
-				this.editor.editAsNew(this.getFileData(true, null, null, null, true, true));
-			}), parent);
-		}
-
-		var url = this.getLinkForPage(page);
+			var url = this.getLinkForPage(page);
 
-		if (url != null)
-		{
-			menu.addItem(mxResources.get('link') + '...', null, mxUtils.bind(this, function()
+			if (url != null)
+			{
+				menu.addItem(mxResources.get('link') + '...', null, mxUtils.bind(this, function()
+				{
+					this.showPageLinkDialog(page);
+				}));
+			}
+			
+			if (!mxClient.IS_CHROMEAPP && !EditorUi.isElectronApp && this.getServiceName() == 'draw.io')
 			{
-				this.showPageLinkDialog(page);
-			}));
+				menu.addItem(mxResources.get('openInNewWindow'), null, mxUtils.bind(this, function()
+				{
+					this.editor.editAsNew(this.getFileData(true, null, null, null, true, true));
+				}), parent);
+			}
+
+			menu.addSeparator(parent);
 		}
-		
-		menu.addSeparator(parent);
 
-		menu.addItem(mxResources.get('rename') + '...', null, mxUtils.bind(this, function()
-		{
-			this.renamePage(page, label);
-		}), parent);
-	
-		menu.addItem(mxResources.get('delete'), null, mxUtils.bind(this, function()
+		menu.addItem(mxResources.get('duplicate'), null, mxUtils.bind(this, function()
 		{
-			this.removePage(page);
+			this.duplicatePage(page, mxResources.get('copyOf', [page.getName()]));
 		}), parent);
+
+		menu.addSeparator(parent);
 		
 		if (this.currentPage == page && this.pages.length > 1)
 		{
 			this.menus.addSubmenu('movePage', menu, parent, mxResources.get('move'));
-			menu.addSeparator(parent);
 		}
 
-		menu.addSeparator(parent);
+		menu.addItem(mxResources.get('delete'), null, mxUtils.bind(this, function()
+		{
+			this.removePage(page);
+		}), parent);
 		
-		menu.addItem(mxResources.get('duplicate'), null, mxUtils.bind(this, function()
+		menu.addItem(mxResources.get('rename') + '...', null, mxUtils.bind(this, function()
 		{
-			this.duplicatePage(page, mxResources.get('copyOf', [page.getName()]));
+			this.renamePage(page, label);
 		}), parent);
 	});
 };

+ 142 - 144
src/main/webapp/js/diagramly/Trees.js

@@ -4,11 +4,7 @@
  */
 (function()
 {
-	/**
-	 * Defines resources.
-	 */
-	EditorUi.prototype.altShiftActions[68] = 'selectDescendants'; // Alt+Shift+D
-	
+
 	/**
 	 * Overrides folding based on treeFolding style.
 	 */
@@ -29,7 +25,6 @@
 		try
 		{
 			var newCells = cells.slice();
-			var tmp = [];
 			
 			for (var i = 0; i < cells.length; i++)
 			{
@@ -119,7 +114,7 @@
 	{
 		return this.getTreeEdges(cell, parent, true, false, false);
 	};
-		
+
 	/**
 	 * Returns all outgoing tree edges for the given cell.
 	 */
@@ -240,16 +235,17 @@
 				}
 			}
 		};
-		
+
 		// Adds actions
-		ui.actions.addAction('selectChildren', function()
+		ui.actions.addAction('selectChildren', function(evt)
 		{
 			if (graph.isEnabled() && graph.getSelectionCount() == 1)
 			{
 				var cell = graph.getSelectionCell();
-				var sib = graph.getOutgoingTreeEdges(cell);
+				var sib = mxEvent.isControlDown(evt) ? null :
+					graph.getOutgoingTreeEdges(cell);
 				
-				if (sib != null)
+				if (sib != null && sib.length > 0)
 				{
 					var tmp = [];
 					
@@ -260,89 +256,103 @@
 					
 					graph.setSelectionCells(tmp);
 				}
+				else
+				{
+					graph.setSelectionCells(graph.model.getChildren(cell));
+				}
 			}
-		}, null, null, 'Alt+Shift+X');
+		}, null, null, 'Alt+Shift+C');
 		
-		// Adds actions
-		ui.actions.addAction('selectSiblings', function()
+		ui.actions.addAction('selectDescendants', function(evt)
 		{
-			if (graph.isEnabled() && graph.getSelectionCount() == 1)
+			var cell = graph.getSelectionCell();
+			
+			if (graph.isEnabled() && cell != null)
 			{
-				var cell = graph.getSelectionCell();
-				var edges = graph.getIncomingTreeEdges(cell);
-	
-				if (edges != null && edges.length > 0)
+				var tmp = [];
+
+				if (!mxEvent.isControlDown(evt))
 				{
-					var sib = graph.getOutgoingTreeEdges(graph.model.getTerminal(edges[0], true));
-					
-					if (sib != null)
+					graph.traverse(cell, true, function(vertex, edge)
 					{
-						var tmp = [];
+						var treeEdge = edge != null && graph.isTreeEdge(edge);
+				
+						if (treeEdge && mxEvent.isControlDown(evt))
+						{
+							tmp.push(edge);
+						}
 						
-						for (var i = 0; i < sib.length; i++)
+						if (edge == null || treeEdge)
 						{
-							tmp.push(graph.model.getTerminal(sib[i], false));
+							tmp.push(vertex);
 						}
 						
-						graph.setSelectionCells(tmp);
-					}
+						return edge == null || treeEdge;
+					});
+				}
+				
+				if (tmp.length == 0 || (tmp.length == 1 &&
+					tmp[0] == cell))
+				{
+					tmp = graph.model.getDescendants(cell);
 				}
+				
+				graph.setSelectionCells(tmp);
 			}
-		}, null, null, 'Alt+Shift+S');
+		}, null, null, 'Alt+Shift+X');
 		
 		// Adds actions
-		ui.actions.addAction('selectParent', function()
+		ui.actions.addAction('selectParent', function(evt)
 		{
-			if (graph.isEnabled() && graph.getSelectionCount() == 1)
+			var cell = graph.getSelectionCell();
+
+			if (graph.isEnabled() && cell != null)
 			{
-				var cell = graph.getSelectionCell();
-				var edges = graph.getIncomingTreeEdges(cell);
+				var edges = mxEvent.isControlDown(evt) ? null :
+					graph.getIncomingTreeEdges(cell);
 	
 				if (edges != null && edges.length > 0)
 				{
 					graph.setSelectionCell(graph.model.getTerminal(edges[0], true));
 				}
+				else
+				{
+					graph.selectParentCell();
+				}
 			}
 		}, null, null, 'Alt+Shift+P');
 		
-		ui.actions.addAction('selectDescendants', function(trigger, evt)
+		// Adds actions
+		ui.actions.addAction('selectSiblings', function()
 		{
-			var cell = graph.getSelectionCell();
-			
-			if (graph.isEnabled() && graph.model.isVertex(cell))
+			if (graph.isEnabled() && graph.getSelectionCount() == 1)
 			{
-				if (evt != null && mxEvent.isAltDown(evt))
-				{
-					graph.setSelectionCells(graph.getTreeEdges(cell,
-						evt == null || !mxEvent.isShiftDown(evt),
-						evt == null || !mxEvent.isControlDown(evt)));
-				}
-				else
+				var cell = graph.getSelectionCell();
+				var edges = mxEvent.isControlDown(evt) ? null :
+					graph.getIncomingTreeEdges(cell);
+				var tmp = [];
+	
+				if (edges != null && edges.length > 0)
 				{
-					var subtree = [];
+					var sib = graph.getOutgoingTreeEdges(graph.model.getTerminal(edges[0], true));
 					
-					graph.traverse(cell, true, function(vertex, edge)
+					if (sib != null)
 					{
-						var treeEdge = edge != null && graph.isTreeEdge(edge);
-				
-						if (treeEdge && !mxEvent.isControlDown(evt))
-						{
-							subtree.push(edge);
-						}
-						
-						if ((edge == null || treeEdge) &&
-							(evt == null || !mxEvent.isShiftDown(evt)))
+						for (var i = 0; i < sib.length; i++)
 						{
-							subtree.push(vertex);
+							tmp.push(graph.model.getTerminal(sib[i], false));
 						}
-						
-						return edge == null || treeEdge;
-					});
+					}
 				}
-				
-				graph.setSelectionCells(subtree);
+
+				if (tmp.length == 0)
+				{
+					tmp = graph.model.getChildren(graph.model.getParent(cell));
+				}
+
+				graph.setSelectionCells(tmp);
 			}
-		}, null, null, 'Alt+Shift+D');
+		}, null, null, 'Alt+Shift+S');
 		
 		/**
 		 * Overriddes
@@ -1051,92 +1061,87 @@
 				}	
 			}
 		};
-	
+			
 		// Overrides keyboard shortcuts inside tree containers
-		var altShiftActions = {88: ui.actions.get('selectChildren'), // Alt+Shift+X
-				84: ui.actions.get('selectSubtree'), // Alt+Shift+T
+		var altShiftActions = {67: ui.actions.get('selectChildren'), // Alt+Shift+C
+				88: ui.actions.get('selectDescendants'), // Alt+Shift+X
 				80: ui.actions.get('selectParent'), // Alt+Shift+P
 				83: ui.actions.get('selectSiblings')} // Alt+Shift+S
-	
+
 		var editorUiOnKeyDown = ui.onKeyDown;
 		
 		ui.onKeyDown = function(evt)
 		{
 			try
 			{
-				if (graph.isEnabled() && !graph.isEditing() &&
-					isTreeVertex(graph.getSelectionCell()) &&
-					graph.getSelectionCount() == 1)
+				var cell = graph.getSelectionCell();
+
+				if (graph.isEnabled() && !graph.isEditing() && cell != null)
 				{
-					var cells = null;
-	
-					if (graph.getIncomingTreeEdges(graph.getSelectionCell()).length > 0)
-					{
-						if (evt.which == 9) // Tab adds child
-						{
-							cells = (mxEvent.isShiftDown(evt)) ?
-								addParent(graph.getSelectionCell()) :
-								addChild(graph.getSelectionCell());
-						}
-						else if (evt.which == 13) // Enter adds sibling
-						{
-							cells = addSibling(graph.getSelectionCell(), !mxEvent.isShiftDown(evt));
-						}
-					}
+					var action = (mxEvent.isAltDown(evt) && mxEvent.isShiftDown(evt)) ? 
+						altShiftActions[evt.keyCode] : null;
 					
-					if (cells != null && cells.length > 0)
+					if (action != null)
 					{
-						if (cells.length == 1 && graph.model.isEdge(cells[0]))
-						{
-							graph.setSelectionCell(graph.model.getTerminal(cells[0], false));
-						}
-						else
-						{
-							graph.setSelectionCell(cells[cells.length - 1]);
-						}
-						
-						if (ui.hoverIcons != null)
-						{
-							ui.hoverIcons.update(graph.view.getState(graph.getSelectionCell()));
-						}
-						
-						graph.startEditingAtCell(graph.getSelectionCell());
+						action.funct(evt);
 						mxEvent.consume(evt);
 					}
-					else
+					else if (isTreeVertex(cell))
 					{
-						if (mxEvent.isAltDown(evt) && mxEvent.isShiftDown(evt))
+						var cells = null;
+		
+						if (graph.getIncomingTreeEdges(cell).length > 0)
 						{
-							var action = altShiftActions[evt.keyCode];
-	
-							if (action != null)
+							if (evt.which == 9) // Tab adds child
 							{
-								action.funct(evt);
-								mxEvent.consume(evt);
+								cells = (mxEvent.isShiftDown(evt)) ?
+									addParent(cell) :
+									addChild(cell);
 							}
-						}
-						else
-						{
-							if (evt.keyCode == 37) // left
+							else if (evt.which == 13) // Enter adds sibling
 							{
-								selectCell(graph.getSelectionCell(), mxConstants.DIRECTION_WEST);
-								mxEvent.consume(evt);
+								cells = addSibling(cell, !mxEvent.isShiftDown(evt));
 							}
-							else if (evt.keyCode == 38) // up
+						}
+						
+						if (cells != null && cells.length > 0)
+						{
+							if (cells.length == 1 && graph.model.isEdge(cells[0]))
 							{
-								selectCell(graph.getSelectionCell(), mxConstants.DIRECTION_NORTH);
-								mxEvent.consume(evt);
+								graph.setSelectionCell(graph.model.getTerminal(cells[0], false));
 							}
-							else if (evt.keyCode == 39) // right
+							else
 							{
-								selectCell(graph.getSelectionCell(), mxConstants.DIRECTION_EAST);
-								mxEvent.consume(evt);
+								graph.setSelectionCell(cells[cells.length - 1]);
 							}
-							else if (evt.keyCode == 40) // down
+							
+							if (ui.hoverIcons != null)
 							{
-								selectCell(graph.getSelectionCell(), mxConstants.DIRECTION_SOUTH);
-								mxEvent.consume(evt);
+								ui.hoverIcons.update(graph.view.getState(cell));
 							}
+							
+							graph.startEditingAtCell(cell);
+							mxEvent.consume(evt);
+						}
+						else if (evt.keyCode == 37) // left
+						{
+							selectCell(cell, mxConstants.DIRECTION_WEST);
+							mxEvent.consume(evt);
+						}
+						else if (evt.keyCode == 38) // up
+						{
+							selectCell(cell, mxConstants.DIRECTION_NORTH);
+							mxEvent.consume(evt);
+						}
+						else if (evt.keyCode == 39) // right
+						{
+							selectCell(cell, mxConstants.DIRECTION_EAST);
+							mxEvent.consume(evt);
+						}
+						else if (evt.keyCode == 40) // down
+						{
+							selectCell(cell, mxConstants.DIRECTION_SOUTH);
+							mxEvent.consume(evt);
 						}
 					}
 				}
@@ -1300,6 +1305,8 @@
 			var graph = this.graph;
 			
 			// Style that defines the key, value pairs to be used for creating styles of new connections if no incoming edge exists
+			var orgEdgeStyle = 'edgeStyle=elbowEdgeStyle;elbow=vertical;sourcePerimeterSpacing=0;' +
+				'targetPerimeterSpacing=0;startArrow=none;endArrow=none;rounded=0;curved=0;';
 			var mmEdgeStyle = 'newEdgeStyle={"edgeStyle":"entityRelationEdgeStyle","startArrow":"none","endArrow":"none",' +
 				'"segment":10,"curved":1,"sourcePerimeterSpacing":0,"targetPerimeterSpacing":0};';
 			var treeEdgeStyle = 'newEdgeStyle={"edgeStyle":"elbowEdgeStyle","startArrow":"none","endArrow":"none"};';
@@ -1319,9 +1326,7 @@
 			    		'whiteSpace=wrap;html=1;treeFolding=1;treeMoving=1;' + treeEdgeStyle);
 			    	cell3.vertex = true;
 	
-			    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0),
-			    		'edgeStyle=elbowEdgeStyle;elbow=vertical;' +
-						'startArrow=none;endArrow=none;rounded=0;');
+			    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), orgEdgeStyle);
 					edge.geometry.relative = true;
 					edge.edge = true;
 	
@@ -1352,7 +1357,8 @@
 			    	cell2.vertex = true;
 
 			    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' +
-						'startArrow=none;endArrow=none;segment=10;curved=1;');
+						'startArrow=none;endArrow=none;segment=10;curved=1;sourcePerimeterSpacing=0;' +
+						'targetPerimeterSpacing=0;');
 					edge.geometry.relative = true;
 					edge.edge = true;
 	
@@ -1365,8 +1371,7 @@
 			    		'snapToPoint=1;autosize=1;treeFolding=1;treeMoving=1;' + mmEdgeStyle);
 			    	cell3.vertex = true;
 
-			    	var edge2 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' +
-						'startArrow=none;endArrow=none;segment=10;curved=1;');
+			    	var edge2 = new mxCell('', new mxGeometry(0, 0, 0, 0), edge.style);
 					edge2.geometry.relative = true;
 					edge2.edge = true;
 	
@@ -1378,8 +1383,7 @@
 		    			'strokeWidth=1;autosize=1;spacing=4;treeFolding=1;treeMoving=1;' + mmEdgeStyle);
 			    	cell4.vertex = true;
 	
-			    	var edge3 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' +
-						'startArrow=none;endArrow=none;segment=10;curved=1;');
+			    	var edge3 = new mxCell('', new mxGeometry(0, 0, 0, 0), edge.style);
 					edge3.geometry.relative = true;
 					edge3.edge = true;
 		
@@ -1392,8 +1396,7 @@
 			    		'snapToPoint=1;autosize=1;treeFolding=1;treeMoving=1;' + mmEdgeStyle);
 			    	cell5.vertex = true;
 	
-			    	var edge4 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' +
-						'startArrow=none;endArrow=none;segment=10;curved=1;');
+			    	var edge4 = new mxCell('', new mxGeometry(0, 0, 0, 0), edge.style);
 					edge4.geometry.relative = true;
 					edge4.edge = true;
 	
@@ -1432,7 +1435,8 @@
 			    	cell.vertex = true;
 	
 			    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;' +
-						'startArrow=none;endArrow=none;segment=10;curved=1;');
+						'startArrow=none;endArrow=none;segment=10;curved=1;sourcePerimeterSpacing=0;' +
+						'targetPerimeterSpacing=0;');
 					edge.geometry.setTerminalPoint(new mxPoint(-40, 40), true);
 					edge.geometry.relative = true;
 					edge.edge = true;
@@ -1450,7 +1454,8 @@
 			    	cell.vertex = true;
 	
 			    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=entityRelationEdgeStyle;startArrow=none;' +
-			    		'endArrow=none;segment=10;curved=1;sourcePerimeterSpacing=0;targetPerimeterSpacing=0;');
+			    		'endArrow=none;segment=10;curved=1;sourcePerimeterSpacing=0;' +
+						'targetPerimeterSpacing=0;');
 					edge.geometry.setTerminalPoint(new mxPoint(-40, 40), true);
 					edge.geometry.relative = true;
 					edge.edge = true;
@@ -1475,9 +1480,7 @@
 			    		'whiteSpace=wrap;html=1;align=center;verticalAlign=middle;treeFolding=1;treeMoving=1;' + treeEdgeStyle);
 			    	cell2.vertex = true;
 	
-			    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0),
-			    		'edgeStyle=elbowEdgeStyle;elbow=vertical;' +
-						'startArrow=none;endArrow=none;rounded=0;');
+			    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), orgEdgeStyle);
 					edge.geometry.relative = true;
 					edge.edge = true;
 	
@@ -1488,9 +1491,7 @@
 			    		'whiteSpace=wrap;html=1;align=center;verticalAlign=middle;treeFolding=1;treeMoving=1;' + treeEdgeStyle);
 			    	cell3.vertex = true;
 	
-			    	var edge2 = new mxCell('', new mxGeometry(0, 0, 0, 0),
-			    		'edgeStyle=elbowEdgeStyle;elbow=vertical;' +
-						'startArrow=none;endArrow=none;rounded=0;');
+			    	var edge2 = new mxCell('', new mxGeometry(0, 0, 0, 0), orgEdgeStyle);
 					edge2.geometry.relative = true;
 					edge2.edge = true;
 	
@@ -1522,9 +1523,7 @@
 			    		'whiteSpace=wrap;html=1;align=center;verticalAlign=middle;treeFolding=1;treeMoving=1;' + treeEdgeStyle);
 			    	cell.vertex = true;
 			    	
-			    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0),
-			    		'edgeStyle=elbowEdgeStyle;elbow=vertical;sourcePerimeterSpacing=0;targetPerimeterSpacing=0;' +
-						'startArrow=none;endArrow=none;rounded=0;curved=0;');
+			    	var edge = new mxCell('', new mxGeometry(0, 0, 0, 0), orgEdgeStyle);
 			    	edge.geometry.setTerminalPoint(new mxPoint(0, 0), true);
 					edge.geometry.relative = true;
 					edge.edge = true;
@@ -1552,8 +1551,7 @@
 			    		'whiteSpace=wrap;html=1;align=center;verticalAlign=middle;treeFolding=1;treeMoving=1;');
 			    	cell2.vertex = true;
 	
-			    	var edge2 = new mxCell('', new mxGeometry(0, 0, 0, 0), 'edgeStyle=orthogonalEdgeStyle;sourcePerimeterSpacing=0;targetPerimeterSpacing=0;' +
-						'startArrow=none;endArrow=none;rounded=0;targetPortConstraint=eastwest;sourcePortConstraint=northsouth;curved=0;rounded=0;');
+			    	var edge2 = new mxCell('', new mxGeometry(0, 0, 0, 0), edge.style);
 					edge2.geometry.setTerminalPoint(new mxPoint(110, -40), true);
 					edge2.geometry.relative = true;
 					edge2.edge = true;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 11 - 7
src/main/webapp/js/diagramly/sidebar/Sidebar-Advanced.js


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

@@ -986,6 +986,9 @@
 					130, 88, '', 'Anticreepage Device', null, null, this.getTagsForStencil(gnmetr, 'anticreepage device', dtmetr).join(' ')),
 			this.createVertexTemplateEntry(metr + 'testPoint;', 
 					60, 130, '', 'Test Point', null, null, this.getTagsForStencil(gnmetr, 'test point', dtmetr).join(' ')),
+			this.createEdgeTemplateEntry('shape=wire;edgeStyle=orthogonalEdgeStyle;orthogonalLoop=1;jettySize=auto;html=1;sourcePerimeterSpacing=0;targetPerimeterSpacing=0;' +
+				'endArrow=none;curved=0;rounded=0;strokeColor=#009900;dashed=1;fillColor=#ffff00;dashPattern=12 12;fixDash=1;startSize=6;endSize=6;',
+				100, 0, '', 'Dashed Wire', null, this.getTagsForStencil(gnmess, '', 'cable wire dashed').join(' ')),
 			this.createEdgeTemplateEntry('endArrow=none;html=1;strokeWidth=1;',
 					100, 0, '', 'Transmission Path', null, this.getTagsForStencil(gnmess, '', 'transmission path').join(' ')),
 			this.createEdgeTemplateEntry('endArrow=classicThin;html=1;strokeWidth=1;endSize=20;',

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

@@ -496,8 +496,8 @@
 	/**
 	 * Overrides the sidebar init.
 	 */
-	 Sidebar.prototype.init = function()
-	 {
+	Sidebar.prototype.init = function()
+	{
 		this.updateEntries();
 
 		// Uses search.xml index file instead (faster load times)
@@ -514,7 +514,7 @@
 		}
 		
 		this.initPalettes();
-	 }
+	};
 	 
 	/**
 	 * Defines all entries for the sidebar. This is used in the MoreShapes dialog. Create screenshots using the savesidebar URL parameter and
@@ -1458,8 +1458,12 @@
 				var off = mxUtils.getOffset(this.editorUi.sidebarWindow.window.div);
 
 				off.x += this.editorUi.sidebarWindow.window.div.offsetWidth + 2;
-				off.y += elt.offsetTop - elt.offsetParent.scrollTop +
-					(elt.offsetHeight - bounds.height) / 2;
+				off.y += elt.offsetTop + (elt.offsetHeight - bounds.height) / 2;
+
+				if (elt.offsetParent != null)
+				{
+					off.y -= elt.offsetParent.scrollTop;
+				}
 				
 				return new mxPoint(Math.max(0, off.x), Math.max(0, off.y));
 			}

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

@@ -313,7 +313,7 @@ Actions.prototype.init = function()
 				ui.copiedSize = new mxRectangle(geo.x, geo.y, geo.width, geo.height);
 			}
 		}
-	}, null, null, 'Alt+Shift+X');
+	}, null, null, 'Alt+Shift+F');
 
 	this.addAction('pasteSize', function()
 	{
@@ -1232,7 +1232,7 @@ Actions.prototype.init = function()
 	{
 		graph.setConnectable(!graph.connectionHandler.isEnabled());
 		ui.fireEvent(new mxEventObject('connectionPointsChanged'));
-	}, null, null, 'Alt+Shift+P');
+	}, null, null, 'Alt+Shift+O');
 	action.setToggleAction(true);
 	action.setSelectedCallback(function() { return graph.connectionHandler.isEnabled(); });
 	action = this.addAction('copyConnect', function()
@@ -1619,7 +1619,7 @@ Actions.prototype.init = function()
 				graph.getModel().endUpdate();
 			}
 		}
-	}, null, null, 'Alt+Shift+C');
+	}, null, null, 'Alt+Shift+W');
 	action = this.addAction('subscript', mxUtils.bind(this, function()
 	{
 	    if (graph.cellEditor.isContentEditing())
@@ -1876,7 +1876,7 @@ Actions.prototype.init = function()
 			});
 			dlg.init();
 		}
-	}).isEnabled = isGraphEnabled;
+	}, null, null, 'Alt+Shift+Q').isEnabled = isGraphEnabled;
 };
 
 /**

+ 11 - 3
src/main/webapp/js/grapheditor/Editor.js

@@ -1631,6 +1631,7 @@ var PageSetupDialog = function(editorUi)
 	
 	var newBackgroundImage = graph.backgroundImage;
 	var newBackgroundColor = graph.background;
+	var newShadowVisible = graph.shadowVisible;
 	
 	function updateBackgroundImage()
 	{
@@ -1663,7 +1664,7 @@ var PageSetupDialog = function(editorUi)
 
 	var changeImage = function(evt)
 	{
-		editorUi.showBackgroundImageDialog(function(image, failed, color)
+		editorUi.showBackgroundImageDialog(function(image, failed, color, shadowVisible)
 		{
 			if (!failed)
 			{
@@ -1673,11 +1674,12 @@ var PageSetupDialog = function(editorUi)
 				}
 
 				newBackgroundImage = image;
+				newShadowVisible = shadowVisible;
 			}
 
 			newBackgroundColor = color;
 			updateBackgroundImage();
-		}, newBackgroundImage, newBackgroundColor);
+		}, newBackgroundImage, newBackgroundColor, true);
 		
 		mxEvent.consume(evt);
 	};
@@ -1728,9 +1730,15 @@ var PageSetupDialog = function(editorUi)
 		
 		change.ignoreImage = oldSrc === newSrc;
 
+		if (newShadowVisible != null)
+		{
+			change.shadowVisible = newShadowVisible;
+		}
+
 		if (graph.pageFormat.width != change.previousFormat.width ||
 			graph.pageFormat.height != change.previousFormat.height ||
-			!change.ignoreColor || !change.ignoreImage)
+			!change.ignoreColor || !change.ignoreImage||
+			change.shadowVisible != graph.shadowVisible)
 		{
 			graph.model.execute(change);
 		}

+ 24 - 9
src/main/webapp/js/grapheditor/EditorUi.js

@@ -1510,6 +1510,7 @@ EditorUi.prototype.updateSelectionStateForCell = function(result, cell, cells, i
 		result.image = result.image || graph.isImageState(state);
 		result.shadow = result.shadow && graph.isShadowState(state);
 		result.fill = result.fill && graph.isFillState(state);
+		result.gradient = result.fill && graph.isGradientState(state);
 		result.stroke = result.stroke && graph.isStrokeState(state);
 		
 		var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null);
@@ -1822,6 +1823,12 @@ EditorUi.prototype.createShapePicker = function(x, y, source, callback, directio
 		div.style.top = y + 'px';
 		div.style.width = w + 'px';
 
+		// Disables built-in pan and zoom on touch devices
+		if (mxClient.IS_POINTER)
+		{
+			div.style.touchAction = 'none';
+		}
+
 		if (!hovering)
 		{
 			mxUtils.setPrefixedStyle(div.style, 'transform', 'translate(-22px,-22px)');
@@ -1982,7 +1989,8 @@ EditorUi.prototype.getCellsForShapePicker = function(cell, hovering, showEdges)
 		createVertex('shape=tape;whiteSpace=wrap;html=1;', 120, 100),
 		createVertex('ellipse;shape=cloud;whiteSpace=wrap;html=1;', 120, 80),
 		createVertex('shape=singleArrow;whiteSpace=wrap;html=1;arrowWidth=0.4;arrowSize=0.4;', 80, 60),
-		createVertex('shape=waypoint;sketch=0;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;rotatable=0;perimeter=centerPerimeter;snapToPoint=1;', 40, 40)];
+		createVertex('shape=waypoint;sketch=0;size=6;pointerEvents=1;points=[];fillColor=none;resizable=0;' +
+			'rotatable=0;perimeter=centerPerimeter;snapToPoint=1;', 20, 20)];
 	
 	if (showEdges)
 	{
@@ -3201,6 +3209,7 @@ EditorUi.prototype.initCanvas = function()
 	var scrollPosition = null;
 	var forcedZoom = null;
 	var filter = null;
+	var mult = 20;
 	
 	var scheduleZoom = function(delay)
 	{
@@ -3266,7 +3275,7 @@ EditorUi.prototype.initCanvas = function()
 						}
 
 						graph.zoom(graph.cumulativeZoomFactor, null,
-							graph.isFastZoomEnabled() ? 20 : null);
+							graph.isFastZoomEnabled() ? mult : null);
 						var s = graph.view.scale;
 						
 						if (s != prev)
@@ -3358,6 +3367,10 @@ EditorUi.prototype.initCanvas = function()
 			}
 
 			scrollPosition = new mxPoint(graph.container.scrollLeft, graph.container.scrollTop);
+
+			// Applies final rounding to preview
+			var f = Math.round((Math.round(this.view.scale * this.cumulativeZoomFactor *
+				100) / 100) * mult) / (mult * this.view.scale);
 			
 			var cx = (ignoreCursorPosition || cursorPosition == null) ?
 				graph.container.scrollLeft + graph.container.clientWidth / 2 :
@@ -3366,9 +3379,9 @@ EditorUi.prototype.initCanvas = function()
 				graph.container.scrollTop + graph.container.clientHeight / 2 :
 				cursorPosition.y + graph.container.scrollTop - graph.container.offsetTop;
 			mainGroup.style.transformOrigin = cx + 'px ' + cy + 'px';
-			mainGroup.style.transform = 'scale(' + this.cumulativeZoomFactor + ')';
+			mainGroup.style.transform = 'scale(' + f + ')';
 			bgGroup.style.transformOrigin = cx + 'px ' + cy + 'px';
-			bgGroup.style.transform = 'scale(' + this.cumulativeZoomFactor + ')';
+			bgGroup.style.transform = 'scale(' + f + ')';
 			
 			if (graph.view.backgroundPageShape != null && graph.view.backgroundPageShape.node != null)
 			{
@@ -3383,8 +3396,7 @@ EditorUi.prototype.initCanvas = function()
 						((graph.container.clientHeight / 2 + graph.container.scrollTop -
 						page.offsetTop) + 'px') : ((cursorPosition.y + graph.container.scrollTop -
 						page.offsetTop - graph.container.offsetTop) + 'px')));
-				mxUtils.setPrefixedStyle(page.style, 'transform',
-					'scale(' + this.cumulativeZoomFactor + ')');
+				mxUtils.setPrefixedStyle(page.style, 'transform', 'scale(' + f + ')');
 			}
 
 			graph.view.getDecoratorPane().style.opacity = '0';
@@ -3394,6 +3406,8 @@ EditorUi.prototype.initCanvas = function()
 			{
 				ui.hoverIcons.reset();
 			}
+
+			graph.fireEvent(new mxEventObject('zoomPreview', 'factor', f));
 		}
 		
 		scheduleZoom(graph.isFastZoomEnabled() ? delay : 0);
@@ -5744,13 +5758,14 @@ EditorUi.prototype.createOutline = function(wnd)
 };
 
 // Alt+Shift+Keycode mapping to action
-EditorUi.prototype.altShiftActions = {67: 'clearWaypoints', // Alt+Shift+C
+EditorUi.prototype.altShiftActions = {87: 'clearWaypoints', // Alt+Shift+W
   65: 'connectionArrows', // Alt+Shift+A
   76: 'editLink', // Alt+Shift+L
-  80: 'connectionPoints', // Alt+Shift+P
+  79: 'connectionPoints', // Alt+Shift+O
+  81: 'editConnectionPoints', // Alt+Shift+Q
   84: 'editTooltip', // Alt+Shift+T
   86: 'pasteSize', // Alt+Shift+V
-  88: 'copySize', // Alt+Shift+X
+  70: 'copySize', // Alt+Shift+F
   66: 'copyData', // Alt+Shift+B
   69: 'pasteData' // Alt+Shift+E
 };

+ 120 - 61
src/main/webapp/js/grapheditor/Format.js

@@ -3448,8 +3448,7 @@ TextFormatPanel.prototype.addFont = function(container)
 					var child = newFonts[i].firstChild;
 
 					// Moves the font element to inside the anchor element and adopts all children
-					if (child != null && child.nodeName == 'A' && child.nextSibling ==
-						null &&
+					if (child != null && child.nodeName == 'A' && child.nextSibling == null &&
 						child.firstChild != null)
 					{
 						var parent = newFonts[i].parentNode;
@@ -3627,17 +3626,15 @@ TextFormatPanel.prototype.addFont = function(container)
 			var blocks = graph.getSelectedTextBlocks();
 
 			// Adds paragraph tags if no block element is selected
-			if (blocks.length == 0)
+			if (blocks.length == 0 && graph.cellEditor.textarea != null &&
+				graph.cellEditor.textarea.firstChild != null)
 			{
-				if (graph.cellEditor.textarea.firstChild != null)
+				if (graph.cellEditor.textarea.firstChild.nodeName != 'P')
 				{
-					if (graph.cellEditor.textarea.firstChild.nodeName != 'P')
-					{
-						graph.cellEditor.textarea.innerHTML = '<p>' + graph.cellEditor.textarea.innerHTML + '</p>';
-					}
-
-					blocks = [graph.cellEditor.textarea.firstChild];
+					graph.cellEditor.textarea.innerHTML = '<p>' + graph.cellEditor.textarea.innerHTML + '</p>';
 				}
+
+				blocks = [graph.cellEditor.textarea.firstChild];
 			}
 
 			for (var i = 0; i < blocks.length; i++)
@@ -4713,7 +4710,11 @@ StyleFormatPanel.prototype.addFill = function(container)
 	};
 
 	populateFillStyle();
-	fillPanel.appendChild(fillStyleSelect);
+
+	if (ss.gradient)
+	{
+		fillPanel.appendChild(fillStyleSelect);
+	}
 
 	var listener = mxUtils.bind(this, function()
 	{
@@ -4764,8 +4765,10 @@ StyleFormatPanel.prototype.addFill = function(container)
 
 			fillStyleSelect.style.display = ss.style.sketch == '1' ||
 				gradientSelect.style.display == 'none'? '' : 'none';
-			gradientPanel.style.display = (!ss.containsImage && (ss.style.sketch != '1' ||
-				fillStyle == 'solid' || fillStyle == 'auto')) ? '' : 'none';
+			gradientPanel.style.display = (ss.gradient &&
+				!ss.containsImage && (ss.style.sketch != '1' ||
+				fillStyle == 'solid' || fillStyle == 'auto')) ?
+				'' : 'none';
 		}
 	});
 	
@@ -4947,7 +4950,9 @@ StyleFormatPanel.prototype.addStroke = function(container)
 	var pattern = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel, 'geSprite-orthogonal', mxResources.get('pattern'), false, mxUtils.bind(this, function(menu)
 	{
 		addItem(menu, 75, 'solid', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], [null, null]).setAttribute('title', mxResources.get('solid'));
-		addItem(menu, 75, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', null]).setAttribute('title', mxResources.get('dashed'));
+		addItem(menu, 75, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', null]).setAttribute('title', mxResources.get('dashed') + ' (1)');
+		addItem(menu, 75, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '8 8']).setAttribute('title', mxResources.get('dashed') + ' (2)');
+		addItem(menu, 75, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '12 12']).setAttribute('title', mxResources.get('dashed') + ' (3)');
 		addItem(menu, 75, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 1']).setAttribute('title', mxResources.get('dotted') + ' (1)');
 		addItem(menu, 75, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 2']).setAttribute('title', mxResources.get('dotted') + ' (2)');
 		addItem(menu, 75, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 4']).setAttribute('title', mxResources.get('dotted') + ' (3)');
@@ -4967,7 +4972,9 @@ StyleFormatPanel.prototype.addStroke = function(container)
 	var altPattern = this.editorUi.toolbar.addMenuFunctionInContainer(altStylePanel, 'geSprite-orthogonal', mxResources.get('pattern'), false, mxUtils.bind(this, function(menu)
 	{
 		addItem(menu, 33, 'solid', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], [null, null]).setAttribute('title', mxResources.get('solid'));
-		addItem(menu, 33, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', null]).setAttribute('title', mxResources.get('dashed'));
+		addItem(menu, 33, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', null]).setAttribute('title', mxResources.get('dashed') + ' (1)');
+		addItem(menu, 33, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '8 8']).setAttribute('title', mxResources.get('dashed') + ' (2)');
+		addItem(menu, 33, 'dashed', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '12 12']).setAttribute('title', mxResources.get('dashed') + ' (3)');
 		addItem(menu, 33, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 1']).setAttribute('title', mxResources.get('dotted') + ' (1)');
 		addItem(menu, 33, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 2']).setAttribute('title', mxResources.get('dotted') + ' (2)');
 		addItem(menu, 33, 'dotted', [mxConstants.STYLE_DASHED, mxConstants.STYLE_DASH_PATTERN], ['1', '1 4']).setAttribute('title', mxResources.get('dotted') + ' (3)');
@@ -5068,7 +5075,7 @@ StyleFormatPanel.prototype.addStroke = function(container)
 
 	var lineStart = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel2, 'geSprite-startclassic', mxResources.get('linestart'), false, mxUtils.bind(this, function(menu)
 	{
-		if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow' || ss.style.shape == 'filledEdge')
+		if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow' || ss.style.shape == 'filledEdge' || ss.style.shape == 'wire')
 		{
 			var item = this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.NONE, 0], 'geIcon', null, false);
 			item.setAttribute('title', mxResources.get('none'));
@@ -5078,7 +5085,7 @@ StyleFormatPanel.prototype.addStroke = function(container)
 			mxUtils.write(font, mxResources.get('none'));
 			item.firstChild.firstChild.appendChild(font);
 
-			if (ss.style.shape == 'connector' || ss.style.shape == 'filledEdge')
+			if (ss.style.shape == 'connector' || ss.style.shape == 'filledEdge' || ss.style.shape == 'wire')
 			{
 				Format.processMenuIcon(this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC, 1], null, null, false, Format.classicFilledMarkerImage.src));
 				Format.processMenuIcon(this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_STARTARROW, 'startFill'], [mxConstants.ARROW_CLASSIC_THIN, 1], null, null, false, Format.classicThinFilledMarkerImage.src));
@@ -5134,7 +5141,7 @@ StyleFormatPanel.prototype.addStroke = function(container)
 
 	var lineEnd = this.editorUi.toolbar.addMenuFunctionInContainer(stylePanel2, 'geSprite-endclassic', mxResources.get('lineend'), false, mxUtils.bind(this, function(menu)
 	{
-		if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow' || ss.style.shape == 'filledEdge')
+		if (ss.style.shape == 'connector' || ss.style.shape == 'flexArrow' || ss.style.shape == 'filledEdge' || ss.style.shape == 'wire')
 		{
 			var item = this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.NONE, 0], 'geIcon', null, false);
 			item.setAttribute('title', mxResources.get('none'));
@@ -5144,7 +5151,7 @@ StyleFormatPanel.prototype.addStroke = function(container)
 			mxUtils.write(font, mxResources.get('none'));
 			item.firstChild.firstChild.appendChild(font);
 			
-			if (ss.style.shape == 'connector' || ss.style.shape == 'filledEdge')
+			if (ss.style.shape == 'connector' || ss.style.shape == 'filledEdge' || ss.style.shape == 'wire')
 			{
 				Format.processMenuIcon(this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC, 1], null, null, false, Format.classicFilledMarkerImage.src), 'scaleX(-1)');
 				Format.processMenuIcon(this.editorUi.menus.edgeStyleChange(menu, '', [mxConstants.STYLE_ENDARROW, 'endFill'], [mxConstants.ARROW_CLASSIC_THIN, 1], null, null, false, Format.classicThinFilledMarkerImage.src), 'scaleX(-1)');
@@ -5361,7 +5368,8 @@ StyleFormatPanel.prototype.addStroke = function(container)
 		
 		if (mxUtils.getValue(ss.style, mxConstants.STYLE_DASHED, null) == '1')
 		{
-			if (mxUtils.getValue(ss.style, mxConstants.STYLE_DASH_PATTERN, null) == null)
+			if (mxUtils.getValue(ss.style, mxConstants.STYLE_DASH_PATTERN, null) == null ||
+				mxUtils.getValue(ss.style, mxConstants.STYLE_DASH_PATTERN, '').substring(0, 2) != '1 ')
 			{
 				solid.style.borderBottom = '1px dashed ' + this.defaultStrokeColor;
 			}
@@ -5493,7 +5501,8 @@ StyleFormatPanel.prototype.addStroke = function(container)
 
 		mxUtils.setOpacity(edgeStyle, (ss.style.shape == 'arrow') ? 30 : 100);			
 		
-		if (ss.style.shape != 'connector' && ss.style.shape != 'flexArrow' && ss.style.shape != 'filledEdge')
+		if (ss.style.shape != 'connector' && ss.style.shape != 'flexArrow' &&
+			ss.style.shape != 'filledEdge' && ss.style.shape != 'wire')
 		{
 			mxUtils.setOpacity(lineStart, 30);
 			mxUtils.setOpacity(lineEnd, 30);
@@ -6476,24 +6485,19 @@ DiagramFormatPanel.prototype.addView = function(div)
 	
 	if (graph.isEnabled())
 	{
-		var bg = null;
-
 		if (this.showBackgroundImageOption)
 		{
 			var bg = this.createOption(mxResources.get('background'), function()
 			{
-				return (graph.background != mxConstants.NONE &&
-					graph.background != null) ||
-					graph.backgroundImage != null;
+				return graph.backgroundImage != null;
 			}, function(checked)
 			{
-				if (checked)
+				if (!checked)
 				{
-					graph.model.execute(new ChangePageSetup(ui, '#ffffff'));
-				}
-				else
-				{
-					graph.model.execute(new ChangePageSetup(ui));
+					var change = new ChangePageSetup(ui, null, null);
+					change.ignoreColor = true;
+
+					graph.model.execute(change);
 				}
 			},
 			{
@@ -6501,12 +6505,9 @@ DiagramFormatPanel.prototype.addView = function(div)
 				{
 					this.listener = function()
 					{
-						apply((graph.background != mxConstants.NONE &&
-							graph.background != null) ||
-							graph.backgroundImage != null);
+						apply(graph.backgroundImage != null);
 					};
 					
-					ui.addListener('backgroundColorChanged', this.listener);
 					ui.addListener('backgroundImageChanged', this.listener);
 				},
 				destroy: function()
@@ -6515,6 +6516,8 @@ DiagramFormatPanel.prototype.addView = function(div)
 				}
 			});
 
+			bg.getElementsByTagName('input')[0].style.visibility = graph.backgroundImage != null ? 'visible' : 'hidden';
+
 			var label = bg.getElementsByTagName('div')[0];
 			label.style.display = 'inline-block';
 			label.style.textOverflow = 'ellipsis';
@@ -6542,38 +6545,94 @@ DiagramFormatPanel.prototype.addView = function(div)
 			btn.style.maxWidth = '110px';
 			
 			bg.appendChild(btn);
+			div.appendChild(bg);
 		}
-		else
+
+		var bgColor = this.createColorOption(mxResources.get('backgroundColor'), function()
 		{
-			bg = this.createColorOption(mxResources.get('background'), function()
-			{
-				return graph.background;
-			}, function(color)
+			return graph.background;
+		}, function(color)
+		{
+			var change = new ChangePageSetup(ui, color);
+			change.ignoreImage = true;
+
+			graph.model.execute(change);
+		}, '#ffffff');
+
+		bgColor.style.padding = '5px 0 1px 0';
+		div.appendChild(bgColor);
+
+		var option = this.createOption(mxResources.get('shadow'), function()
+		{
+			return graph.shadowVisible;
+		}, function(checked)
+		{
+			var change = new ChangePageSetup(ui);
+			change.ignoreColor = true;
+			change.ignoreImage = true;
+			change.shadowVisible = checked;
+			
+			graph.model.execute(change);
+		},
+		{
+			install: function(apply)
 			{
-				var change = new ChangePageSetup(ui, color);
-				change.ignoreImage = color != null &&
-					color != mxConstants.NONE;
+				this.listener = function()
+				{
+					apply(graph.shadowVisible);
+				};
 				
-				graph.model.execute(change);
-			}, '#ffffff',
+				ui.addListener('shadowVisibleChanged', this.listener);
+			},
+			destroy: function()
 			{
-				install: function(apply)
-				{
-					this.listener = function()
-					{
-						apply(graph.background);
-					};
-					
-					ui.addListener('backgroundColorChanged', this.listener);
-				},
-				destroy: function()
-				{
-					ui.removeListener(this.listener);
-				}
-			});
+				ui.removeListener(this.listener);
+			}
+		});
+		
+		if (!Editor.enableShadowOption)
+		{
+			option.getElementsByTagName('input')[0].setAttribute('disabled', 'disabled');
+			mxUtils.setOpacity(option, 60);
 		}
+
+		option.style.display = 'inline-flex';
+		option.style.width = '100px';
+		option.style.maxWidth = '100px';
+		option.style.marginRight = '4px';
+		div.appendChild(option);
+
+		var sketchOption = this.createOption(mxResources.get('sketch'), function()
+		{
+			return Editor.sketchMode;
+		}, function(checked)
+		{
+			graph.updateCellStyles({'sketch': (checked) ? '1' : null,
+				'curveFitting': (checked) ? Editor.sketchDefaultCurveFitting : null,
+				'jiggle': (checked) ? Editor.sketchDefaultJiggle : null},
+				graph.getVerticesAndEdges());
+			ui.setSketchMode(checked);
+		},
+		{
+			install: function(apply)
+			{
+				this.listener = function()
+				{
+					apply(Editor.sketchMode);
+				};
+				
+				ui.addListener('sketchModeChanged', this.listener);
+			},
+			destroy: function()
+			{
+				ui.removeListener(this.listener);
+			}
+		});
 		
-		div.appendChild(bg);
+		sketchOption.style.display = 'inline-flex';
+		sketchOption.style.width = '104px';
+		sketchOption.style.maxWidth = '104px';
+		div.appendChild(sketchOption);
 	}
 	
 	return div;

+ 15 - 3
src/main/webapp/js/grapheditor/Graph.js

@@ -477,10 +477,11 @@ Graph = function(container, model, renderHint, stylesheet, themes, standalone)
 			    			
 			    			if (handler != null && handler.bends != null && handler.bends.length > 0)
 			    			{
+								handler.redrawHandles();
 			    				var handle = handler.getHandleForEvent(start.event, true);
 			    				var edgeStyle = this.view.getEdgeStyle(state);
 			    				var entity = edgeStyle == mxEdgeStyle.EntityRelation;
-			    				
+								
 			    				// Handles special case where label was clicked on unselected edge in which
 			    				// case the label will be moved regardless of the handle that is returned
 			    				if (!start.selected && start.handle == mxEvent.LABEL_HANDLE)
@@ -498,10 +499,11 @@ Graph = function(container, model, renderHint, stylesheet, themes, standalone)
 				    					if (!entity && handle != mxEvent.LABEL_HANDLE)
 				    					{
 					    					var pts = state.absolutePoints;
-				    						
+											
 					    					// Default case where handles are at corner points handles
 					    					// drag of corner as drag of existing point
 					    					if (pts != null && ((edgeStyle == null && handle == null) ||
+					    						edgeStyle == mxEdgeStyle.SegmentConnector ||
 					    						edgeStyle == mxEdgeStyle.OrthConnector))
 					    					{
 					    						// Does not use handles if they were not initially visible
@@ -2313,11 +2315,21 @@ Graph.prototype.init = function(container)
 			mxUtils.getValue(state.style, 'lineShape', null) != '1' &&
 			(this.model.isVertex(state.cell) ||
 			mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'arrow' ||
+			mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'wire' ||
 			mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'filledEdge' ||
 			mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'flexArrow' ||
 			mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null) == 'mxgraph.arrows2.wedgeArrow');
 	};
 	
+	/**
+	 * Returns information about the current selection.
+	 */
+	Graph.prototype.isGradientState = function(state)
+	{
+		return this.isFillState(state) && mxUtils.getValue(state.style,
+			mxConstants.STYLE_SHAPE, null) != 'wire';
+	};
+	
 	/**
 	 * Returns information about the current selection.
 	 */
@@ -2366,7 +2378,7 @@ Graph.prototype.init = function(container)
 		var shape = mxUtils.getValue(state.style, mxConstants.STYLE_SHAPE, null);
 		var curved = mxUtils.getValue(state.style, mxConstants.STYLE_CURVED, false);
 		
-		return !curved && (shape == 'connector' || shape == 'filledEdge');
+		return !curved && (shape == 'connector' || shape == 'filledEdge' || shape == 'wire');
 	};
 	
 	/**

+ 32 - 12
src/main/webapp/js/grapheditor/Menus.js

@@ -594,6 +594,7 @@ Menus.prototype.get = function(name)
 Menus.prototype.addSubmenu = function(name, menu, parent, label)
 {
 	var entry = this.get(name);
+	var submenu = null;
 	
 	if (entry != null)
 	{
@@ -601,10 +602,13 @@ Menus.prototype.addSubmenu = function(name, menu, parent, label)
 	
 		if (menu.showDisabled || enabled)
 		{
-			var submenu = menu.addItem(label || mxResources.get(name), null, null, parent, null, enabled);
+			submenu = menu.addItem(label || mxResources.get(name),
+				null, null, parent, null, enabled);
 			this.addMenu(name, menu, submenu);
 		}
 	}
+
+	return submenu;
 };
 
 /**
@@ -1422,10 +1426,7 @@ Menus.prototype.addMenuItem = function(menu, key, parent, trigger, sprite, label
 			menu.addCheckmark(item, Editor.checkmarkImage);
 		}
 
-		if (!menu.hideShortcuts)
-		{
-			this.addShortcut(item, action);
-		}
+		this.addShortcut(item, action, menu.hideShortcuts);
 		
 		return item;
 	}
@@ -1436,15 +1437,22 @@ Menus.prototype.addMenuItem = function(menu, key, parent, trigger, sprite, label
 /**
  * Adds a checkmark to the given menuitem.
  */
-Menus.prototype.addShortcut = function(item, action)
+Menus.prototype.addShortcut = function(item, action, asTooltip)
 {
 	if (action.shortcut != null)
 	{
-		var td = item.firstChild.nextSibling.nextSibling;
-		var span = document.createElement('span');
-		span.style.color = 'gray';
-		mxUtils.write(span, action.shortcut);
-		td.appendChild(span);
+		if (asTooltip)
+		{
+			item.setAttribute('title', action.shortcut);
+		}
+		else
+		{
+			var td = item.firstChild.nextSibling.nextSibling;	
+			var span = document.createElement('span');
+			span.style.color = 'gray';
+			mxUtils.write(span, action.shortcut);
+			td.appendChild(span);
+		}
 	}
 };
 
@@ -1481,7 +1489,11 @@ Menus.prototype.createPopupMenu = function(menu, cell, evt)
  */
 Menus.prototype.addPopupMenuItems = function(menu, cell, evt)
 {
-	this.addPopupMenuHistoryItems(menu, cell, evt);
+	if (this.isShowHistoryItems())
+	{
+		this.addPopupMenuHistoryItems(menu, cell, evt);	
+	}
+
 	this.addPopupMenuEditItems(menu, cell, evt);
 
 	if (this.isShowStyleItems())
@@ -1498,6 +1510,14 @@ Menus.prototype.addPopupMenuItems = function(menu, cell, evt)
 	this.addPopupMenuSelectionItems(menu, cell, evt);
 };
 
+/**
+ * Creates the keyboard event handler for the current graph and history.
+ */
+Menus.prototype.isShowHistoryItems = function()
+{
+	return true;
+};
+
 /**
  * Creates the keyboard event handler for the current graph and history.
  */

+ 20 - 0
src/main/webapp/js/grapheditor/Shapes.js

@@ -448,6 +448,26 @@
 
 	mxCellRenderer.registerShape('isoRectangle', IsoRectangleShape);
 	
+	// Wire Shape
+	function WireShape()
+	{
+		mxConnector.call(this);
+	};
+
+	mxUtils.extend(WireShape, mxConnector);
+
+	WireShape.prototype.paintEdgeShape = function(c, pts)
+	{
+		c.save();
+		c.setDashed(false);
+		mxConnector.prototype.paintEdgeShape.apply(this, [c, pts]);
+		c.restore();
+		c.setStrokeColor(this.fill);
+		mxPolyline.prototype.paintEdgeShape.apply(this, [c, pts]);
+	};
+
+	mxCellRenderer.registerShape('wire', WireShape);
+	
 	// Cube Shape, supports size style
 	function WaypointShape()
 	{

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 106 - 32
src/main/webapp/js/grapheditor/Sidebar.js


+ 9 - 2
src/main/webapp/js/grapheditor/Toolbar.js

@@ -84,9 +84,10 @@ Toolbar.prototype.init = function()
 	}
 	
 	// Updates the label if the scale changes
-	this.updateZoom = mxUtils.bind(this, function()
+	this.updateZoom = mxUtils.bind(this, function(sender, evt, f)
 	{
-		viewMenu.innerHTML = Math.round(this.editorUi.editor.graph.view.scale * 100) + '%';
+		f = (f != null) ? f : 1;
+		viewMenu.innerHTML = Math.round(this.editorUi.editor.graph.view.scale * 100 * f) + '%';
 		this.appendDropDownImageHtml(viewMenu);
 		
 		if (EditorUi.compactUi)
@@ -99,6 +100,12 @@ Toolbar.prototype.init = function()
 	this.editorUi.editor.graph.view.addListener(mxEvent.EVENT_SCALE, this.updateZoom);
 	this.editorUi.editor.addListener('resetGraphView', this.updateZoom);
 
+	// Zoom Preview
+	this.editorUi.editor.graph.addListener('zoomPreview', mxUtils.bind(this, function(sender, evt)
+	{
+		this.updateZoom(sender, evt, evt.getProperty('factor'));
+	}));
+
 	var elts = this.addItems(['-', 'undo', 'redo']);
 	elts[1].setAttribute('title', mxResources.get('undo') + ' (' + this.editorUi.actions.get('undo').shortcut + ')');
 	elts[2].setAttribute('title', mxResources.get('redo') + ' (' + this.editorUi.actions.get('redo').shortcut + ')');

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2899 - 2884
src/main/webapp/js/integrate.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1831 - 1825
src/main/webapp/js/viewer-static.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1831 - 1825
src/main/webapp/js/viewer.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 84 - 84
src/main/webapp/mxgraph/mxClient.js


+ 556 - 0
src/main/webapp/plugins/nextcloud.js

@@ -0,0 +1,556 @@
+/**
+ * Plugin for embed mode in Nextcloud
+ */
+Draw.loadPlugin(function(ui)
+{
+    var loadDescriptor = null;
+    var ncUser = null;
+    
+    mxEvent.addListener(window, 'message', mxUtils.bind(this, function(evt)
+    {
+        var data = evt.data;
+
+        try
+        {
+            data = JSON.parse(data);
+            
+            if (data.action == 'load')
+            {
+                if (data.desc != null)
+                {
+                    loadDescriptor = data.desc;
+                }
+
+                if (data.disableAutoSave)
+                {
+                    ui.editor.setAutosave(false);
+                }
+            }
+        }
+        catch (e)
+        {
+            // Ignore
+        }
+    }));
+
+    ui.getCurrentUser = function()
+	{
+		if (ncUser == null)
+		{
+			ui.remoteInvoke('getCurrentUser', null, null, function(user)
+			{
+				ncUser = new DrawioUser(user.uid, null, user.displayName);
+			}, function()
+			{
+				//ignore such that next call we retry
+			});
+			
+			//Return a dummy user until we have the actual user in order for UI to be populated
+			return new DrawioUser(Date.now(), null, 'Anonymous');
+		}
+		
+		return ncUser;
+	};
+
+    //======================== Revisions ========================
+	
+	ui.isRevisionHistoryEnabled = function()
+	{
+		return true;
+	};
+	
+	ui.isRevisionHistorySupported = function()
+	{
+		return true;
+	};
+
+	/**
+	 * Get revisions of current file
+	 */
+	ui.getRevisions = function(success, error)
+	{
+        var path = ui.getCurrentFile().desc.path;
+
+		function getXml(success, error)
+		{
+			ui.remoteInvoke('loadFileVersion', [path, this.revId], null, success, error);
+		};
+		
+		function restoreFn(xml)
+		{
+			if (ui.spinner.spin(document.body, mxResources.get('restoring')))
+			{
+				ui.replaceFileData(xml);
+				ui.spinner.stop();
+				ui.hideDialog();
+			}
+		};
+		
+		ui.remoteInvoke('getFileRevisions', [path], null, function(revisions)
+		{
+            revisions.sort(function(a, b)
+            {
+                return a.timestamp - b.timestamp;
+            });
+
+			//convert to editor format and add getXml function
+			var revs = [];
+			
+			for (var i = 0; i < revisions.length; i++)
+			{
+				var rev = revisions[i];
+                rev.modifiedDate = rev.timestamp * 1000;
+				rev.getXml = mxUtils.bind(rev, getXml);
+				revs.push(rev);
+			}
+			
+			success(revs, restoreFn);
+		}, error);
+	};
+	
+    //============= Embed File with real-time collab support =================
+    // Use optimistic sync since we cannot save file properties/metadata so far
+    
+    /**
+     * Shorter autosave delay for optimistic sync.
+     */
+    EmbedFile.prototype.autosaveDelay = 500;
+
+    /**
+     * Delay for last save in ms.
+     */
+    EmbedFile.prototype.saveDelay = 0;
+    
+    /**
+     * 
+     */
+    EmbedFile.prototype.isConflict = function(err)
+    {
+        return err != null && err.status == 409;
+    };
+
+    /**
+     * Returns the current user.
+     */
+    EmbedFile.prototype.getCurrentUser = function()
+    {
+        return ui.getCurrentUser();
+    };
+
+    EmbedFile.prototype.isRealtimeSupported = function()
+    {
+        return true;
+    };
+    
+    /**
+     * 
+     */
+    EmbedFile.prototype.save = function(revision, success, error, unloading, overwrite)
+    {
+        this.saveStarted = true;
+        
+        DrawioFile.prototype.save.apply(this, [revision, mxUtils.bind(this, function()
+        {
+            this.saveFile(null, revision, success, error, unloading, overwrite);
+            this.saveStarted = false;
+        }), error, unloading, overwrite]);
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.setModified = function(value)
+    {
+        DrawioFile.prototype.setModified.apply(this, arguments);
+        
+        //Set editor modified also to prevent accidental closure or exiting without saving  
+        ui.editor.modified = value;
+    };
+    
+    /**
+     * 
+     */
+    EmbedFile.prototype.saveFile = function(title, revision, success, error, unloading, overwrite)
+    {
+        EditorUi.debug('EmbedFile.saveFile', [this], 'saving', this.savingFile);
+
+        try
+        {
+            if (!this.isEditable())
+            {
+                if (success != null)
+                {
+                    success();
+                }
+            }
+            else if (!this.savingFile)
+            {
+                // Sets shadow modified state during save
+                this.savingFileTime = new Date();
+                this.setShadowModified(false);
+                this.savingFile = true;
+
+
+                var doSave = mxUtils.bind(this, function()
+                {
+                    try
+                    {
+                        var lastDesc = this.desc;
+                        var savedData = this.getData();
+                        var etag = this.getCurrentEtag();
+                        
+                        if (this.sync != null)
+                        {
+                            this.sync.fileSaving();
+                        }
+
+                        ui.remoteInvoke('saveFile', [this.desc.path, savedData, etag], null, mxUtils.bind(this, function(resp)
+                        {
+                            try
+                            {
+                                // Checks for changes during save
+                                this.setModified(this.getShadowModified());
+                                this.savingFile = false;
+                                this.desc = Object.assign({}, this.desc); // Clone the object
+                                Object.assign(this.desc, resp); // Assign the new values
+            
+                                this.fileSaved(savedData, lastDesc, mxUtils.bind(this, function()
+                                {
+                                    this.contentChanged();
+                                    
+                                    if (success != null)
+                                    {
+                                        success();
+                                    }
+                                }), error);
+                            }
+                            catch (e)
+                            {
+                                this.savingFile = false;
+                                
+                                if (error != null)
+                                {
+                                    error(e);
+                                }
+                                else
+                                {
+                                    throw e;
+                                }
+                            }
+                        }),
+                        mxUtils.bind(this, function(err)
+                        {
+                            try
+                            {
+                                this.savingFile = false;
+                            
+                                if (this.isConflict(err))
+                                {
+                                    this.inConflictState = true;
+                                    
+                                    if (this.sync != null)
+                                    {
+                                        this.savingFile = true;
+                                        
+                                        this.sync.fileConflict(null, mxUtils.bind(this, function()
+                                        {
+                                            // Adds random cool-off
+                                            var delay = 100 + Math.random() * 500;
+                                            window.setTimeout(mxUtils.bind(this, function()
+                                            {
+                                                this.updateFileData();
+                                                doSave();
+                                            }), delay);
+
+                                            EditorUi.debug('EmbedFile.saveFile.conflict',
+                                                [this], 'err', err, 'delay', delay);
+                                        }), mxUtils.bind(this, function()
+                                        {
+                                            this.savingFile = false;
+                                            
+                                            if (error != null)
+                                            {
+                                                error();
+                                            }
+                                        }));
+                                    }
+                                    else if (error != null)
+                                    {
+                                        error();
+                                    }
+                                }
+                                else if (error != null)
+                                {
+                                    error(err);
+                                }
+                            }
+                            catch (e)
+                            {
+                                this.savingFile = false;
+                                
+                                if (error != null)
+                                {
+                                    error(e);
+                                }
+                                else
+                                {
+                                    throw e;
+                                }
+                            }
+                        }));
+                    }
+                    catch (e)
+                    {
+                        this.savingFile = false;
+                        
+                        if (error != null)
+                        {
+                            error(e);
+                        }
+                        else
+                        {
+                            throw e;
+                        }
+                    }
+                });
+                
+                doSave();
+            }
+        }
+        catch (e)
+        {
+            if (error != null)
+            {
+                error(e);
+            }
+            else
+            {
+                throw e;
+            }
+        }
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.getTitle = function()
+    {
+        return this.desc.name;
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.getHash = function()
+    {
+        return 'E' + this.getId();
+    };
+
+    /**
+     * Overridden to enable the autosave option in the document properties dialog.
+     */
+    EmbedFile.prototype.isAutosaveOptional = function()
+    {
+        return true;
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.getId = function()
+    {
+        return this.desc.id;
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.isSyncSupported = function()
+    {
+        return true;
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.isRevisionHistorySupported = function()
+    {
+        return true;
+    };
+
+    EmbedFile.prototype.isOptimisticSync = function()
+    {
+        return true;
+    };
+
+    /**
+     * Enabling fast syncin
+     */
+    EmbedFile.prototype.isSyncEnabled = function()
+    {
+        return true;
+    };
+
+    OneDriveFile.prototype.getSize = function()
+    {
+        return this.desc.size;
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.getLatestVersion = function(success, error)
+    {
+        ui.remoteInvoke('loadFile', [this.desc.path], null, mxUtils.bind(this, function(data)
+        {
+            var xml = data.xml;
+            delete data.xml;
+            success(new EmbedFile(ui, xml, data));
+        }), error);
+    };
+
+    /**
+     * Gets the channel ID from the given descriptor.
+     */
+    EmbedFile.prototype.getChannelId = function()
+    {
+        return 'C-' + DrawioFile.prototype.getChannelId.apply(this, arguments);
+    };
+
+    OneDriveFile.prototype.getHash = function()
+    {
+        return 'C' + encodeURIComponent(this.getId());
+    };
+
+    /**
+     * Using MD5 of create timestamp and user ID as crypto key.
+     */
+    EmbedFile.prototype.getChannelKey = function()
+    {
+        if (typeof CryptoJS !== 'undefined')
+        {
+            return CryptoJS.MD5((this.desc.created || this.desc.id) + this.desc.owner).toString();
+        }
+        
+        return null;
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.getLastModifiedDate = function()
+    {
+        return new Date(this.desc.mtime * 1000);
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.getDescriptor = function()
+    {
+        return this.desc;
+    };
+
+    /**
+     * Updates the descriptor of this file with the one from the given file.
+     */
+    EmbedFile.prototype.setDescriptor = function(desc)
+    {
+        this.desc = desc;
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.getDescriptorEtag = function(desc)
+    {
+        return desc.etag;
+    };
+
+    /**
+     *
+     */
+    EmbedFile.prototype.setDescriptorEtag = function(desc, etag)
+    {
+        desc.etag = etag;
+    };
+
+    /**
+     * 
+     */
+    EmbedFile.prototype.loadDescriptor = function(success, error)
+    {
+        ui.remoteInvoke('getFileInfo', [this.desc.path], null, success, error);
+    };
+    
+    var allowAutoSave = true;
+    
+    EmbedFile.prototype.isAutosaveNow = function(success, error)
+    {
+        return allowAutoSave;
+    };
+    
+    //Ensure saving is via the file
+    ui.actions.get('save').funct = function(exit)
+    {
+        if (ui.editor.graph.isEditing())
+        {
+            ui.editor.graph.stopEditing();
+        }
+
+        var curFile = ui.getCurrentFile();
+        
+        if (exit)
+        {
+            allowAutoSave = false;
+        }
+
+        function doActions()
+        {
+            if (exit)
+            {
+                ui.actions.get('exit').funct();
+            }
+        };
+        
+        function doSave()
+        {
+            if (curFile.saveStarted || curFile.savingFile)
+            {
+                setTimeout(doSave, 100);
+                return;
+            }
+            
+            if (curFile.isModified())
+            {
+                ui.saveFile(null, doActions);
+            }
+            else
+            {
+                doActions();
+            }
+        };
+        
+        doSave();
+    };
+
+    //Add file opening here (or it should be for all in EditorUi?)
+    var origInstallMessageHandler =  ui.installMessageHandler;
+    
+    ui.installMessageHandler = function(callback)
+    {
+        origInstallMessageHandler.call(this, function()
+        {
+            callback.apply(this, arguments);
+            
+            var file = ui.getCurrentFile();
+            file.setDescriptor(loadDescriptor || {});
+            ui.fileLoaded(file, true);
+        });
+    }
+    
+    ui.editor.setModified = function()
+    {
+        //Cancel set modified of the editor and use the file's one
+    };
+});

+ 3 - 9
src/main/webapp/plugins/props.js

@@ -22,7 +22,7 @@ Draw.loadPlugin(function(ui) {
 
 		var iiw = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
 		
-		var dataWindow = new mxWindow('Data', div, iiw - 320, 60, 200, 130, true, true);
+		var dataWindow = new mxWindow('Data', div, iiw - 320, 60, 240, 220, true, true);
 		dataWindow.destroyOnClose = false;
 		dataWindow.setMaximizable(false);
 		dataWindow.setResizable(true);
@@ -69,11 +69,11 @@ Draw.loadPlugin(function(ui) {
 
 		if (mxEvent.isShiftDown(evt))
 		{
-			console.log(result);
+			console.log(JSON.stringify(result, null, '  '));
 		}
 		else
 		{
-			console.log(JSON.stringify(result, null, '  '));
+			console.log(result);
 		}
 	};
 
@@ -82,12 +82,6 @@ Draw.loadPlugin(function(ui) {
 	 */
 	function cellClicked(cell)
 	{
-		// Forces focusout in IE
-		if (!ui.editor.isChromelessView())
-		{
-			graph.container.focus();
-		}
-
 		// Gets the selection cell
 		if (cell == null)
 		{

+ 2 - 9
src/main/webapp/plugins/trees/trees.js

@@ -1246,7 +1246,7 @@ Draw.loadPlugin(function(ui)
 	// Adds sidebar entries
 	var sb = ui.sidebar;
 	
-    sb.addPalette('trees', 'Trees', true, function(content)
+    sb.addPalette('trees', 'Trees', false, function(content)
     {
         (function()
         {
@@ -1432,11 +1432,4 @@ Draw.loadPlugin(function(ui)
 			content.appendChild(sb.createVertexTemplateFromCells([edge, edge2, cell, cell2], 220, 60, 'Sub Sections'));
         })();
     });
-    
-    // Collapses default sidebar entry and inserts this before
-    var c = ui.sidebar.container;
-    var general = c.getElementsByTagName('a')[0];
-    general.click();
-    c.insertBefore(c.lastChild.previousSibling, general);
-    c.insertBefore(c.lastChild, general);
-});
+});

+ 1 - 1
src/main/webapp/resources/dia_ar.txt

@@ -101,7 +101,7 @@ chatWindowTitle=‫دردشة‬
 chooseAnOption=‫اختر خيارا‬
 chromeApp=‫تطبيق Chrome‬
 collaborativeEditingNotice=‫ملاحظات مهمة عن مشاركة التعديل‬
-compare=‫قارن‬
+compare=‫يقارن‬
 compressed=‫مضغوط‬
 commitMessage=‫أكد علي تسجيل الرسالة‬
 configLinkWarn=‫هذة الوصلة تقوم بتغيرات علي draw.io . اضغط علي موافق لو كنت تثق فيمن ارسله اليك‬

+ 33 - 33
src/main/webapp/resources/dia_ca.txt

@@ -3,7 +3,7 @@
 about=Quant al
 aboutDrawio=Quant al draw.io
 accessDenied=Accés denegat
-accounts=Accounts
+accounts=Comptes
 action=Acció
 actualSize=Mida real
 add=Afegeix
@@ -15,7 +15,7 @@ addLayer=Afegeix una capa
 addProperty=Afegeix una propietat
 address=Adreça
 addToExistingDrawing=Afegeix al dibuix actual
-addToScratchpad=Add to Scratchpad
+addToScratchpad=Afegeix al Bloc de notes
 addWaypoint=Afegeix una coordenada
 adjustTo=Ajustar a
 advanced=Avançat
@@ -37,7 +37,7 @@ allChangesSavedInDrive=S'han desat tots els canvis a Drive
 allowPopups=Permet els elements emergents per evitar aquest quadre de diàleg.
 allowRelativeUrl=Permet URL relatiu
 alreadyConnected=Els nodes ja estan connectats
-appearance=Appearance
+appearance=Aparença
 apply=Aplica
 archiMate21=ArchiMate 2.1
 arrange=Organitza
@@ -78,7 +78,7 @@ bottomAlign=Alineació inferior
 bottomLeft=Inferior esquerra
 bottomRight=Inferior dreta
 bpmn=BPMN
-bringForward=Envia cap endavant
+bringForward=Posa-ho endavant
 browser=Navegador
 bulletedList=Llista de pics
 business=Professional
@@ -114,7 +114,7 @@ diagramHtmlDesc=Fitxer HTML
 diagramPngDesc=Imatge de mapa de bits editable
 diagramSvgDesc=Imatge vectorial editable
 didYouMeanToExportToPdf=Voleu exportar-ho a PDF?
-disabled=Disabled
+disabled=Inhabilitat
 draftFound=S'ha trobat un esborrany per a '{1}'. Carrega'l a l'editor o descarta'l per continuar.
 draftRevisionMismatch=Hi ha una versió diferent d'aquest diagrama en un esborrany compartit d'aquesta pàgina. Editeu el diagrama des de l'esborrany per assegurar que esteu treballant amb la darrera versió.
 selectDraft=Seleccioneu un esborrany per continuar editant-lo:
@@ -131,7 +131,7 @@ clipart=Imatges predissenyades
 close=Tanca
 closingFile=S'està tancant el fitxer
 realtimeCollaboration=Col·laboració en temps real
-collaborate=Collaborate
+collaborate=Col·laborar
 collaborator=Col·laborador
 collaborators=Col·laboradors
 collapse=Minimitza
@@ -523,7 +523,7 @@ noPreview=No hi ha vista prèvia
 noResponse=El servidor no respon
 noResultsFor=No s'ha trobat cap resultat per {1}
 noRevisions=Sense revisions
-noSearchResults=La s'ha trobat cap resultat
+noSearchResults=No s'ha trobat cap resultat
 noPageContentOrNotSaved=No s'han trobat enllaços a la pàgina o encara no s'ha desat
 normal=Normal
 north=Nord
@@ -568,7 +568,7 @@ pageContent=Contingut de la pàgina
 pageNotFound=No s'ha trobat la pàgina
 pageWithNumber=Pàgina-{1}
 pages=Pàgines
-pageTabs=Page Tabs
+pageTabs=Pestanyes de la pàgina
 pageView=Vista de pàgina
 pageSetup=Configuració de la pàgina
 pageScale=Escala de la pàgina
@@ -617,7 +617,7 @@ recentlyUpdated=Actualitzat recentment
 recentlyViewed=Visitat recentment
 rectangle=Rectangle
 redirectToNewApp=Aquest fitxer va ser creat o modificat en una versió posterior d'aquesta aplicació. Ara hi sereu redirigits.
-realtimeTimeout=Sembla que heu fet canvis mentre s'estava desconnectat. Malauradament, aquests canvis ara no es poden desar.
+realtimeTimeout=Sembla que heu fet canvis mentre estàveu desconnectat. Malauradament, aquests canvis ara no es poden desar.
 redo=Refés
 refresh=Refresca
 regularExpression=Expressió normal
@@ -670,7 +670,7 @@ saveLibrary403=Permisos insuficients per editar aquesta biblioteca
 saveLibrary500=Hi ha hagut un error desant la biblioteca
 saveLibraryReadOnly=No s'ha pogut desar la biblioteca mentre el mode de només lectura està actiu
 saving=S'està desant
-scratchpad=Scratchpad
+scratchpad=Bloc de notes
 scrollbars=Barres de desplaçament
 search=Cerca
 searchShapes=Cerca formes
@@ -684,14 +684,14 @@ selectFont=Selecciona una font
 selectNone=No seleccionis res
 selectTemplate=Selecciona una plantilla
 selectVertices=Selecciona els vèrtexs
-sendBackward=Envia cap enrere
+sendBackward=Posa-ho enrere
 sendMessage=Envia
 sendYourFeedback=Envieu els vostres comentaris
 serviceUnavailableOrBlocked=El servei no està disponible o està bloquejat
 sessionExpired=La sessió ha caducat. Refresqueu la finestra del navegador.
 sessionTimeoutOnSave=La sessió ha caducat i us heu desconnectat de Google Drive. Premeu "D'acord" per accedir-hi i desar.
 setAsDefaultStyle=Estableix com estil predeterminat
-settings=Settings
+settings=Configuració
 shadow=Ombra
 shape=Forma
 shapes=Formes
@@ -699,7 +699,7 @@ share=Comparteix
 shareCursor=Comparteix el cursor del ratolí
 shareLink=Enllaç per a l'edició compartida
 sharingAvailable=Compartició disponible per a fitxers de Google Drive i OneDrive.
-moveItToGoogleDrive=You'll need to move "{1}" to Google Drive before you can collaborate.
+moveItToGoogleDrive=Haureu de moure "{1}" a Google Drive abans de poder col·laborar.
 sharp=Angulós
 show=Mostra
 showRemoteCursors=Mostra els cursors del ratolí remot
@@ -748,8 +748,8 @@ theme=Tema
 timeout=Temps límit
 title=Títol
 to=a
-toBack=Envia darrera de tot
-toFront=Envia davant de tot
+toBack=Posa-ho al darrere
+toFront=Posa-ho al davant
 tooLargeUseDownload=Massa gran, baixeu-lo.
 toolbar=Barra d'eines
 tooltips=Consells d'eines
@@ -769,7 +769,7 @@ uml=UML
 underline=Subratlla
 undo=Desfés
 ungroup=Desagrupa
-unmerge=Des-fusiona
+unmerge=Divideix
 unsavedChanges=Canvis no desats
 unsavedChangesClickHereToSave=Canvis no desats. Clica aquí per desar.
 untitled=Sense títol
@@ -796,7 +796,7 @@ voiceAssistant=Assistent de veu (beta)
 warning=Atenció
 waypoints=Coordenades
 west=Oest
-where=Where
+where=On
 width=Amplada
 wiki=Wiki
 wordWrap=Ajust de línia
@@ -854,7 +854,7 @@ errorAuthOD=S'ha produït un error en autenticar-se a OneDrive
 officeMainHeader=Afegeix esquemes draw.io al document.
 officeStepsHeader=Aquest complement realitza els passos següents:
 officeStep1=Es connecta a Microsoft OneDrive, Google Drive o al vostre dispositiu.
-officeStep2=Seleccioneu un diagrama de draw.io:
+officeStep2=Seleccioneu un diagrama de draw.io.
 officeStep3=Insereix el diagrama al document.
 officeAuthPopupInfo=Completeu l'autenticació a la finestra emergent.
 officeSelDiag=Seleccioneu un diagrama de draw.io
@@ -955,9 +955,9 @@ confAAllDiagInPageDone=Tots els diagrames {1} de la pàgina "{2}" s'han processa
 confAPartialDiagDone={1} de {2} diagrames {3} de la pàgina "{4}" s'han processat correctament.
 confAUpdatePageFailed=No s'ha pogut actualitzar la pàgina "{1}".
 confANoDiagFoundInPage=No s'han trobat diagrames {1} a la pàgina "{2}".
-confAFetchPageFailed=S'ha produït un error al obtenir la pàgina.
+confAFetchPageFailed=S'ha produït un error en obtenir la pàgina.
 confANoDiagFound=No s'han trobat diagrames {1}. Procés acabat.
-confASearchFailed=La cerca de diagrames {1} ha fallat. Siusplau, intenta-ho més tard.
+confASearchFailed=La cerca de diagrames {1} ha fallat. Si us plau, intenteu-ho més tard.
 confAGliffyDiagFound=Diagrama {2} "{1}" trobat. Important
 confAGliffyDiagImported=Diagrama {2} "{1}" importat correctament.
 confASavingImpGliffyFailed=No s'ha pogut desar el diagrama {2} importat "{1}".
@@ -971,7 +971,7 @@ confADelDiagLnkFailed=No s'ha pogut suprimir l'enllaç del diagrama "{1}".
 confAUnexpErrProcessPage=Error inesperat durant el processament de la pàgina amb l'identificador: {1}
 confADiagFoundIndex=S'ha trobat el diagrama "{1}". Indexant
 confADiagIndexSucc=El diagrama "{1}" s'ha indexat correctament.
-confAIndexDiagFailed=Ha fallat l'indexació del diagrama "{1}".
+confAIndexDiagFailed=Ha fallat la indexació del diagrama "{1}".
 confASkipDiagOtherPage=S'ha omès "{1}" perquè pertany a una altra pàgina!
 confADiagUptoDate=El diagrama "{1}" està actualitzat.
 confACheckPagesWDraw=Comprovant pàgines amb diagrames draw.io.
@@ -1009,9 +1009,9 @@ millimeters=Mil·límetres
 confEditDraftDelOrExt=Aquest diagrama es troba en una pàgina d'esborrany, s'ha eliminat de la pàgina o està editat externament. Es desarà com a una versió nova adjunta i pot ser que no es reflecteixi a la pàgina.
 confDiagEditedExt=El diagrama s'edita en una altra sessió. Es desarà com a una nova versió adjunta, però la pàgina mostrarà les modificacions d'altres sessions.
 macroNotFound=No s'ha trobat la macro
-confAInvalidPageIdsFormat=Format de fitxer d'IDs de pàgina incorrectes
-confACollectingCurPages=Recopilant pàgines actuals
-confABuildingPagesMap=Creant mapeig de pàgines
+confAInvalidPageIdsFormat=Format de fitxer d'IDs de pàgina incorrecte
+confACollectingCurPages=S'està recopilant les pàgines actuals
+confABuildingPagesMap=S'està creant el mapatge de pàgines
 confAProcessDrawDiag=S'ha començat a processar els diagrames de draw.io importats
 confAProcessDrawDiagDone=S'ha acabat de processar els diagrames de draw.io importats
 confAProcessImpPages=S'ha començat a processar les pàgines importades
@@ -1061,7 +1061,7 @@ loginFirstThen=Inicieu sessió primer a {1} i després a {2}
 errFetchDocList=Error: no s'ha pogut obtenir la llista de documents
 builtinPlugins=Connectors integrats
 extPlugins=Connectors externs
-backupFound=S'ha trobat un fitxer còpia de seguretat
+backupFound=S'ha trobat un fitxer de còpia de seguretat
 chromeOnly=Aquesta funció només funciona a Google Chrome
 msgDeleted=Aquest missatge s'ha suprimit
 confAErrFetchDrawList=S'ha produït un error en obtenir la llista de diagrames. Alguns diagrames s'han saltat.
@@ -1073,7 +1073,7 @@ diagNameEmptyErr=El diagrama ha de tenir un nom
 openDiagram=Obre un diagrama
 newDiagram=Diagrama nou
 editable=Editable
-confAReimportStarted=S'ha tornar a iniciar l'importació de {1} diagrames...
+confAReimportStarted=S'ha començat a tornar a importar {1} diagrames
 spaceFilter=Filtra per espais
 curViewState=Estat actual del visualitzador
 pageLayers=Pàgina i capes
@@ -1107,7 +1107,7 @@ fetchingRecentFailed=No s'han pogut obtenir els diagrames recents
 useSrch2FindDiags=Utilitzeu el quadre de cerca per trobar diagrames de draw.io
 cantReadChckPerms=No es pot llegir el diagrama especificat. Si us plau, comproveu que teniu permís de lectura sobre aquest fitxer.
 cantFetchChckPerms=No es pot obtenir la informació del diagrama. Si us plau, comproveu que teniu permís de lectura sobre aquest fitxer.
-searchFailed=La cerca ha fallat. Siusplau, intenta-ho més tard.
+searchFailed=La cerca ha fallat. Si us plau, intenteu-ho més tard.
 plsTypeStr=Escriviu una cadena de cerca.
 unsupportedFileChckUrl=Fitxer no compatible. Comproveu l'URL especificat
 diagNotFoundChckUrl=No s'ha trobat el diagrama o no es pot accedir. Comproveu l'URL especificat
@@ -1137,10 +1137,10 @@ loadAttFailed=No s'ha pogut carregar el fitxer adjunt "{1}"
 embedDrawDiag=Incrusta el diagrama draw.io
 addDiagram=Afegeix un diagrama
 embedDiagram=Incrusta un diagrama
-editOwningPg=Edita la pàgina al què pertany
-deepIndexing=Indexació Profunda (també els diagrames d'índex que no s'utilitzen en cap pàgina)
+editOwningPg=Edita la pàgina a què pertany
+deepIndexing=Indexació Profunda (indexa els diagrames que no s'utilitzen en cap pàgina)
 confADeepIndexStarted=S'ha iniciat la indexació profunda
-confADeepIndexDone=Indexació profunda completada
+confADeepIndexDone=S'ha completat la indexació profunda
 officeNoDiagramsSelected=No s'han trobat diagrames a la selecció
 officeNoDiagramsInDoc=No s'han trobat diagrames al document
 officeNotSupported=Aquesta funció no és compatible amb aquesta aplicació amfitrió
@@ -1164,7 +1164,7 @@ replaceAll=Substitueix-ho tot
 confASkipDiagModified=S'ha omès "{1}", ja que es va modificar després de la importació inicial
 replFind=Substitueix/Troba
 matchesRepl=S'han substituït {1} coincidències
-draftErrDataLoss=S'ha produït un error en llegir el fitxer esborrany. El diagrama no es pot editar ara per evitar possibles pèrdues de dades. Torneu-ho a provar més tard o poseu-vos en contacte amb el servei d'assistència.
+draftErrDataLoss=S'ha produït un error en llegir el fitxer d'esborrany. El diagrama no es pot editar ara per evitar possibles pèrdues de dades. Torneu-ho a provar més tard o poseu-vos en contacte amb el servei d'assistència.
 ibm=IBM
 linkToDiagramHint=Afegir un enllaç a aquest diagrama. El diagrama només es pot editar des de la pàgina a la qual pertany.
 linkToDiagram=Enllaç al diagrama
@@ -1182,7 +1182,7 @@ owner=Propietari
 repository=Repositori
 branch=Branca
 meters=Mesuradors
-teamsNoEditingMsg=La funcionalitat de l'editor només està disponible a l'entorn d'escriptori (a l'aplicació MS Teams o un navegador web)
+teamsNoEditingMsg=La funcionalitat de l'editor només està disponible a l'ordinador (a l'aplicació del Microsoft Teams o en un navegador web)
 contactOwner=Contacta amb el propietari
 viewerOnlyMsg=No podeu editar els diagrames a la plataforma mòbil, feu servir el client d'escriptori o un navegador web.
 website=Lloc web
@@ -1213,7 +1213,7 @@ drafts=Esborranys
 draftSaveInt=Interval de desat d'esborrany [seg] (0 per desactivar)
 pluginsDisabled=Connectors externs desactivats.
 extExpNotConfigured=El servei d'imatge externa no està configurat
-pathFilename=Ruta/Nom de fitxer
+pathFilename=Camí/Nom del fitxer
 confAHugeInstances=Instàncies molt grans
 confAHugeInstancesDesc=Si aquesta instància inclou més de 100.000 pàgines, és més ràpid sol·licitar la llista de pàgines de la instància actual a Atlassian. Poseu-vos en contacte amb el nostre suport per obtenir més detalls.
 choosePageIDsFile=Trieu el fitxer csv d'identificadors de pàgina actuals

+ 76 - 76
src/main/webapp/resources/dia_it.txt

@@ -37,7 +37,7 @@ allChangesSavedInDrive=Tutte le modifiche sono state salvate sul Drive
 allowPopups=Autorizza i pop-up per non vedere questa finestra
 allowRelativeUrl=Consenti URL relativi
 alreadyConnected=Nodi già connessi
-appearance=Apparenza
+appearance=Aspetto
 apply=Applica
 archiMate21=ArchiMate 2.1
 arrange=Organizza
@@ -243,7 +243,7 @@ googleImages=Google Immagini
 imageSearch=Ricerca immagine
 eip=EIP
 embed=Integra
-embedFonts=Embed Fonts
+embedFonts=Integra caratteri
 embedImages=Integra immagini
 mainEmbedNotice=Incolla nella pagina
 electrical=Elettrico
@@ -359,7 +359,7 @@ fullscreen=Schermo intero
 gap=Spazio
 gcp=GCP
 general=Generale
-getNotionChromeExtension=Get the Notion Chrome Extension
+getNotionChromeExtension=Scarica l'estensione Notion di Chrome
 github=GitHub
 gitlab=GitLab
 gliffy=Gliffy
@@ -434,7 +434,7 @@ ios=iOS
 italic=Corsivo
 kennedy=Kennedy
 keyboardShortcuts=Scorciatoie da tastiera
-labels=Labels
+labels=Etichette
 layers=Livelli
 landscape=Orizzontale
 language=Lingua
@@ -445,7 +445,7 @@ licensingError=Errore di licenza
 licenseHasExpired=La licenza per {1} è scaduta il {2}. Fai clic qui.
 licenseRequired=Questa funzione richiede la licenza di draw.io.
 licenseWillExpire=La licenza per {1} scadrà il {2}. Fai clic qui.
-light=Light
+light=Chiaro
 lineJumps=Salti di linea
 linkAccountRequired=Se il diagramma non è pubblico, è necessario un account Google per visualizzare il collegamento.
 linkText=Testo del collegamento
@@ -568,7 +568,7 @@ pageContent=Contenuto pagina
 pageNotFound=Pagina non trovata
 pageWithNumber=Pagina-{1}
 pages=Pagine
-pageTabs=Page Tabs
+pageTabs=Linguette delle pagine
 pageView=Vista pagina
 pageSetup=Impostazioni pagina
 pageScale=Scala pagina
@@ -691,18 +691,18 @@ serviceUnavailableOrBlocked=Servizio non disponibile o bloccato
 sessionExpired=La tua sessione è scaduta. Aggiorna la finestra del browser.
 sessionTimeoutOnSave=La tua sessione è scaduta e sei stato disconnesso da Google Drive. Premi OK per collegarti e salvare
 setAsDefaultStyle=Imposta come stile predefinito
-settings=Settings
+settings=Impostazioni
 shadow=Ombra
 shape=Forma
 shapes=Forme
 share=Condividi
-shareCursor=Share Mouse Cursor
+shareCursor=Condividi il puntatore del mouse
 shareLink=Collegamento per la modifica condivisa
 sharingAvailable=Condivisione disponibile per file su Google Drive e OneDrive.
-moveItToGoogleDrive=You'll need to move "{1}" to Google Drive before you can collaborate.
+moveItToGoogleDrive=Dovrai spostare "{1}" in Google Drive prima di poter collaborare
 sharp=Netto
 show=Mostra
-showRemoteCursors=Show Remote Mouse Cursors
+showRemoteCursors=Mostra i puntatori remoti del mouse
 showStartScreen=Mostra la schermata d'inizio
 sidebarTooltip=Fai clic per espandere. Trascina e rilascia le forme nel diagramma. Maiusc+clic per cambiare selezione. Alt+clic per inserire e connettere.
 signs=Segni
@@ -712,7 +712,7 @@ simpleArrow=Freccia semplice
 simpleViewer=Visualizzatore semplice
 size=Dim.
 sketch=Schizzo
-snapToGrid=Snap to Grid
+snapToGrid=Aggancia alla griglia
 solid=Solido
 sourceSpacing=Spaziatura dell'origine
 south=Sud
@@ -769,7 +769,7 @@ uml=UML
 underline=Sottolinea
 undo=Annulla
 ungroup=Separa
-unmerge=Unmerge
+unmerge=Dividi
 unsavedChanges=Modifiche non salvate
 unsavedChangesClickHereToSave=Modifiche non salvate. Fai clic qui per salvare.
 untitled=Senza titolo
@@ -996,9 +996,9 @@ hiResPreview=Anteprima ad alta risoluzione
 officeNotLoggedGD=Non sei connesso a Google Drive. Apri il pannello delle attività di draw.io e accedi prima.
 officePopupInfo=Completa il processo nella finestra a comparsa.
 pickODFile=Scegli file di OneDrive
-createODFile=Create OneDrive File
+createODFile=Crea file di OneDrive
 pickGDriveFile=Scegli file di Google Drive
-createGDriveFile=Create Google Drive File
+createGDriveFile=Crea file di Google Drive
 pickDeviceFile=Scegli di file da dispositivo
 vsdNoConfig="vsdurl" non è configurato
 ruler=Righello
@@ -1175,68 +1175,68 @@ showAllTemps=Mostra tutti i modelli
 notionToken=Token di Notion
 selectDB=Seleziona database
 noDBs=Nessun database
-diagramEdited={1} diagram "{2}" edited
-confDraftPermissionErr=Draft cannot be written. Do you have attachment write/read permission on this page?
-confDraftTooBigErr=Draft size is too large. Pease check "Attachment Maximum Size" of "Attachment Settings" in Confluence Configuration?
+diagramEdited={1} diagramma "{2}" modificato
+confDraftPermissionErr=La bozza non può essere scritta. Hai i permessi di scrittura/lettura degli allegati in questa pagina?
+confDraftTooBigErr=La dimensione della bozza è troppo grande. Controlla "Dimensioni massime degli allegati" di "impostazioni allegati" nella configurazione di Confluence?
 owner=Proprietario
-repository=Repository
-branch=Branch
-meters=Meters
-teamsNoEditingMsg=Editor functionality is only available in Desktop environment (in MS Teams App or a web browser)
-contactOwner=Contact Owner
-viewerOnlyMsg=You cannot edit the diagrams in the mobile platform, please use the desktop client or a web browser.
+repository=Deposito
+branch=Ramo
+meters=Metri
+teamsNoEditingMsg=La funzionalità dell'editor è disponibile solo in ambiente desktop (nell'applicazione MS Teams o in un browser web)
+contactOwner=Contatta il proprietario
+viewerOnlyMsg={1}: scrittura dell'allegato non riuscita, riprova tra {2} secondi...
 website=Sito web
 check4Updates=Controlla aggiornamenti
-attWriteFailedRetry={1}: Attachment write failed, trying again in {2} seconds...
-confPartialPageList=We couldn't fetch all pages due to an error in Confluence. Continuing using {1} pages only.
-spellCheck=Spell checker
-noChange=No Change
-lblToSvg=Convert labels to SVG
-txtSettings=Text Settings
-LinksLost=Links will be lost
-arcSize=Arc Size
-editConnectionPoints=Edit Connection Points
-notInOffline=Not supported while offline
-notInDesktop=Not supported in Desktop App
-confConfigSpaceArchived=draw.io Configuration space (DRAWIOCONFIG) is archived. Please restore it first.
-confACleanOldVerStarted=Cleaning old diagram draft versions started
-confACleanOldVerDone=Cleaning old diagram draft versions finished
-confACleaningFile=Cleaning diagram draft "{1}" old versions
-confAFileCleaned=Cleaning diagram draft "{1}" done
-confAFileCleanFailed=Cleaning diagram draft "{1}" failed
-confACleanOnly=Clean Diagram Drafts Only
-brush=Brush
-openDevTools=Open Developer Tools
-autoBkp=Automatic Backup
-confAIgnoreCollectErr=Ignore collecting current pages errors
-drafts=Drafts
-draftSaveInt=Draft save interval [sec] (0 to disable)
-pluginsDisabled=External plugins disabled.
-extExpNotConfigured=External image service is not configured
-pathFilename=Path/Filename
-confAHugeInstances=Very Large Instances
-confAHugeInstancesDesc=If this instance includes 100,000+ pages, it is faster to request the current instance pages list from Atlassian. Please contact our support for more details.
-choosePageIDsFile=Choose current page IDs csv file
-chooseDrawioPsgesFile=Choose pages with draw.io diagrams csv file
-private=Private
-diagramTooLarge=The diagram is too large, please reduce its size and try again.
-selectAdminUsers=Select Admin Users
-xyzTeam={1} Team
-addTeamTitle=Adding a new draw.io Team
-addTeamInst1=To create a new draw.io Team, you need to create a new Atlassian group with "drawio-" postfix (e.g, a group named "drawio-marketing").
-addTeamInst2=Then, configure which team member can edit/add configuration, templates, and libraries from this page.
-drawioTeams=draw.io Teams
-members=Members
-adminEditors=Admins/Editors
-allowAll=Allow all
-noTeams=No teams found
-errorLoadingTeams=Error Loading Teams
-noTeamMembers=No team members found
-errLoadTMembers=Error loading team members
-errCreateTeamPage=Error creating team "{1}" page in "draw.io Configuration" space, please check you have the required permissions.
-gotoConfigPage=Please create the space from draw.io "Configuration" page.
-noAdminsSelected=No admins/editors selected
-errCreateConfigFile=Error creating "configuration.json" file, please check you have the required permissions.
-errSetPageRestr=Error setting page restrictions
-notAdmin4Team=You are not an admin for this team
-configUpdated=Configuration updated, restart the editor if you want to work with last configuration.
+attWriteFailedRetry={1}: Write allegato non è riuscito, riprova in {2} secondi ...
+confPartialPageList=Impossibile recuperare tutte le pagine a causa di un errore in Confluence. Procedo usando solo {1} pagine.
+spellCheck=Controllo ortografico
+noChange=Nessuna modifica
+lblToSvg=Converti le etichette in SVG
+txtSettings=Impostazioni del testo
+LinksLost=I collegamenti andranno persi
+arcSize=Dimensione dell'arco
+editConnectionPoints=Modifica punti di connessione
+notInOffline=Non supportato mentre non è in linea
+notInDesktop=Non supportato nell'applicazione desktop
+confConfigSpaceArchived=Lo spazio di configurazione di draw.io (DRAWIOCONFIG) è archiviato. Ripristinalo prima.
+confACleanOldVerStarted=La cancellazione delle bozze di vecchie versioni del diagramma è iniziata
+confACleanOldVerDone=Cancellazione delle bozze di vecchie versioni del diagramma terminata
+confACleaningFile=Cancellazione delle vecchie versioni della bozza di diagramnma "{1}"
+confAFileCleaned=Cancellazione della bozza del diagramma "{1}" completata
+confAFileCleanFailed=Diagramma di pulizia Draft "{1}" non riuscito
+confACleanOnly=Cancella solo le bozze del diagramma
+brush=Spazzola
+openDevTools=Apri strumenti per sviluppatori
+autoBkp=Backup automatico
+confAIgnoreCollectErr=Ignora la raccolta di errori delle pagine attuali
+drafts=Bozze
+draftSaveInt=Intervallo di salvataggio delle bozze [sec] (0 per disabilitare)
+pluginsDisabled=Estensioni esterne disabilitate.
+extExpNotConfigured=Il servizio di immagini esterne non è configurato
+pathFilename=Precorso/nome file
+confAHugeInstances=Istanze molto grandi
+confAHugeInstancesDesc=Se questa istanza include oltre 100.000 pagine, è più veloce richiedere l'elenco delle pagine dell'istanza attuale da Atlassian. Contatta il nostro supporto per maggiori dettagli.
+choosePageIDsFile=Scegli il file CSV della pagina corrente
+chooseDrawioPsgesFile=Scegli pagine con file csv diagrammi Draw.io
+private=Privato
+diagramTooLarge=Il diagramma è troppo grande, riduci le dimensioni e riprova.
+selectAdminUsers=Seleziona gli utenti amministrativi
+xyzTeam=Squadra {1}
+addTeamTitle=Aggiunta di un nuovo team Draw.io
+addTeamInst1=Per creare una nuova squadra draw.io, devi creare un nuovo gruppo Atlassian con postfix "drawio-" (ad esempio, un gruppo chiamato "drawio-marketing").
+addTeamInst2=Quindi, configura quale membro della squadra può modificare/aggiungere configurazioni, modelli e librerie da questa pagina.
+drawioTeams=Squadre di draw.io
+members=Membri
+adminEditors=Amministratori/redattori
+allowAll=Permettere tutto
+noTeams=Nessuna squadra trovata
+errorLoadingTeams=Team di caricamento degli errori
+noTeamMembers=Nessun membro del team trovato
+errLoadTMembers=Error durante il caricamento dei membri della squadra
+errCreateTeamPage=Errore durante la creazione della pagina "{1}" della squadra nello spazio "Configurazione di draw.io", verifica di avere le autorizzazioni richieste.
+gotoConfigPage=Crea lo spazio dalla pagina "Configurazione" di draw.io.
+noAdminsSelected=Nessun amministratore/redattore selezionato
+errCreateConfigFile=Errore durante la creazione del file "configuration.json", verifica di avere le autorizzazioni richieste.
+errSetPageRestr=Errore durante l'impostazione delle restrizioni di pagina
+notAdmin4Team=Non sei un amministratore per questa squadra
+configUpdated=Configurazione aggiornata, riavvia l'editor se desideri lavorare con l'ultima configurazione.

+ 22 - 22
src/main/webapp/resources/dia_ja.txt

@@ -1,6 +1,6 @@
 # *DO NOT DIRECTLY EDIT THIS FILE, IT IS AUTOMATICALLY GENERATED AND IT IS BASED ON:*
 # https://docs.google.com/spreadsheet/ccc?key=0AmQEO36liL4FdDJLWVNMaVV2UmRKSnpXU09MYkdGbEE
-about=について
+about=バージョン情報
 aboutDrawio=draw.ioについて
 accessDenied=アクセス拒否されました
 accounts=Accounts
@@ -8,11 +8,11 @@ action=Action
 actualSize=実寸
 add=追加する
 addAccount=アカウントを追加する
-addedFile=追加された {1}
+addedFile={1} を追加しました。
 addImages=画像を追加する
 addImageUrl=画像のURLを追加する
 addLayer=レイヤーを追加する
-addProperty=属性を追加する
+addProperty=プロパティを追加する
 address=アドレス
 addToExistingDrawing=既存のファイルに追加する
 addToScratchpad=Add to Scratchpad
@@ -37,7 +37,7 @@ allChangesSavedInDrive=すべての変更をドライブに保存しました。
 allowPopups=ポップアップを有効にすると、このダイアログが不表示になります。
 allowRelativeUrl=Allow relative URL
 alreadyConnected=ノードがすでに接続されています
-appearance=Appearance
+appearance=外観
 apply=適用
 archiMate21=ArchiMate 2.1
 arrange=配置
@@ -108,7 +108,7 @@ configLinkWarn=This link configures draw.io. Only click OK if you trust whoever
 configLinkConfirm=Click OK to configure and restart draw.io.
 container=Container
 csv=CSV
-dark=
+dark=ダーク
 diagramXmlDesc=XMLファイル
 diagramHtmlDesc=HTMLファイル
 diagramPngDesc=ビットマップ画像
@@ -158,8 +158,8 @@ copyCreated=ファイルをコピーしました
 copyData=データをコピーする
 copyOf={1}のコピー
 copyOfDrawing=図のコピー
-copySize=Copy Size
-copyStyle=スタイルをコピーする
+copySize=サイズをコピー
+copyStyle=スタイルをコピー
 create=作成する
 createNewDiagram=新規ファイルを作成する
 createRevision=改訂を作成する
@@ -222,7 +222,7 @@ drawingTooLarge=描画が大きすぎます
 drawioForWork=Draw.io の GSuite
 dropbox=Dropbox
 duplicate=複製
-duplicateIt={1}を複製する
+duplicateIt={1} を複製
 divider=分割
 dx=Dx
 dy=Dy
@@ -247,11 +247,11 @@ embedFonts=Embed Fonts
 embedImages=画像を埋め込む
 mainEmbedNotice=ページにペーストする
 electrical=電気
-ellipse=Ellipse
+ellipse=楕円
 embedNotice=ページの最後にこれをペースとする
 enterGroup=グループに入る
 enterName=名前を入力する
-enterPropertyName=属性名の入力する
+enterPropertyName=プロパティ名を入力する
 enterValue=値を設定する
 entityRelation=ER
 entityRelationshipDiagram=ER図
@@ -292,7 +292,7 @@ fileChangedOverwriteDialog=ファイルが変更されました。変更を上
 fileChangedSyncDialog=The file has been modified.
 fileChangedSync=The file has been modified. Click here to synchronize.
 overwrite=上書き
-synchronize=Synchronize
+synchronize=同期
 filename=ファイル名
 fileExists=ファイルはすでに存在します。
 fileMovedToTrash=ファイルはゴミ箱に移動しました
@@ -349,7 +349,7 @@ formatVssx=VSSX
 formatXmlPlain=XML (非圧縮)
 formatXml=XML
 forum=ヘルプ・ディスカッション
-freehand=Freehand
+freehand=フリーハンド
 fromTemplate=テンプレートから
 fromTemplateUrl=テンプレートURLから
 fromText=テキストから挿入
@@ -445,7 +445,7 @@ licensingError=ライセンス エラー
 licenseHasExpired=ライセンス{1} は{2}に期限がきれました。 ここをクリックしてください。
 licenseRequired=この機能には、draw.ioのライセンスが必要です。
 licenseWillExpire=ライセンス{1} に期限切れになります{2}. ここをクリックしてください。
-light=Light
+light=ライト
 lineJumps=Line jumps
 linkAccountRequired=図が公式表示されていない場合は、リンクを表示するために Google アカウントが必要です。
 linkText=リンク テキスト
@@ -489,7 +489,7 @@ microsoftExcel=Microsoft Excel
 microsoftPowerPoint=Microsoft PowerPoint
 microsoftWord=Microsoft Word
 middle=中央揃え
-minimal=Minimal
+minimal=ミニマル
 misc=その他
 mockups=実物大
 modificationDate=変更日
@@ -568,7 +568,7 @@ pageContent=ページ コンテンツ
 pageNotFound=ページが見つかりません
 pageWithNumber=ページ{1}
 pages=ページを指定
-pageTabs=Page Tabs
+pageTabs=ページタブ
 pageView=ページビュー
 pageSetup=ページ設定
 pageScale=ページスケール
@@ -615,7 +615,7 @@ readOnly=読み取り専用
 reconnecting=再接続中
 recentlyUpdated=最近更新されました
 recentlyViewed=最近閲覧しました
-rectangle=Rectangle
+rectangle=長方形
 redirectToNewApp=このファイルはdraw.io Proで作成または編集されました。リダイレクトします。
 realtimeTimeout=オフライン時にいくつかの修正があったようですが、それらは保存されません。申し訳ございません。
 redo=やり直し
@@ -627,11 +627,11 @@ rememberMe=保存する
 rememberThisSetting=設定を保存
 removeFormat=書式をクリア
 removeFromGroup=グループから削除
-removeIt={1}  を削除
+removeIt={1} を削除
 removeWaypoint=途中点を削除
 rename=名前を変更
 renamed=名前が変更されました
-renameIt={1}  の名前を変更する。
+renameIt={1} の名前を変更
 renaming=名前を変更中
 replace=置き換え
 replaceIt={1}はすでに存在します。上書きしますか?
@@ -651,7 +651,7 @@ retryingLogin=ログインがタイムアウトしました。再試行中。
 reverse=逆
 revision=改訂
 revisionHistory=改訂履歴
-rhombus=Rhombus
+rhombus=ひし形
 right=右
 rightAlign=右揃え
 rightToLeft=右から左
@@ -712,7 +712,7 @@ simpleArrow=シンプルな矢印
 simpleViewer=Simple Viewer
 size=サイズ
 sketch=スケッチ
-snapToGrid=Snap to Grid
+snapToGrid=グリッドに合わせる
 solid=実線
 sourceSpacing=始点の間隔
 south=下
@@ -822,8 +822,8 @@ venndiagrams=ベン図表
 webEmailOrOther=ウェブ電子メール、またはその他のインター ネット アドレス
 webLink=ウェブリンク
 wireframes=ワイヤーフレーム
-property=Property
-value=Value
+property=プロパティ
+value=
 showMore=Show More
 showLess=Show Less
 myDiagrams=My Diagrams

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
src/main/webapp/service-worker.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
src/main/webapp/service-worker.js.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
src/main/webapp/shortcuts.svg


+ 24 - 0
src/main/webapp/styles/grapheditor.css

@@ -188,6 +188,18 @@ a.geStatus .geStatusAlertOrange {
 	color:#000000 !important;
 	border-radius:3px;
 }
+html body div.geSmallBanner {
+	background-color: #F2931E;
+	background-image: linear-gradient(#F2931E 0px,#F08707 100%);
+	border: 1px solid #F08707;
+	color: #000;
+}
+html body div.geSmallBanner:hover:not([disabled]) {
+	background-color: #ffb75e;
+	background-image: linear-gradient(#ffb75e 0px,#F2931E 100%);
+	border: 1px solid #F08707;
+	color: #000;
+}
 a.geStatus .geStatusMessage {
 	padding:4px 6px 4px 6px;
 	font-size:12px;
@@ -471,8 +483,14 @@ div.mxWindow .geButton {
 	max-width:calc(100% - 90px);
 	white-space:nowrap;
 	overflow:hidden;
+	overflow-x:auto;
+	-ms-overflow-style: none;
+	scrollbar-width: none;
 	left:0px;
 }
+.geTabScroller::-webkit-scrollbar {
+	display: none;
+}
 .geToggleItem {
 	padding:4px;
 	border-radius:8px;
@@ -581,9 +599,15 @@ html body div.geActivePage, .geRuler {
 	background-position:50% 50%;
 	border-radius: 8px;
 }
+.geSidebar .geItem, .geShapePicker .geItem {
+	transition: transform 100ms ease-out;
+}
 .geSidebar .geItem:hover {
 	background-color:#e0e0e0;
 }
+.geSidebar .geItem:active, .geShapePicker .geItem:active {
+	transform: scale(0.8,0.8);
+}
 .geItem {
 	vertical-align: top;
 	display: inline-block;