Browse Source

13.4.0 release

Gaudenz Alder 5 years ago
parent
commit
07a0c65256

+ 6 - 0
ChangeLog

@@ -1,3 +1,9 @@
+08-JUL-2020: 13.4.0
+
+- Adds border for lightbox export
+- Uses mxGraph 4.2.1 beta 4
+- Adds Diagram Style panel
+
 04-JUL-2020: 13.3.9
 
 - Fixes ignored autosave for native files

+ 1 - 1
VERSION

@@ -1 +1 @@
-13.3.9
+13.4.0

File diff suppressed because it is too large
+ 4 - 4
etc/mxgraph/mxClient.js


File diff suppressed because it is too large
+ 472 - 455
src/main/webapp/js/app.min.js


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

@@ -3442,12 +3442,12 @@ App.prototype.createFileSystemOptions = function(name)
 	for (var i = 0; i < this.editor.diagramFileTypes.length; i++)
 	{
 		ext.push({description: mxResources.get(this.editor.diagramFileTypes[i].description) +
-			' (.' + this.editor.diagramFileTypes[i].extension + ')',
+			((mxClient.IS_MAC) ? ' (.' + this.editor.diagramFileTypes[i].extension + ')' : ''),
 			extensions: [this.editor.diagramFileTypes[i].extension]});
 	}
 	
-	// TODO: Specify default name via options
-	return {type: 'save-file', accepts: ext, defaultPath: name};
+	// TODO: Specify default filename
+	return {type: 'save-file', accepts: ext, fileName: name};
 };
 
 /**
@@ -3464,7 +3464,7 @@ App.prototype.chooseFileSystemEntries = function(success, error, opts)
 	});
 	
 	opts = (opts != null) ? opts : this.createFileSystemOptions();
-
+	
 	// LATER: Specify default name via options
 	window.chooseFileSystemEntries(opts).then(mxUtils.bind(this, function(fileHandle)
 	{

+ 35 - 6
src/main/webapp/js/diagramly/Editor.js

@@ -40,6 +40,29 @@
 		{ext: 'html', title: 'filetypeHtml'},
 		{ext: 'png', title: 'filetypePng'},
 		{ext: 'svg', title: 'filetypeSvg'}];
+	
+	/**
+	 * 
+	 */
+	Editor.styles = [{},
+		{commonStyle: {fontColor: '#5C5C5C', strokeColor: '#006658', fillColor: '#21C0A5'}},
+		{commonStyle: {fontColor: '#095C86', strokeColor: '#AF45ED', fillColor: '#F694C1'},
+			edgeStyle: {strokeColor: '#60E696'}},
+		{commonStyle: {fontColor: '#46495D', strokeColor: '#788AA3', fillColor: '#B2C9AB'}},
+		{commonStyle:  {fontColor: '#5AA9E6', strokeColor: '#FF6392', fillColor: '#FFE45E'},
+			graph: {background: '#F9F9F9'}},
+		{commonStyle:  {fontColor: '#393C56', strokeColor: '#E07A5F', fillColor: '#F2CC8F'},
+			graph: {background: '#F4F1DE'}},
+		{commonStyle: {fontColor: '#1D3557', strokeColor: '#457B9D', fillColor: '#A8DADC'},
+			graph: {background: '#F1FAEE'}},
+		{commonStyle: {fontColor: '#143642', strokeColor: '#0F8B8D', fillColor: '#FAE5C7'},
+			edgeStyle: {strokeColor: '#A8201A'},
+			graph: {background: '#DAD2D8', gridColor: '#ABA4A9'}},
+		{commonStyle: {fontColor: '#FEFAE0', strokeColor: '#DDA15E', fillColor: '#BC6C25'},
+			graph: {background: '#283618', gridColor: '#48632C'}},
+		{commonStyle:  {fontColor: '#E4FDE1', strokeColor: '#028090', fillColor: '#F45B69'},
+			graph: {background: '#114B5F', gridColor: '#0B3240'}}
+	];
 
 	/**
 	 * Used in the GraphViewer lightbox.
@@ -1615,6 +1638,11 @@
 				EditorUi.templateFile = config.templateFile;
 			}
 			
+			if (config.styles != null)
+			{
+				Editor.styles = config.styles;
+			}
+			
 			if (config.globalVars != null)
 			{
 				Editor.globalVars = config.globalVars;
@@ -4750,7 +4778,8 @@
 		 */
 		StyleFormatPanel.prototype.addStyles = function(div)
 		{
-			var graph = this.editorUi.editor.graph;
+			var ui = this.editorUi;
+			var graph = ui.editor.graph;
 			var picker = document.createElement('div');
 			picker.style.whiteSpace = 'nowrap';
 			picker.style.paddingLeft = '24px';
@@ -4835,7 +4864,7 @@
 									style = mxUtils.removeStylename(style, stylenames[j]);
 								}
 
