소스 검색

6.0.1.3 release

Former-commit-id: 3cd747cb87bc163442b8da06c949d897e883845d
David Benson 8 년 전
부모
커밋
fd4103d904

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+09-NOV-2016: 6.0.1.3
+
+- Shift+Drop ignores embedded XML in images
+- Alt+Drop ignores highlighted drop target
+
 07-NOV-2016: 6.0.1.2
 
 - Adds new electrical shapes

+ 1 - 1
VERSION

@@ -1 +1 @@
-6.0.1.2
+6.0.1.3

+ 39 - 36
src/com/mxgraph/io/gliffy/importer/GliffyDiagramConverter.java

@@ -24,16 +24,16 @@ import com.mxgraph.io.gliffy.model.Constraint.ConstraintData;
 import com.mxgraph.io.gliffy.model.Constraints;
 import com.mxgraph.io.gliffy.model.Diagram;
 import com.mxgraph.io.gliffy.model.EmbeddedResources.Resource;
+import com.mxgraph.io.gliffy.model.GliffyObject;
+import com.mxgraph.io.gliffy.model.GliffyText;
 import com.mxgraph.io.gliffy.model.Graphic;
 import com.mxgraph.io.gliffy.model.Graphic.GliffyImage;
 import com.mxgraph.io.gliffy.model.Graphic.GliffyLine;
 import com.mxgraph.io.gliffy.model.Graphic.GliffyMindmap;
 import com.mxgraph.io.gliffy.model.Graphic.GliffyShape;
 import com.mxgraph.io.gliffy.model.Graphic.GliffySvg;
-import com.mxgraph.io.gliffy.model.GliffyObject;
 import com.mxgraph.model.mxCell;
 import com.mxgraph.model.mxGeometry;
-import com.mxgraph.model.mxICell;
 import com.mxgraph.util.mxDomUtils;
 import com.mxgraph.util.mxPoint;
 import com.mxgraph.util.mxXmlUtils;
@@ -103,31 +103,6 @@ public class GliffyDiagramConverter
 
 	}
 
-	@SuppressWarnings("unused")
-	private void correctLineEndings()
-	{
-		java.lang.Object[] edges = drawioDiagram.getAllEdges(new java.lang.Object[] { drawioDiagram.getDefaultParent() });
-
-		for (int i = 0; i < edges.length; i++)
-		{
-			mxCell edge = (mxCell) edges[i];
-
-			mxICell source = edge.getTerminal(true);
-			mxICell target = edge.getTerminal(false);
-			mxPoint srcP = edge.getGeometry().getSourcePoint();
-			mxPoint trgtP = edge.getGeometry().getTargetPoint();
-
-			// TODO should this be logging instead?
-//			if (target != null)
-//			{
-//				if (trgtP != null)
-//					System.out.println(target.getGeometry().contains(trgtP.getX(), trgtP.getY()));
-//				if (srcP != null)
-//					System.out.println(source.getGeometry().contains(srcP.getX(), srcP.getY()));
-//			}
-		}
-	}
-
 	/**
 	 * Imports the objects into the draw.io diagram. Recursively adds the children 
 	 */
@@ -135,7 +110,7 @@ public class GliffyDiagramConverter
 	{
 		mxCell parent = gliffyParent != null ? gliffyParent.mxObject : null;
 		
-		if (!obj.isLine())
+		//if (!obj.isLine())
 		{
 			drawioDiagram.addCell(obj.mxObject, parent);
 
@@ -153,7 +128,7 @@ public class GliffyDiagramConverter
 				}
 			}
 		}
-		else
+		if (obj.isLine())
 		{
 			// gets the terminal cells for the edge
 			mxCell startTerminal = getTerminalCell(obj, true);
@@ -161,7 +136,7 @@ public class GliffyDiagramConverter
 
 			drawioDiagram.addCell(obj.getMxObject(), parent, null, startTerminal, endTerminal);
 
-			applyControlPoints(obj, startTerminal, endTerminal);
+			setWaypoints(obj, startTerminal, endTerminal);
 		}
 	}
 