-								var defaults = (graph.getModel().isVertex(cells[i])) ? graph.defaultVertexStyle : graph.defaultEdgeStyle;
+								var defaults = (graph.getModel().isVertex(cells[i])) ? ui.initialDefaultVertexStyle : ui.initialdefaultEdgeStyle;
 								
 								if (colorset != null)
 								{
@@ -4926,12 +4955,12 @@
 						}
 						else if (colorset['fill'] == '')
 						{
-							btn.style.backgroundColor = mxUtils.getValue(graph.defaultVertexStyle,
+							btn.style.backgroundColor = mxUtils.getValue(ui.initialDefaultVertexStyle,
 								mxConstants.STYLE_FILLCOLOR, (uiTheme == 'dark') ?'#2a2a2a' : '#ffffff');
 						}
 						else
 						{
-							btn.style.backgroundColor = colorset['fill'] || mxUtils.getValue(graph.defaultVertexStyle,
+							btn.style.backgroundColor = colorset['fill'] || mxUtils.getValue(ui.initialDefaultVertexStyle,
 								mxConstants.STYLE_FILLCOLOR, (uiTheme == 'dark') ?'#2a2a2a' : '#ffffff');
 						}
 						
@@ -4941,12 +4970,12 @@
 						}
 						else if (colorset['stroke'] == '')
 						{
-							btn.style.border = '1px solid ' + mxUtils.getValue(graph.defaultVertexStyle, 
+							btn.style.border = '1px solid ' + mxUtils.getValue(ui.initialDefaultVertexStyle, 
 								mxConstants.STYLE_STROKECOLOR, (uiTheme != 'dark') ?'#2a2a2a' : '#ffffff');
 						}
 						else
 						{
-							btn.style.border = '1px solid ' + (colorset['stroke'] || mxUtils.getValue(graph.defaultVertexStyle,
+							btn.style.border = '1px solid ' + (colorset['stroke'] || mxUtils.getValue(ui.initialDefaultVertexStyle,
 									mxConstants.STYLE_STROKECOLOR, (uiTheme != 'dark') ?'#2a2a2a' : '#ffffff'));
 						}
 					}

+ 1 - 1
src/main/webapp/js/diagramly/EditorUi.js

@@ -4514,7 +4514,7 @@
 				   	{
 				   		this.spinner.stop();
 				   		this.handleError(e);
-				   	}));
+				   	}), null, null, null, null, null, null, null, 5);
 					
 					mxEvent.addListener(this.editor.graph.container, 'click', clickHandler);
 				   	document.body.appendChild(this.exportDialog);

+ 99 - 90
src/main/webapp/js/diagramly/Extensions.js

@@ -5219,7 +5219,10 @@ LucidImporter = {};
 							dx = (exit.x == entry.x) ? 20 : 0;
 							dy = (exit.y == entry.y) ? 0 : 0;
 							
-							cell.geometry.points = [new mxPoint(exit.x + dx, exit.y + dy), new mxPoint(entry.x + dx, entry.y + dy)];
+							var p1 = new mxPoint(exit.x + dx, exit.y + dy), p2 = new mxPoint(entry.x + dx, entry.y + dy);
+							p1.generated = true;
+							p2.generated = true;
+							cell.geometry.points = [p1, p2];
 							implicitX = (exit.y == entry.y);
 							implicitY = (exit.x == entry.x);
 						}
@@ -5417,32 +5420,7 @@ LucidImporter = {};
 		}
 	};
 
-	var hideObj = function(key, groups, hidden)
-	{
-		if (mxUtils.indexOf(hidden, key) < 0)
-		{
-			hidden.push(key);
-		}
-
-		if (key in groups)
-		{
-			var obj = groups[key];
-			obj.id = key;
-			
-			if (obj.Members != null)
-			{
-				for (var key2 in obj.Members)
-				{
-					hidden = hideObj(key2, groups, hidden);
-				}
-			}
-		
-		}
-		
-		return hidden;
-	};
-	
-	function createGroup(obj, lookup)
+	function createGroup(obj, lookup, edgesGroups)
 	{
 		try
 		{
@@ -5461,10 +5439,14 @@ LucidImporter = {};
 					minY = Math.min(minY, v.geometry.y);
 					maxX = Math.max(maxX, v.geometry.x + v.geometry.width);
 					maxY = Math.max(maxY, v.geometry.y + v.geometry.height);
+					v.parent = group;
+					group.insert(v);
+				}
+				else
+				{
+					//Edges are not yet created, so, create a map for them
+					edgesGroups[key] = group;
 				}
-				
-				v.parent = group;
-				group.insert(v);
 			}
 			
 			group.geometry.x = minX;
@@ -5479,6 +5461,19 @@ LucidImporter = {};
 				geo.y -= minY;
 			}
 			
+			if (obj.IsState)
+			{
+				group.lucidLayerInfo = {
+					name: obj.Name,
+					visible: !obj.Hidden,
+					locked: obj.Restrictions.b && obj.Restrictions.p && obj.Restrictions.c
+				};
+			}
+			else if (obj.Hidden)
+			{
+				group.visible = false;
+			}
+			
 			return group;
 		}
 		catch(e)
@@ -5494,34 +5489,9 @@ LucidImporter = {};
 		{
 			var select = [];
 			var lookup = {};
+			var edgesGroups = {};
 			var queue = [];
 
-			//collect IDs that are part of groups and hidden
-			var hidden = [];
-			var i = 0;
-			
-			if (g.Groups != null)
-			{
-				for (var key in g.Groups)
-				{
-					var obj = g.Groups[key];
-					obj.id = key;
-					
-					if (obj.Hidden == true && obj.Members != null)
-					{
-						if (mxUtils.indexOf(hidden, key) < 0)
-						{
-							hidden.push(key);
-						}
-
-						for (var key2 in obj.Members)
-						{
-							hidden = hideObj(key2, g.Groups, hidden);
-						}
-					}
-				}
-			}
-			
 			// Vertices first (populates lookup table for connecting edges)
 			if (g.Blocks != null)
 			{
@@ -5530,26 +5500,23 @@ LucidImporter = {};
 					var obj = g.Blocks[key];
 					obj.id = key;
 					
-					if (mxUtils.indexOf(hidden, key) < 0)
+					var created = false;
+					
+					if (styleMap[obj.Class] != null)
 					{
-						var created = false;
-						
-						if (styleMap[obj.Class] != null)
-						{
-							if (styleMap[obj.Class] == 'mxCompositeShape')
-							{
-								lookup[obj.id] = addCompositeShape(obj, select, graph);
-								queue.push(obj);
-								created = true;
-							}
-						}
-						
-						if (!created)
+						if (styleMap[obj.Class] == 'mxCompositeShape')
 						{
-							lookup[obj.id] = createVertex(obj, graph);
+							lookup[obj.id] = addCompositeShape(obj, select, graph);
 							queue.push(obj);
+							created = true;
 						}
 					}
+					
+					if (!created)
+					{
+						lookup[obj.id] = createVertex(obj, graph);
+						queue.push(obj);
+					}
 				}
 			}
 			else
@@ -5584,7 +5551,7 @@ LucidImporter = {};
 					
 					if (obj.IsGroup)
 					{
-						var group = createGroup(obj, lookup);
+						var group = createGroup(obj, lookup, edgesGroups);
 						
 						if (group)
 						{
@@ -5595,7 +5562,7 @@ LucidImporter = {};
 				}
 			}
 			
-			//Create non-hidden groups
+			//Create groups
 			if (g.Groups != null)
 			{
 				try
@@ -5605,15 +5572,12 @@ LucidImporter = {};
 						var obj = g.Groups[key];
 						obj.id = key;
 
-						if (obj.Hidden == 0 && obj.Members != null)
+						var group = createGroup(obj, lookup, edgesGroups);
+						
+						if (group)
 						{
-							var group = createGroup(obj, lookup);
-							
-							if (group)
-							{
-								lookup[obj.id] = group;
-								queue.push(obj);	
-							}
+							lookup[obj.id] = group;
+							queue.push(obj);	
 						}
 					}
 				}
@@ -5627,13 +5591,10 @@ LucidImporter = {};
 			{
 				for (var key in g.Lines)
 				{
-					if (mxUtils.indexOf(hidden, key) < 0)
-					{
-						var obj = g.Lines[key];
-						obj.id = key;
-						
-						queue.push(obj);
-					}
+					var obj = g.Lines[key];
+					obj.id = key;
+					
+					queue.push(obj);
 				}
 			}
 			
@@ -5667,7 +5628,36 @@ LucidImporter = {};
 						Math.round(p.Endpoint2.y * scale)), false);
 				}
 				
-				select.push(graph.addCell(e, null, null, src, trg));
+				var group = edgesGroups[obj.id];
+				
+				function fixPoint(p, pgeo)
+				{
+					if (p != null && !p.generated)
+					{
+						p.x -= pgeo.x;
+						p.y -= pgeo.y;
+					}
+				};
+				
+				if (group != null)
+				{
+					//Correct edge geometry
+					var geo = e.geometry, pgeo = group.geometry;
+					fixPoint(geo.sourcePoint, pgeo);
+					fixPoint(geo.targetPoint, pgeo);
+					fixPoint(geo.offset, pgeo);
+                    var points = geo.points;
+                    
+                    if (points != null) 
+                    {
+                        for (var i = 0; i < points.length; i++) 
+                        {
+                        	fixPoint(points[i], pgeo);
+                        }
+                    }
+				}
+				
+				select.push(graph.addCell(e, group, null, src, trg));
 			};
 			
 			// Inserts cells in ZOrder and connects edges via lookup
@@ -5680,7 +5670,26 @@ LucidImporter = {};
 				{
 					if (v.parent == null)
 					{
-						select.push(graph.addCell(v));
+						if (v.lucidLayerInfo)
+						{
+							var layerCell = new mxCell();
+					        graph.addCell(layerCell, graph.model.root);
+					        
+					        layerCell.setVisible(v.lucidLayerInfo.visible);
+
+					        if (v.lucidLayerInfo.locked)
+					        {
+					            layerCell.setStyle("locked=1;");
+					        }
+					        
+					        layerCell.setValue(v.lucidLayerInfo.name);
+					        delete v.lucidLayerInfo;
+					        graph.addCell(v, layerCell);
+						}
+						else
+						{
+							select.push(graph.addCell(v));
+						}
 					}
 				}
 				else if (obj.IsLine && obj.Action != null && obj.Action.Properties != null)

+ 24 - 0
src/main/webapp/js/diagramly/GraphViewer.js

@@ -337,6 +337,15 @@ GraphViewer.prototype.init = function(container, xmlNode, graphConfig)
 					return true;
 				};
 				
+				//Fix graph clipping by avoiding negative negative translation (after resize is finished)
+				var graphFoldCells = this.graph.foldCells;
+				
+				this.graph.foldCells = mxUtils.bind(this, function()
+				{
+					this.cellFolded = true;
+					return graphFoldCells.apply(this.graph, arguments);
+				});
+				
 				this.fireEvent(new mxEventObject('render'));
 			});
 
@@ -551,6 +560,21 @@ GraphViewer.prototype.addSizeHandler = function()
 			{
 				this.toolbar.style.width = Math.max(this.minToolbarWidth, container.offsetWidth) + 'px';
 			}
+
+			//If a cell is folded set the translation zero to avoid -ve translation
+			if (this.cellFolded)
+			{
+				this.cellFolded = false;
+				
+				if (this.center)
+				{
+					this.graph.center();
+				}
+				else
+				{
+					this.graph.view.setTranslate(0, 0);
+				}
+			}
 			
 			updatingOverflow = false;
 		}

File diff suppressed because it is too large
+ 285 - 284
src/main/webapp/js/extensions.min.js


+ 12 - 3
src/main/webapp/js/mxgraph/Editor.js

@@ -227,7 +227,12 @@ Editor.fullscreenLargeImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACA
 Editor.roughFillStyles = [{val: 'auto', dispName: 'Auto'}, {val: 'hachure', dispName: 'Hachure'}, {val: 'solid', dispName: 'Solid'},
 	{val: 'zigzag', dispName: 'ZigZag'}, {val: 'cross-hatch', dispName: 'Cross Hatch'}, {val: 'dots', dispName: 'Dots'},
 	{val: 'dashed', dispName: 'Dashed'}, {val: 'zigzag-line', dispName: 'ZigZag Line'}];
-	
+
+/**
+ * Graph themes for the format panel.
+ */
+Editor.themes = null;
+
 /**
  * Specifies the image URL to be used for the transparent background.
  */
@@ -2586,13 +2591,17 @@ FilenameDialog.createFileTypes = function(editorUi, nameInput, types)
 		drawPageBreaks(this.verticalPageBreaks);
 	};
 	