@@ -226,9 +201,13 @@ public class GliffyDiagramConverter
 	}
 
 	/**
+	 * Sets the waypoints
 	 * 
+	 * @param object Gliffy line
+	 * @param startTerminal starting point
+	 * @param endTerminal ending point
 	 */
-	private void applyControlPoints(GliffyObject object, mxCell startTerminal, mxCell endTerminal)
+	private void setWaypoints(GliffyObject object, mxCell startTerminal, mxCell endTerminal)
 	{
 		mxCell cell = object.getMxObject();
 		mxGeometry geo = drawioDiagram.getModel().getGeometry(cell);
@@ -268,6 +247,7 @@ public class GliffyDiagramConverter
 		}
 
 		drawioDiagram.getModel().setGeometry(cell, geo);
+		
 	}
 
 	/**
@@ -288,7 +268,7 @@ public class GliffyDiagramConverter
 			}
 			
 			// don't collect for swimlanes and mindmaps, their children are treated differently
-			if (object.isGroup())
+			if (object.isGroup() || (object.isLine() && object.hasChildren()))
 			{
 				collectVerticesAndConvert(vertices, object.children, object);
 			}
@@ -363,8 +343,11 @@ public class GliffyDiagramConverter
 				style.append("shape=" + StencilTranslator.translate(gliffyObject.uid)).append(";");
 				style.append("shadow=" + (shape.dropShadow ? 1 : 0)).append(";");
 				style.append("strokeWidth=" + shape.strokeWidth).append(";");
-				style.append("fillColor=" + shape.fillColor).append(";");
-				style.append("strokeColor=" + shape.strokeColor).append(";");
+				
+				if(style.lastIndexOf("fillColor") == -1)
+					style.append("fillColor=" + shape.fillColor).append(";");
+				if(style.lastIndexOf("strokeColor") == -1)
+					style.append("strokeColor=" + shape.strokeColor).append(";");
 
 				if (shape.gradient)
 				{
@@ -404,7 +387,27 @@ public class GliffyDiagramConverter
 				if (gliffyObject.parent != null && !gliffyObject.parent.isGroup()) 
 				{
 					mxGeometry parentGeometry = gliffyObject.parent.mxObject.getGeometry();
-					cell.setGeometry(new mxGeometry(0, 0, parentGeometry.getWidth(), parentGeometry.getHeight()));
+					
+					//if text is a child of a line, special positioning is in place
+					if(gliffyObject.parent.isLine()) 
+					{
+						/* Gliffy's text offset is a float in the range of [0,1]
+						 * draw.io's text offset is a float in the range of [-1,-1] (while still keeping the text within the line)
+						 * The equation that translates Gliffy offset to draw.io offset is : G*2 - 1 = D 
+						 */
+						mxGeometry mxGeo = new mxGeometry(graphic.Text.lineTValue != null ? graphic.Text.lineTValue * 2 -1 : GliffyText.DEFAULT_LINE_T_VALUE, 0, 0, 0);
+						mxGeo.setOffset(new mxPoint());
+						cell.setGeometry(mxGeo);
+						
+						style.append("labelBackgroundColor=" + gliffyDiagram.stage.getBackgroundColor()).append(";");
+						//should we force horizontal align for text on lines?
+						style.append("align=center;");
+					}
+					else 
+					{
+						cell.setGeometry(new mxGeometry(0, 0, parentGeometry.getWidth(), parentGeometry.getHeight()));
+					}
+					
 					cell.getGeometry().setRelative(true);
 				}
 			}
@@ -523,11 +526,11 @@ public class GliffyDiagramConverter
 		if (!gliffyObject.isLine() && textObject != null)
 		{
 			style.append(textObject.graphic.getText().getStyle());
+			cell.setValue(textObject.getText());
 		}
 		
 		if (textObject != null) 
 		{
-			cell.setValue(textObject.getText());
 			style.append("html=1;nl2Br=0;whiteSpace=wrap");
 		}
 		

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 373 - 239
src/com/mxgraph/io/gliffy/importer/gliffyTranslation.properties