-	// Disables removing relative children from parents
+	// Disables removing relative children and table rows and cells from parents
 	var mxGraphHandlerShouldRemoveCellsFromParent = mxGraphHandler.prototype.shouldRemoveCellsFromParent;
 	mxGraphHandler.prototype.shouldRemoveCellsFromParent = function(parent, cells, evt)
 	{
 		for (var i = 0; i < cells.length; i++)
 		{
-			if (this.graph.getModel().isVertex(cells[i]))
+			if (this.graph.isTableCell(cells[i]) || this.graph.isTableRow(cells[i]))
+			{
+				return false;
+			}
+			else if (this.graph.getModel().isVertex(cells[i]))
 			{
 				var geo = this.graph.getCellGeometry(cells[i]);
 				

+ 27 - 2
src/main/webapp/js/mxgraph/EditorUi.js

@@ -14,6 +14,8 @@ EditorUi = function(editor, container, lightbox)
 	
 	var graph = this.editor.graph;
 	graph.lightbox = lightbox;
+	this.initialDefaultVertexStyle = mxUtils.clone(graph.defaultVertexStyle);
+	this.initialDefaultEdgeStyle = mxUtils.clone(graph.defaultEdgeStyle);
 
 	// Faster scrollwheel zoom is possible with CSS transforms
 	if (graph.useCssTransforms)
@@ -567,9 +569,9 @@ EditorUi = function(editor, container, lightbox)
 		}
 	
 		// Implements a global current style for edges and vertices that is applied to new cells
-		var insertHandler = function(cells, asText)
+		var insertHandler = function(cells, asText, model)
 		{
-			var model = graph.getModel();
+			model = (model != null) ? model : graph.getModel();
 			
 			model.beginUpdate();
 			try
@@ -668,6 +670,8 @@ EditorUi = function(editor, container, lightbox)
 			insertHandler(evt.getProperty('cells'), true);
 		});
 		
+		this.insertHandler = insertHandler;
+		
 		graph.connectionHandler.addListener(mxEvent.CONNECT, function(sender, evt)
 		{
 			var cells = [evt.getProperty('cell')];
@@ -2932,6 +2936,27 @@ EditorUi.prototype.setPageVisible = function(value)
 	this.fireEvent(new mxEventObject('pageViewChanged'));
 };
 
+/**
+ * Class: ChangeGridColor
+ *
+ * Undoable change to grid color.
+ */
+function ChangeGridColor(ui, color)
+{
+	this.ui = ui;
+	this.color = color;
+};
+
+/**
+ * Executes selection of a new page.
+ */
+ChangeGridColor.prototype.execute = function()
+{
+	var temp = this.ui.editor.graph.view.gridColor;
+	this.ui.setGridColor(this.color);
+	this.color = temp;
+};
+
 /**
  * Change types
  */

+ 556 - 66
src/main/webapp/js/mxgraph/Format.js

@@ -12,6 +12,11 @@ Format = function(editorUi, container)
  */
 Format.prototype.labelIndex = 0;
 
+/**
+ * Returns information about the current selection.
+ */
+Format.prototype.diagramIndex = 0;
+
 /**
  * Returns information about the current selection.
  */
@@ -369,17 +374,121 @@ Format.prototype.refresh = function()
 	{
 		evt.preventDefault();
 	}));
+
+	var containsLabel = this.getSelectionState().containsLabel;
+	var currentLabel = null;
+	var currentPanel = null;
+	
+	var addClickHandler = mxUtils.bind(this, function(elt, panel, index)
+	{
+		var clickHandler = mxUtils.bind(this, function(evt)
+		{
+			if (currentLabel != elt)
+			{
+				if (containsLabel)
+				{
+					this.labelIndex = index;
+				}
+				else if (graph.isSelectionEmpty())
+				{
+					this.diagramIndex = index;
+				}
+				else
+				{
+					this.currentIndex = index;
+				}
+				
+				if (currentLabel != null)
+				{
+					currentLabel.style.backgroundColor = this.inactiveTabBackgroundColor;
+					currentLabel.style.borderBottomWidth = '1px';
+				}
+
+				currentLabel = elt;
+				currentLabel.style.backgroundColor = '';
+				currentLabel.style.borderBottomWidth = '0px';
+				
+				if (currentPanel != panel)
+				{
+					if (currentPanel != null)
+					{
+						currentPanel.style.display = 'none';
+					}
+					
+					currentPanel = panel;
+					currentPanel.style.display = '';
+				}
+			}
+		});
+		
+		mxEvent.addListener(elt, 'click', clickHandler);
+		
+		// Prevents text selection
+	    mxEvent.addListener(elt, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown',
+        	mxUtils.bind(this, function(evt)
+    	{
+			evt.preventDefault();
+		}));
+		
+		if (index == ((containsLabel) ? this.labelIndex : ((graph.isSelectionEmpty()) ?
+			this.diagramIndex : this.currentIndex)))
+		{
+			// Invokes handler directly as a workaround for no click on DIV in KHTML.
+			clickHandler();
+		}
+	});
 	
+	var idx = 0;
+
 	if (graph.isSelectionEmpty())
 	{
 		mxUtils.write(label, mxResources.get('diagram'));
 		label.style.borderLeftWidth = '0px';
+
+		div.appendChild(label);
+		var diagramPanel = div.cloneNode(false);
+		this.panels.push(new DiagramFormatPanel(this, ui, diagramPanel));
+		this.container.appendChild(diagramPanel);
+		
+		if (Editor.styles != null)
+		{
+			diagramPanel.style.display = 'none';
+			label.style.width = '106px';
+			label.style.cursor = 'pointer';
+			label.style.backgroundColor = this.inactiveTabBackgroundColor;
+			
+			var label2 = label.cloneNode(false);
+			label2.style.borderLeftWidth = '1px';
+			label2.style.borderRightWidth = '1px';
+			label2.style.backgroundColor = this.inactiveTabBackgroundColor;
+			
+			addClickHandler(label, diagramPanel, idx++);
+			
+			var stylePanel = div.cloneNode(false);
+			stylePanel.style.display = 'none';
+			mxUtils.write(label2, mxResources.get('style'));
+			div.appendChild(label2);
+			this.panels.push(new DiagramStylePanel(this, ui, stylePanel));
+			this.container.appendChild(stylePanel);
+			
+			addClickHandler(label2, stylePanel, idx++);
+		}
 		
 		// Adds button to hide the format panel since
 		// people don't seem to find the toolbar button
 		// and the menu item in the format menu
 		if (this.showCloseButton)
 		{
+			var label2 = label.cloneNode(false);
+			label2.style.borderLeftWidth = '1px';
+			label2.style.borderRightWidth = '1px';
+			label2.style.borderBottomWidth = '1px';
+			label2.style.backgroundColor = this.inactiveTabBackgroundColor;
+			label2.style.position = 'absolute';
+			label2.style.right = '0px';
+			label2.style.top = '0px';
+			label2.style.width = '25px';
+			
 			var img = document.createElement('img');
 			img.setAttribute('border', '0');
 			img.setAttribute('src', Dialog.prototype.closeImage);
@@ -390,20 +499,20 @@ Format.prototype.refresh = function()
 			img.style.top = '8px';
 			img.style.cursor = 'pointer';
 			img.style.marginTop = '1px';
-			img.style.marginRight = '17px';
+			img.style.marginRight = '6px';
 			img.style.border = '1px solid transparent';
 			img.style.padding = '1px';
 			img.style.opacity = 0.5;
-			label.appendChild(img)
+			label2.appendChild(img)
 			
 			mxEvent.addListener(img, 'click', function()
 			{
 				ui.actions.get('formatPanel').funct();
 			});
+			
+			div.appendChild(label2);
 		}
 		
-		div.appendChild(label);
-		this.panels.push(new DiagramFormatPanel(this, ui, div));
 	}
 	else if (graph.isEditing())
 	{
@@ -413,71 +522,10 @@ Format.prototype.refresh = function()
 	}
 	else
 	{
-		var containsLabel = this.getSelectionState().containsLabel;
-		var currentLabel = null;
-		var currentPanel = null;
-		
-		var addClickHandler = mxUtils.bind(this, function(elt, panel, index)
-		{
-			var clickHandler = mxUtils.bind(this, function(evt)
-			{
-				if (currentLabel != elt)
-				{
-					if (containsLabel)
-					{
-						this.labelIndex = index;
-					}
-					else
-					{
-						this.currentIndex = index;
-					}
-					
-					if (currentLabel != null)
-					{
-						currentLabel.style.backgroundColor = this.inactiveTabBackgroundColor;
-						currentLabel.style.borderBottomWidth = '1px';
-					}
-	
-					currentLabel = elt;
-					currentLabel.style.backgroundColor = '';
-					currentLabel.style.borderBottomWidth = '0px';
-					
-					if (currentPanel != panel)
-					{
-						if (currentPanel != null)
-						{
-							currentPanel.style.display = 'none';
-						}
-						
-						currentPanel = panel;
-						currentPanel.style.display = '';
-					}
-				}
-			});
-			
-			mxEvent.addListener(elt, 'click', clickHandler);
-			
-			// Prevents text selection
-		    mxEvent.addListener(elt, (mxClient.IS_POINTER) ? 'pointerdown' : 'mousedown',
-	        	mxUtils.bind(this, function(evt)
-	    	{
-				evt.preventDefault();
-			}));
-			
-			if (index == ((containsLabel) ? this.labelIndex : this.currentIndex))
-			{
-				// Invokes handler directly as a workaround for no click on DIV in KHTML.
-				clickHandler();
-			}
-		});
-		
-		var idx = 0;
-
 		label.style.backgroundColor = this.inactiveTabBackgroundColor;
 		label.style.borderLeftWidth = '1px';
 		label.style.cursor = 'pointer';
 		label.style.width = (containsLabel) ? '50%' : '33.3%';
-		label.style.width = (containsLabel) ? '50%' : '33.3%';
 		var label2 = label.cloneNode(false);
 		var label3 = label2.cloneNode(false);
 
@@ -853,7 +901,7 @@ BaseFormatPanel.prototype.createStepper = function(input, update, step, height,
 /**
  * Adds the given option.
  */
-BaseFormatPanel.prototype.createOption = function(label, isCheckedFn, setCheckedFn, listener)
+BaseFormatPanel.prototype.createOption = function(label, isCheckedFn, setCheckedFn, listener, fn)
 {
 	var div = document.createElement('div');
 	div.style.padding = '6px 0px 1px 0px';
@@ -931,6 +979,11 @@ BaseFormatPanel.prototype.createOption = function(label, isCheckedFn, setChecked
 		listener.install(apply);
 		this.listeners.push(listener);
 	}
+	
+	if (fn != null)
+	{
+		fn(div);
+	}
 
 	return div;
 };
@@ -5509,6 +5562,443 @@ StyleFormatPanel.prototype.addStyleOps = function(div)
 	return div;
 };
 
+/**
+ * Adds the label menu items to the given menu and parent.
+ */
+DiagramStylePanel = function(format, editorUi, container)
+{
+	BaseFormatPanel.call(this, format, editorUi, container);
+	this.init();
+};
+
+mxUtils.extend(DiagramStylePanel, BaseFormatPanel);
+
+/**
+ * Adds the label menu items to the given menu and parent.
+ */
+DiagramStylePanel.prototype.init = function()
+{
+	var ui = this.editorUi;
+	var editor = ui.editor;
+	var graph = editor.graph;
+
+	this.container.appendChild(this.addView(this.createPanel()));
+};
+
+/**
+ * Adds the label menu items to the given menu and parent.
+ */
+DiagramStylePanel.prototype.addView = function(div)
+{
+	var ui = this.editorUi;
+	var editor = ui.editor;
+	var graph = editor.graph;
+	var model = graph.getModel();
+
+	div.style.whiteSpace = 'normal';
+
+	var cells = graph.getCells();
+	var rounded = true;
+	var sketch = true;
+	var curved = true;
+	
+	for (var i = 0; i < cells.length; i++)
+	{
+		var style = graph.getCurrentCellStyle(cells[i]);
+		
+		sketch = sketch && mxUtils.getValue(style, 'sketch', '0') == '1';
+		rounded = rounded && (!model.isVertex(cells[i]) || mxUtils.getValue(style, 'rounded', '0') == '1');
+		curved = curved && (!model.isEdge(cells[i]) || mxUtils.getValue(style, 'curved', '0') == '1');
+	}
+	
+	var opts = document.createElement('div');
+	opts.style.paddingBottom = '12px';
+	opts.style.marginRight = '16px';
+	
+	
+	var table = document.createElement('table');
+
+	if (mxClient.IS_QUIRKS)
+	{
+		table.style.fontSize = '1em';
+	}
+
+	table.style.width = '100%';
+	table.style.fontWeight = 'bold';
+	
+	var tbody = document.createElement('tbody');
+	var row = document.createElement('tr');
+	row.style.padding = '0px';
+	
+	var left = document.createElement('td');
+	left.style.padding = '0px';
+	left.style.width = '50%';
+	left.setAttribute('valign', 'middle');
+	
+	var right = left.cloneNode(true);
+	right.style.paddingLeft = '8px';
+	row.appendChild(left);
+	row.appendChild(right);
+	tbody.appendChild(row);
+	table.appendChild(tbody);
+	
+	// Sketch
+	left.appendChild(this.createOption(mxResources.get('sketch'), function()
+	{
+		return sketch;
+	}, function(checked)
+	{
+		graph.updateCellStyles('sketch', (checked) ? '1' : null, graph.getCells());
+		sketch = checked;
+		
+		if (checked)
+		{
+			graph.currentEdgeStyle['sketch'] = '1';
+			graph.currentVertexStyle['sketch'] = '1';
+		}
+		else
+		{
+			delete graph.currentEdgeStyle['sketch'];
+			delete graph.currentVertexStyle['sketch'];
+		}
+	}, null, function(div)
+	{
+		div.style.width = 'auto';
+	}));
+	
+	// Rounded
+	right.appendChild(this.createOption(mxResources.get('rounded'), function()
+	{
+		return rounded;
+	}, function(checked)
+	{
+		graph.updateCellStyles('rounded', (checked) ? '1' : null, graph.getCells(true, false));
+		rounded = checked;
+		
+		if (checked)
+		{
+			graph.currentVertexStyle['rounded'] = '1';
+		}
+		else
+		{
+			delete graph.currentVertexStyle['rounded'];
+		}
+	}, null, function(div)
+	{
+		div.style.width = 'auto';
+	}));
+
+	left = left.cloneNode(false);
+	right = left.cloneNode(false);
+	row = row.cloneNode(false);
+	row.appendChild(left);
+	row.appendChild(right);
+	tbody.appendChild(row);
+	
+	// Curved
+	left.appendChild(this.createOption(mxResources.get('curved'), function()
+	{
+		return curved;
+	}, function(checked)
+	{
+		graph.updateCellStyles('curved', (checked) ? '1' : null, graph.getCells(false, true));
+		curved = checked;
+		
+		if (checked)
+		{
+			graph.currentEdgeStyle['curved'] = '1';
+		}
+		else
+		{
+			delete graph.currentEdgeStyle['curved'];
+		}
+	}, null, function(div)
+	{
+		div.style.width = 'auto';
+	}));
+	
+	opts.appendChild(table);
+	div.appendChild(opts);
+
+	var defaultStyles = ['fillColor', 'strokeColor', 'fontColor', 'gradientColor'];
+	
+	var updateCells = mxUtils.bind(this, function(styles, graphStyle)
+	{
+		var cells = graph.getCells();
+		
+		model.beginUpdate();
+		try
+		{
+			for (var i = 0; i < cells.length; i++)
+			{
+				var style = graph.getCellStyle(cells[i]);
+				
+				// Handles special label background color
+				if (style['labelBackgroundColor'] != null)
+				{
+					graph.updateCellStyles('labelBackgroundColor', (graphStyle != null) ?
+						graphStyle.background : null, [cells[i]]);
+				}
+				
+				var edge = model.isEdge(cells[i]);
+				var newStyle = model.getStyle(cells[i]);
+				var current = (edge) ? graph.currentEdgeStyle : graph.currentVertexStyle;
+
+				for (var j = 0; j < styles.length; j++)
+				{
+					if ((style[styles[j]] != null && style[styles[j]] != mxConstants.NONE) ||
+						(styles[j] != mxConstants.STYLE_FILLCOLOR &&
+						styles[j] != mxConstants.STYLE_STROKECOLOR))
+					{
+						newStyle = mxUtils.setStyle(newStyle, styles[j], current[styles[j]]);
+					}
+				}
+				
+				model.setStyle(cells[i], newStyle);
+			}
+		}
+		finally
+		{
+			model.endUpdate();
+		}
+	});
+			
+	var removeStyles = mxUtils.bind(this, function(style, styles, defaultStyle)
+	{
+		if (style != null)
+		{
+			for (var j = 0; j < styles.length; j++)
+			{
+				if (((style[styles[j]] != null &&
+					style[styles[j]] != mxConstants.NONE) ||
+					(styles[j] != mxConstants.STYLE_FILLCOLOR &&
+					styles[j] != mxConstants.STYLE_STROKECOLOR)))
+				{
+					style[styles[j]] = defaultStyle[styles[j]];
+				}
+			}
+		}
+	});
+
+	var applyStyle = mxUtils.bind(this, function(style, result, cell, graphStyle, theGraph)
+	{
+		if (style != null)
+		{
+			if (cell != null)
+			{
+				// Handles special label background color
+				if (result['labelBackgroundColor'] != null)
+				{
+					var bg = (graphStyle != null) ? graphStyle.background : null;
+					theGraph = (theGraph != null) ? theGraph : graph;
+					
+					if (bg == null)
+					{
+						bg = theGraph.background;
+					}
+					
+					if (bg == null)
+					{
+						bg = theGraph.defaultPageBackgroundColor;
+					}
+					
+					result['labelBackgroundColor'] = bg;
+				}
+			}
+			
+			for (var key in style)
+			{
+				if (cell == null || ((result[key] != null &&
+					result[key] != mxConstants.NONE) ||
+					(key != mxConstants.STYLE_FILLCOLOR &&
+					key != mxConstants.STYLE_STROKECOLOR)))
+				{
+					result[key] = style[key];
+				}
+			}
+		}
+	});
+	
+	var createPreview = mxUtils.bind(this, function(commonStyle, vertexStyle, edgeStyle, graphStyle, container)
+	{
+		// Wrapper needed to catch events
+		var div = document.createElement('div');
+		div.style.cssText = 'position:absolute;display:inline-block;position:relative;width:100%;height:100%;overflow:hidden;pointer-events:none;';
+		container.appendChild(div);
+		
+		var graph2 = new Graph(div, null, null, graph.getStylesheet());
+		graph2.resetViewOnRootChange = false;
+		graph2.foldingEnabled = false;
+		graph2.gridEnabled = false;
+		graph2.autoScroll = false;
+		graph2.setTooltips(false);
+		graph2.setConnectable(false);
+		graph2.setPanning(false);
+		graph2.setEnabled(false);
+		
+		graph2.getCellStyle = function(cell)
+		{
+			var result = mxUtils.clone(Graph.prototype.getCellStyle.apply(this, arguments));
+			var defaultStyle = graph.stylesheet.getDefaultVertexStyle();
+			var appliedStyle = vertexStyle;
+			
+			if (model.isEdge(cell))
+			{
+				defaultStyle = graph.stylesheet.getDefaultEdgeStyle();
+				appliedStyle = edgeStyle;	
+			}
+			
+			removeStyles(result, defaultStyles, defaultStyle);
+			applyStyle(commonStyle, result, cell, graphStyle, graph2);
+			applyStyle(appliedStyle, result, cell, graphStyle, graph2);
+			
+			return result;
+		};
+		
+		// Avoid HTML labels to capture events in bubble phase
+		graph2.model.beginUpdate();
+		try
+		{
+			var v1 = graph2.insertVertex(graph2.getDefaultParent(), null, 'Shape', 14, 8, 70, 40, 'strokeWidth=2;');
+			var e1 = graph2.insertEdge(graph2.getDefaultParent(), null, 'Connector', v1, v1,
+				'edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;endSize=5;strokeWidth=2;')
+			e1.geometry.points = [new mxPoint(32, 70)];
+			e1.geometry.offset = new mxPoint(0, 8);
+		}
+		finally
+		{
+			graph2.model.endUpdate();
+		}
+	});
+
+	var addEntry = mxUtils.bind(this, function(commonStyle, vertexStyle, edgeStyle, graphStyle)
+	{
+		var panel = document.createElement('div');
+		panel.style.cssText = 'display:inline-block;position:relative;width:96px;height:90px;' +
+			'cursor:pointer;border:1px solid gray;margin:2px;overflow:hidden;';
+
+		if (graphStyle != null && graphStyle.background != null)
+		{
+			panel.style.backgroundColor = graphStyle.background;
+		}
+		
+		createPreview(commonStyle, vertexStyle, edgeStyle, graphStyle, panel); 
+
+		mxEvent.addGestureListeners(panel, mxUtils.bind(this, function(evt)
+		{
+			panel.style.opacity = 0.5;
+		}), null, mxUtils.bind(this, function(evt)
+		{
+			panel.style.opacity = 1;
+			graph.defaultVertexStyle = mxUtils.clone(ui.initialDefaultVertexStyle);
+			graph.defaultEdgeStyle = mxUtils.clone(ui.initialDefaultEdgeStyle);
+			
+			applyStyle(commonStyle, graph.defaultVertexStyle);
+			applyStyle(commonStyle, graph.defaultEdgeStyle);
+			applyStyle(vertexStyle, graph.defaultVertexStyle);
+			applyStyle(edgeStyle, graph.defaultEdgeStyle);
+			
+			if (sketch)
+			{
+				graph.currentEdgeStyle['sketch'] = '1';
+				graph.currentVertexStyle['sketch'] = '1';
+			}
+			else
+			{
+				graph.currentEdgeStyle['sketch'] = '0';
+				graph.currentVertexStyle['sketch'] = '0';
+			}
+				
+			if (rounded)
+			{
+				graph.currentVertexStyle['rounded'] = '1';
+			}
+			else
+			{
+				graph.currentVertexStyle['rounded'] = '0';
+			}
+			
+			if (curved)
+			{
+				graph.currentEdgeStyle['curved'] = '1';
+			}
+			else
+			{
+				graph.currentEdgeStyle['curved'] = '0';
+			}
+
+			model.beginUpdate();
+			try
+			{
+				ui.clearDefaultStyle();
+				updateCells(defaultStyles, graphStyle);
+				
+				var change = new ChangePageSetup(ui, (graphStyle != null) ? graphStyle.background : null);
+				change.ignoreImage = true;
+				model.execute(change);
+				
+				model.execute(new ChangeGridColor(ui, (graphStyle != null) ? graphStyle.gridColor ||
+					graph.view.defaultGridColor : graph.view.defaultGridColor));
+			}
+			finally
+			{
+				model.endUpdate();
+			}
+		}));
+		
+		mxEvent.addListener(panel, 'mouseenter', mxUtils.bind(this, function(evt)
+		{
+			var prev = graph.getCellStyle;
+			var prevBg = graph.background;
+			var prevGrid = graph.view.gridColor;
+
+			graph.background = (graphStyle != null) ? graphStyle.background : null;
+			graph.view.gridColor = (graphStyle != null) ? graphStyle.gridColor ||
+				graph.view.defaultGridColor : graph.view.defaultGridColor;
+			
+			graph.getCellStyle = function(cell)
+			{
+				var result = mxUtils.clone(prev.apply(this, arguments));
+				
+				var defaultStyle = graph.stylesheet.getDefaultVertexStyle();
+				var appliedStyle = vertexStyle;
+				
+				if (model.isEdge(cell))
+				{
+					defaultStyle = graph.stylesheet.getDefaultEdgeStyle();
+					appliedStyle = edgeStyle;	
+				}
+				
+				removeStyles(result, defaultStyles, defaultStyle);
+				applyStyle(commonStyle, result, cell, graphStyle);
+				applyStyle(appliedStyle, result, cell, graphStyle);
+				
+				return result;
+			};
+			
+			graph.refresh();
+			graph.getCellStyle = prev;
+			graph.background = prevBg;
+			graph.view.gridColor = prevGrid;
+		}));
+		
+		mxEvent.addListener(panel, 'mouseleave', mxUtils.bind(this, function(evt)
+		{
+			graph.refresh();
+		}));
+		
+		div.appendChild(panel);
+	});
+	
+	for (var i = 0; i < Editor.styles.length; i++)
+	{
+		var s = Editor.styles[i];
+		addEntry(s.commonStyle, s.vertexStyle, s.edgeStyle, s.graph);
+	}
+	
+	return div;
+};
+
 /**
  * Adds the label menu items to the given menu and parent.
  */

+ 15 - 0
src/main/webapp/js/mxgraph/Graph.js

@@ -1596,6 +1596,21 @@ Graph.prototype.init = function(container)
 	 */
 	Graph.prototype.currentTranslate = new mxPoint(0, 0);
 	
+	/**
+	 * 
+	 */
+	Graph.prototype.getCells = function(vertices, edges)
+	{
+		vertices = (vertices != null) ? vertices : true;
+		edges = (edges != null) ? edges : true;
+		var model = this.model;
+		
+		return model.filterDescendants(function(cell)
+		{
+			return (vertices && model.isVertex(cell)) || (edges && model.isEdge(cell));
+		}, model.getRoot());
+	};
+
 	/**
 	 * Returns the cell for editing the given cell.
 	 */

+ 6 - 1
src/main/webapp/js/mxgraph/Sidebar.js

@@ -296,7 +296,12 @@ Sidebar.prototype.showTooltip = function(elt, cells, w, h, title, showLabel)
 				this.graph2.labelsVisible = (showLabel == null || showLabel);
 				var fo = mxClient.NO_FO;
 				mxClient.NO_FO = Editor.prototype.originalNoForeignObject;
-				this.graph2.addCells(cells);
+				
+				// Applies current style for preview
+				var temp = this.graph2.cloneCells(cells);
+				this.editorUi.insertHandler(temp, null, this.graph2.model);
+				this.graph2.addCells(temp);
+				
 				mxClient.NO_FO = fo;
 				
 				var bounds = this.graph2.getGraphBounds();

+ 12 - 12
src/main/webapp/js/mxgraph/Toolbar.js

@@ -183,7 +183,7 @@ Toolbar.prototype.addTableDropDown = function()
 	// KNOWN: All table stuff does not work with undo/redo
 	// KNOWN: Lost focus after click on submenu with text (not icon) in quirks and IE8. This is because the TD seems
 	// to catch the focus on click in these browsers. NOTE: Workaround in mxPopupMenu for icon items (without text).
-	var elt = this.addMenuFunction('geIcon geSprite geSprite-table', mxResources.get('table'), false, mxUtils.bind(this, function(menu)
+	var menuElt = this.addMenuFunction('geIcon geSprite geSprite-table', mxResources.get('table'), false, mxUtils.bind(this, function(menu)
 	{
 		var graph = this.editorUi.editor.graph;
 		var cell = graph.getSelectionCell();
@@ -194,7 +194,7 @@ Toolbar.prototype.addTableDropDown = function()
     	}
 		else
     	{
-			elt = menu.addItem('', null, mxUtils.bind(this, function()
+			var elt = menu.addItem('', null, mxUtils.bind(this, function()
 			{
 				try
 				{
@@ -277,17 +277,17 @@ Toolbar.prototype.addTableDropDown = function()
     	}
 	}));
 	
-	elt.style.position = 'relative';
-	elt.style.whiteSpace = 'nowrap';
-	elt.style.overflow = 'hidden';
-	elt.innerHTML = '<div class="geSprite geSprite-table" style="margin-left:-2px;"></div>' + this.dropdownImageHtml;
-	elt.style.width = (mxClient.IS_QUIRKS) ? '50px' : '30px';
+	menuElt.style.position = 'relative';
+	menuElt.style.whiteSpace = 'nowrap';
+	menuElt.style.overflow = 'hidden';
+	menuElt.innerHTML = '<div class="geSprite geSprite-table" style="margin-left:-2px;"></div>' + this.dropdownImageHtml;
+	menuElt.style.width = (mxClient.IS_QUIRKS) ? '50px' : '30px';
 
 	// Fix for item size in kennedy theme
 	if (EditorUi.compactUi)
 	{
-		elt.getElementsByTagName('img')[0].style.left = '22px';
-		elt.getElementsByTagName('img')[0].style.top = '5px';
+		menuElt.getElementsByTagName('img')[0].style.left = '22px';
+		menuElt.getElementsByTagName('img')[0].style.top = '5px';
 	}
 	
 	// Connects to insert menu enabled state
@@ -295,15 +295,15 @@ Toolbar.prototype.addTableDropDown = function()
 	
 	// Workaround for possible not a function
 	// when extending HTML objects
-	if (menu != null && typeof elt.setEnabled === 'function')
+	if (menu != null && typeof menuElt.setEnabled === 'function')
 	{
 		menu.addListener('stateChanged', function()
 		{
-			elt.setEnabled(menu.enabled);
+			menuElt.setEnabled(menu.enabled);
 		});
 	}
 	
-	return elt;
+	return menuElt;
 };
 
 /**

File diff suppressed because it is too large
+ 813 - 810
src/main/webapp/js/viewer-static.min.js


File diff suppressed because it is too large
+ 813 - 810
src/main/webapp/js/viewer.min.js


+ 2 - 2
src/main/webapp/service-worker.js

@@ -6,11 +6,11 @@ if (workbox)
 	workbox.precaching.precacheAndRoute([
   {
     "url": "js/app.min.js",
-    "revision": "155c9b79a191113daecc414c9a898328"
+    "revision": "5c78133585f46412bda6b075020dd391"
   },
   {
     "url": "js/extensions.min.js",
-    "revision": "f401b03f1145a3a76eba114ec7e80b83"
+    "revision": "6025816d5cdf862d2ad3f199c4a5af47"
   },
   {
     "url": "js/stencils.min.js",