+ 34 - 20
src/com/mxgraph/io/gliffy/model/GliffyText.java

@@ -5,7 +5,9 @@ import java.util.regex.Pattern;
 
 public class GliffyText
 {
-
+	//places the text in the middle of the line
+	public static Double DEFAULT_LINE_T_VALUE = 0.5; 
+	
 	private String html;
 
 	private String valign;
@@ -24,8 +26,8 @@ public class GliffyText
 	private Integer paddingBottom;
 
 	private Integer paddingTop;
-
-	public double lineTValue;
+	
+	public Double lineTValue = DEFAULT_LINE_T_VALUE;
 
 	public Integer linePerpValue;
 
@@ -54,25 +56,37 @@ public class GliffyText
 
 		//vertical label position
 		if (vposition.equals("above"))
-			sb.append("verticalLabelPosition=top;");
+		{
+			sb.append("verticalLabelPosition=top;").append(
+					"verticalAlign=bottom;");
+		}
 		else if (vposition.equals("below"))
-			sb.append("verticalLabelPosition=bottom;");
+		{
+			sb.append("verticalLabelPosition=bottom;").append(
+					"verticalAlign=top;");
+		}
 		else if (vposition.equals("none"))
-			sb.append("verticalLabelPosition=middle;");
-		
-		//vertical label align
-		sb.append("verticalAlign=").append(valign).append(";");
-		
-		//horizontal label position
-		if (hposition.equals("none"))
-			sb.append("labelPosition=center;");
-		else 
-			sb.append("labelPosition=").append(hposition).append(";");
-		
-		//horizontal label align
-		if (halign != null)
-			sb.append("align=").append(halign).append(";");
-		
+		{
+			sb.append("verticalAlign=").append(valign).append(";");
+		}
+
+		if (hposition.equals("left"))
+		{
+			sb.append("labelPosition=left;").append("align=right;");
+		}
+		else if (hposition.equals("right"))
+		{
+			sb.append("labelPosition=right;").append("align=left;");
+		}
+		else if (hposition.equals("none"))
+		{
+			String hAlign = getHorizontalTextAlignment();
+			if (hAlign != null)
+			{
+				sb.append("align=").append(hAlign).append(";");
+			}
+		}
+
 		sb.append("spacingLeft=").append(paddingLeft).append(";");
 		sb.append("spacingRight=").append(paddingRight).append(";");
 		sb.append("spacingTop=").append(paddingTop).append(";");

+ 1 - 1
war/WEB-INF/appengine-web.xml

@@ -2,7 +2,7 @@
 <appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
 	<application>drawdotio</application>
 	<!-- IMPORTANT! DO NOT CHANGE THIS VALUE IN SOURCE CONTROL! -->
-	<version>test</version>
+	<version>6-0-1-3</version>
 	
 	<!-- Configure java.util.logging -->
 	<system-properties>

+ 1 - 1
war/cache.manifest

@@ -1,7 +1,7 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 11/07/2016 11:21 AM
+# 11/09/2016 04:11 PM
 
 /app.html
 /index.html?offline=1

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 631 - 629
war/js/app.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 608 - 604
war/js/atlas-viewer.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 624 - 622
war/js/atlas.min.js


+ 5 - 6
war/js/diagramly/App.js

@@ -595,11 +595,6 @@ App.prototype.defaultUserPicture = 'https://lh3.googleusercontent.com/-HIzvXUy6Q
  */
 App.prototype.micImage = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA5UlEQVR4Xr3SMYrCQBTGcSfIQiAgRIS9hOANBCurPUAuIAp7A7FVsFkIbLGYA9gKtoKNYG3jll5AFNKG518YMD6SISD4wY9J4MvkMYwRkZqOMSZkifGFe1b4pnvW3TqK8oMo14twxUgXPRSlDxU7TcUNPqATlG7wCi93cA2Iq2x7l7IJsgofB6UTiEjKklFqsabQSdFA5jqDAzrYQGeNNv5d9yDBEAME6NreFmP8Yuma4A8hFpiLSFNAYYYYn0jwCIUnxMcER4h1whS+7hseXKcu9ifGeQ+qeO8GjN7DPve+Q6+oewPhmE63Qfsb6AAAAABJRU5ErkJggg==';
 
-/**
- * Contains the default XML for an empty diagram.
- */
-App.prototype.emptyDiagramXml = '<mxGraphModel><root><mxCell id="0"/><mxCell id="1" parent="0"/></root></mxGraphModel>';
-
 /**
  * 
  */
@@ -2923,7 +2918,11 @@ App.prototype.createFile = function(title, data, libs, mode, done, replace, fold
 		
 		var error = mxUtils.bind(this, function(resp)
 		{
-			bg.parentNode.removeChild(bg);
+			if (bg.parentNode != null)
+			{
+				bg.parentNode.removeChild(bg);
+			}
+			
 			this.spinner.stop();
 			
 			if (resp == null && this.getCurrentFile() == null && this.dialog == null)

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 60 - 59
war/js/diagramly/EditorUi.js


+ 138 - 62
war/js/diagramly/GraphViewer.js

@@ -6,6 +6,68 @@
  * https://support.draw.io/pages/viewpage.action?pageId=12878123
  */
 GraphViewer = function(container, xmlNode, graphConfig)
+{
+	this.init(container, xmlNode, graphConfig);
+};
+
+// Editor inherits from mxEventSource
+mxUtils.extend(GraphViewer, mxEventSource);
+
+/**
+ * Redirects editing to absolue URLs.
+ */
+GraphViewer.prototype.editBlankUrl = 'https://www.draw.io/?client=1';
+
+/**
+ * Redirects editing to absolue URLs.
+ */
+GraphViewer.prototype.editBlankFallbackUrl = 'https://www.draw.io/?create=drawdata&splash=0';
+
+/**
+ * Base URL for relative images.
+ */
+GraphViewer.prototype.imageBaseUrl = 'https://www.draw.io/';
+
+/**
+ * Redirects editing to absolue URLs.
+ */
+GraphViewer.prototype.toolbarHeight = (document.compatMode == 'BackCompat') ? 28 : 30;
+
+/**
+ * Redirects editing to absolue URLs.
+ */
+GraphViewer.prototype.lightboxChrome = true;
+
+/**
+ * Redirects editing to absolue URLs.
+ */
+GraphViewer.prototype.lightboxZIndex = 999;
+
+/**
+ * Redirects editing to absolue URLs.
+ */
+GraphViewer.prototype.toolbarZIndex = 999;
+
+/**
+ * Base URL for relative images.
+ */
+GraphViewer.prototype.imageBaseUrl = 'https://www.draw.io/';
+
+/**
+ * If automatic fit should be enabled if zoom is disabled. Default is true.
+ */
+GraphViewer.prototype.autoFit = true;
+
+/**
+ * Specifies if the constructur should delay the rendering if the container
+ * is not visible by default.
+ */
+GraphViewer.prototype.checkVisibleState = true;
+
+/**
+ * Initializes the viewer.
+ */
+GraphViewer.prototype.init = function(container, xmlNode, graphConfig)
 {
 	this.graphConfig = (graphConfig != null) ? graphConfig : {};
 	this.autoFit = (graphConfig['auto-fit'] != null) ?
@@ -174,57 +236,6 @@ GraphViewer = function(container, xmlNode, graphConfig)
 	}
 };
 
-/**
- * Redirects editing to absolue URLs.
- */
-GraphViewer.prototype.editBlankUrl = 'https://www.draw.io/?client=1';
-
-/**
- * Redirects editing to absolue URLs.
- */
-GraphViewer.prototype.editBlankFallbackUrl = 'https://www.draw.io/?create=drawdata&splash=0';
-
-/**
- * Base URL for relative images.
- */
-GraphViewer.prototype.imageBaseUrl = 'https://www.draw.io/';
-
-/**
- * Redirects editing to absolue URLs.
- */
-GraphViewer.prototype.toolbarHeight = (document.compatMode == 'BackCompat') ? 28 : 30;
-
-/**
- * Redirects editing to absolue URLs.
- */
-GraphViewer.prototype.lightboxChrome = true;
-
-/**
- * Redirects editing to absolue URLs.
- */
-GraphViewer.prototype.lightboxZIndex = 999;
-
-/**
- * Redirects editing to absolue URLs.
- */
-GraphViewer.prototype.toolbarZIndex = 999;
-
-/**
- * Base URL for relative images.
- */
-GraphViewer.prototype.imageBaseUrl = 'https://www.draw.io/';
-
-/**
- * If automatic fit should be enabled if zoom is disabled. Default is true.
- */
-GraphViewer.prototype.autoFit = true;
-
-/**
- * Specifies if the constructur should delay the rendering if the container
- * is not visible by default.
- */
-GraphViewer.prototype.checkVisibleState = true;
-
 /**
  * 
  */
@@ -262,7 +273,7 @@ GraphViewer.prototype.getImageUrl = function(url)
 /**
  * 
  */
-GraphViewer.prototype.updateGraphXml = function(xmlNode)
+GraphViewer.prototype.setFileNode = function(xmlNode)
 {
 	if (this.xmlNode == null)
 	{
@@ -294,6 +305,50 @@ GraphViewer.prototype.updateGraphXml = function(xmlNode)
 	}
 };
 
+/**
+ * 
+ */
+GraphViewer.prototype.setXmlNode = function(xmlNode)
+{
+	this.xmlDocument = xmlNode.ownerDocument;
+	this.xml = mxUtils.getXml(xmlNode);
+	this.xmlNode = xmlNode;
+	
+	this.updateGraphXml(xmlNode);
+	
+	this.fireEvent(new mxEventObject('xmlNodeChanged'));
+};
+
+/**
+ * 
+ */
+GraphViewer.prototype.updateGraphXml = function(xmlNode)
+{
+	if (this.graph != null)
+	{
+		this.graph.view.translate = new mxPoint();
+		this.graph.view.scale = 1;
+		this.graph.getModel().clear();
+		
+		// Restores initial CSS state
+		if (this.widthIsEmpty)
+		{
+			this.graph.container.style.width = '';
+			this.graph.container.style.height = '';
+		}
+
+		this.editor.setGraphXml(xmlNode);
+		this.positionGraph();
+		
+		this.graph.initialViewState = {
+			translate: this.graph.view.translate.clone(),
+			scale: this.graph.view.scale
+		};
+	}
+	
+	this.fireEvent(new mxEventObject('graphChanged'));
+};
+
 /**
  * 
  */
@@ -715,7 +770,6 @@ GraphViewer.prototype.addToolbar = function()
 	
 	var tokens = this.toolbarItems;
 	var buttonCount = 0;
-	var diagrams = [];
 	
 	function addButton(fn, imgSrc, tip, enabled)
 	{
@@ -770,12 +824,6 @@ GraphViewer.prototype.addToolbar = function()
 		return a;
 	};
 
-	// Adds page placeholders
-	if (this.xmlNode.nodeName == 'mxfile')
-	{
-		diagrams = this.xmlNode.getElementsByTagName('diagram');
-	}
-	
 	var layersDialog = null;
 	var layersDialogEntered = false;
 	var pageInfo = null;
@@ -784,12 +832,13 @@ GraphViewer.prototype.addToolbar = function()
 	{
 		var token = tokens[i];
 		
-		if (token == 'pages' && diagrams.length > 1)
+		if (token == 'pages')
 		{
+			var diagrams = [];
+
 			pageInfo = container.ownerDocument.createElement('div');
 			pageInfo.style.cssText = 'display:inline-block;position:relative;padding:3px 4px 0 4px;' +
 				'vertical-align:top;font-family:Helvetica,Arial;font-size:12px;top:4px;cursor:default;'
-			mxUtils.write(pageInfo, (this.currentPage + 1) + ' / ' + diagrams.length);
 			mxUtils.setOpacity(pageInfo, 70);
 			
 			var prevButton = addButton(mxUtils.bind(this, function()
@@ -817,6 +866,34 @@ GraphViewer.prototype.addToolbar = function()
 			
 			nextButton.style.paddingLeft = '0px';
 			nextButton.style.paddingRight = '0px';
+			
+			var lastXmlNode = null;
+			
+			var update = mxUtils.bind(this, function()
+			{
+				if (this.xmlNode == null || this.xmlNode.nodeName != 'mxfile')
+				{
+					diagrams = [];
+				}
+				if (this.xmlNode != lastXmlNode)
+				{
+					diagrams = this.xmlNode.getElementsByTagName('diagram');
+					this.currentPage = 0;
+					pageInfo.innerHTML = '';
+					mxUtils.write(pageInfo, (this.currentPage + 1) + ' / ' + diagrams.length);
+					lastXmlNode = this.xmlNode;
+				}
+				
+				pageInfo.style.display = (diagrams.length > 1) ? 'inline-block' : 'none';
+				prevButton.style.display = pageInfo.style.display;
+				nextButton.style.display = pageInfo.style.display;
+			});
+			
+			var model = this.graph.getModel();
+
+			// LATER: Add event for setGraphXml
+			this.addListener('xmlNodeChanged', update);
+			update();
 		}
 		else if (token == 'zoom')
 		{
@@ -1265,7 +1342,6 @@ GraphViewer.prototype.showLocalLightbox = function()
 		document.body.appendChild(lightbox);
 		document.body.appendChild(closeImg);
 		
-		console.log('xml', this.xml);
 		ui.setFileData(this.xml);
 
 		mxUtils.setPrefixedStyle(lightbox.style, 'transform', 'rotateY(0deg)');

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 304 - 303
war/js/embed-static.min.js


+ 2 - 35
war/js/mxgraph/Actions.js

@@ -369,40 +369,7 @@ Actions.prototype.init = function()
 
 		    		if (value != null)
 		    		{
-		    			if (value.length == 0)
-		    			{
-		    				document.execCommand('unlink', false);
-		    			}
-		    			else
-		    			{
-							// To find the new link, we create a list of all existing links first
-							var tmp = graph.cellEditor.textarea.getElementsByTagName('a');
-							var oldLinks = [];
-							
-							for (var i = 0; i < tmp.length; i++)
-							{
-								oldLinks.push(tmp[i]);
-							}
-	
-							// LATER: Fix inserting link/image in IE8/quirks after focus lost
-							document.execCommand('createlink', false, mxUtils.trim(value));
-	
-							// Adds target="_blank" for the new link
-							var newLinks = graph.cellEditor.textarea.getElementsByTagName('a');
-							
-							if (newLinks.length == oldLinks.length + 1)
-							{
-								// Inverse order in favor of appended links
-								for (var i = newLinks.length - 1; i >= 0; i--)
-								{
-									if (i == 0 || newLinks[i] != oldLinks[i - 1])
-									{
-										newLinks[i].setAttribute('target', '_blank');
-										break;
-									}
-								}
-							}
-		    			}
+		    			graph.insertLink(value);
 					}
 				}));
 			}
@@ -1070,7 +1037,7 @@ Actions.prototype.init = function()
 			    			{
 			    				var pt = graph.getFreeInsertPoint();
 			    				cells = [graph.insertVertex(graph.getDefaultParent(), null, '', pt.x, pt.y, w, h,
-			    						'shape=image;verticalLabelPosition=bottom;verticalAlign=top;')];
+			    						'shape=image;imageAspect=0;aspect=fixed;verticalLabelPosition=bottom;verticalAlign=top;')];
 			    				select = cells;
 			    			}
 			    			

+ 1 - 0
war/js/mxgraph/Dialogs.js

@@ -3214,6 +3214,7 @@ var LayersWindow = function(editorUi, x, y, w, h)
 			if (graph.getDefaultParent() == child)
 			{
 				ldiv.style.background = '#e6eff8';
+				ldiv.style.fontWeight = 'bold';
 				selectionLayer = child;
 			}
 			else

+ 4 - 1
war/js/mxgraph/EditorUi.js

@@ -2010,7 +2010,10 @@ EditorUi.prototype.addBeforeUnloadListener = function()
 	// This must be disabled during save and image export
 	window.onbeforeunload = mxUtils.bind(this, function()
 	{
-		return this.onBeforeUnload();
+		if (!this.editor.chromeless)
+		{
+			return this.onBeforeUnload();
+		}
 	});
 };
 

+ 62 - 6
war/js/mxgraph/Graph.js

@@ -1060,7 +1060,7 @@ Graph.prototype.getPageLayout = function()
 /**
  * Sanitizes the given HTML markup.
  */
-Graph.prototype.sanitizeHtml = function(value)
+Graph.prototype.sanitizeHtml = function(value, editing)
 {
 	// Uses https://code.google.com/p/google-caja/wiki/JsHtmlSanitizer
 	// NOTE: Original minimized sanitizer was modified to support data URIs for images
@@ -4382,7 +4382,8 @@ if (typeof mxVertexHandler != 'undefined')
 		};
 
 		/**
-		 * Adds event handler for links and lightbox.
+		 * Adds a handler for clicking on shapes with links. This replaces all links in labels
+		 * as a side-effect and adds a target=_blank attribute if required.
 		 */
 		Graph.prototype.addClickHandler = function(highlight, beforeClick, onClick)
 		{
@@ -4697,6 +4698,48 @@ if (typeof mxVertexHandler != 'undefined')
 				}
 			}
 		};
+				
+		/**
+		 * Inserts the given image at the cursor in a content editable text box using
+		 * the insertimage command on the document instance.
+		 */
+		Graph.prototype.insertLink = function(value)
+		{
+			if (value.length == 0)
+			{
+				document.execCommand('unlink', false);
+			}
+			else
+			{
+				// To find the new link, we create a list of all existing links first
+				var tmp = this.cellEditor.textarea.getElementsByTagName('a');
+				var oldLinks = [];
+				
+				for (var i = 0; i < tmp.length; i++)
+				{
+					oldLinks.push(tmp[i]);
+				}
+
+				// LATER: Fix inserting link/image in IE8/quirks after focus lost
+				document.execCommand('createlink', false, mxUtils.trim(value));
+
+				// Adds target="_blank" for the new link
+				var newLinks = this.cellEditor.textarea.getElementsByTagName('a');
+				
+				if (newLinks.length == oldLinks.length + 1)
+				{
+					// Inverse order in favor of appended links
+					for (var i = newLinks.length - 1; i >= 0; i--)
+					{
+						if (i == 0 || newLinks[i] != oldLinks[i - 1])
+						{
+							newLinks[i].setAttribute('target', '_blank');
+							break;
+						}
+					}
+				}
+			}
+		};
 		
 		/**
 		 * 
@@ -5623,7 +5666,7 @@ if (typeof mxVertexHandler != 'undefined')
 					content = mxUtils.replaceTrailingNewlines(content, '<div><br></div>');
 				}
 				
-			    content = this.graph.sanitizeHtml((nl2Br) ? content.replace(/\n/g, '').replace(/&lt;br\s*.?&gt;/g, '<br>') : content);
+			    content = this.graph.sanitizeHtml((nl2Br) ? content.replace(/\n/g, '').replace(/&lt;br\s*.?&gt;/g, '<br>') : content, true);
 				this.textarea.className = 'mxCellEditor mxPlainTextEditor';
 				
 				var size = mxConstants.DEFAULT_FONTSIZE;
@@ -5656,7 +5699,7 @@ if (typeof mxVertexHandler != 'undefined')
 			    	content = content.substring(0, content.length - 1);
 			    }
 			    
-				content = this.graph.sanitizeHtml((nl2Br) ? content.replace(/\n/g, '<br/>') : content)
+				content = this.graph.sanitizeHtml((nl2Br) ? content.replace(/\n/g, '<br/>') : content, true)
 				this.textarea.className = 'mxCellEditor geContentEditable';
 				
 				var size = mxUtils.getValue(state.style, mxConstants.STYLE_FONTSIZE, mxConstants.DEFAULT_FONTSIZE);
@@ -5788,7 +5831,7 @@ if (typeof mxVertexHandler != 'undefined')
 					result = result.replace(/\n/g, '<br/>');
 				}
 				
-				result = this.graph.sanitizeHtml(result);
+				result = this.graph.sanitizeHtml(result, true);
 				
 				return result;
 			}
@@ -5803,7 +5846,7 @@ if (typeof mxVertexHandler != 'undefined')
 			}
 			else
 			{
-				var result = this.graph.sanitizeHtml(this.textarea.innerHTML);
+				var result = this.graph.sanitizeHtml(this.textarea.innerHTML, true);
 	
 				if (mxUtils.getValue(state.style, 'nl2Br', '1') == '1')
 				{
@@ -5895,6 +5938,19 @@ if (typeof mxVertexHandler != 'undefined')
 			return new mxRectangle(0, 0, (state.text == null) ? 30 :  state.text.size * scale + 20, 30);
 		};
 		
+		// Hold alt to ignore drop target
+		var mxGraphHandlerMoveCells = mxGraphHandler.prototype.moveCells;
+		
+		mxGraphHandler.prototype.moveCells = function(cells, dx, dy, clone, target, evt)
+		{
+			if (mxEvent.isAltDown(evt))
+			{
+				target = null;
+			}
+			
+			mxGraphHandlerMoveCells.apply(this, arguments);
+		};
+		
 		/**
 		 * Hints on handlers
 		 */

+ 5 - 3
war/js/mxgraph/Sidebar.js

@@ -1008,8 +1008,8 @@ Sidebar.prototype.addMiscPalette = function(expand)
 	 	this.createEdgeTemplateEntry('edgeStyle=isometricEdgeStyle;endArrow=none;html=1;elbow=vertical;', 50, 100, '', 'Isometric Edge 2'),
 	 	this.createVertexTemplateEntry('line;strokeWidth=2;html=1;', 160, 10, '', 'Horizontal Line'),
 	 	this.createVertexTemplateEntry('line;strokeWidth=2;direction=south;html=1;', 10, 160, '', 'Vertical Line'),
-	 	this.createVertexTemplateEntry('line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;', 160, 10, '', 'Horizontal Backbone', false, null, 'network'),
-	 	this.createVertexTemplateEntry('line;strokeWidth=4;direction=south;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;', 10, 160, '', 'Vertical Backbone', false, null, 'network'),
+	 	this.createVertexTemplateEntry('line;strokeWidth=4;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;', 160, 10, '', 'Horizontal Backbone', false, null, 'backbone bus network'),
+	 	this.createVertexTemplateEntry('line;strokeWidth=4;direction=south;html=1;perimeter=backbonePerimeter;points=[];outlineConnect=0;', 10, 160, '', 'Vertical Backbone', false, null, 'backbone bus network'),
 	 	this.createVertexTemplateEntry('shape=curlyBracket;whiteSpace=wrap;html=1;rounded=1;', 20, 120, '', 'Curly Bracket'),
 	 	this.createVertexTemplateEntry('shape=image;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;imageAspect=1;aspect=fixed;image=' + this.gearImage, 52, 61, '', 'Image (Fixed Aspect)', false, null, 'fixed image icon symbol'),
 	 	this.createVertexTemplateEntry('shape=image;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;imageAspect=0;image=' + this.gearImage, 50, 60, '', 'Image (Variable Aspect)', false, null, 'strechted image icon symbol'),
@@ -1970,7 +1970,9 @@ Sidebar.prototype.createDropHandler = function(cells, allowSplit, allowCellsInse
 			{
 				graph.stopEditing();
 				
-				var validDropTarget = (target != null) ? graph.isValidDropTarget(target, cells, evt) : false;
+				// Holding alt while mouse is released ignores drop target
+				var validDropTarget = (target != null && !mxEvent.isAltDown(evt)) ?
+					graph.isValidDropTarget(target, cells, evt) : false;
 				var select = null;
 
 				if (target != null && !validDropTarget)

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 304 - 303
war/js/reader.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 629 - 625
war/js/viewer.min.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 1 - 1
war/shortcuts.svg