瀏覽代碼

6.6.5 release

Gaudenz Alder 8 年之前
父節點
當前提交
bb683dcd96

+ 5 - 0
ChangeLog

@@ -1,3 +1,8 @@
+25-MAY-2017: 6.6.5
+
+- Adds print option in lightbox
+- Moves insert to arrange menu
+
 24-MAY-2017: 6.6.4
 
 - Fixes possible data loss for back button

+ 1 - 1
VERSION

@@ -1 +1 @@
-6.6.4
+6.6.5

+ 18 - 1
etc/build/build.xml

@@ -50,7 +50,7 @@
 		<copy file="${war.dir}/styles/default.xml" tofile="${basedir}/.tmp1.xml" overwrite="true"/>
 		<replaceregexp file="${basedir}/.tmp1.xml" match="${line.separator}" flags="g" replace=""/>
 		<replaceregexp file="${basedir}/.tmp1.xml" match="\t" flags="g" replace=""/>
-		<replaceregexp file="${basedir}/.tmp1.xml" match="'" replace="\\\\'" byline="true"/>
+		<replaceregexp file="${basedir}/.tmp1.xml" match="'" flags="g" replace="\\\\'" byline="true"/>
 		
 		<delete file="${basedir}/Graph-Stylesheet.js"/>
 		<echo file="${basedir}/Graph-Stylesheet.js">Graph.prototype.defaultThemes[Graph.prototype.defaultThemeName] = mxUtils.parseXml('</echo>
@@ -61,6 +61,20 @@
     	</concat>
 		<echo file="${basedir}/Graph-Stylesheet.js" append="true">').documentElement;</echo>
 
+		<delete file="${basedir}/.tmp2.js"/>
+		<copy file="${war.dir}/resources/dia.txt" tofile="${basedir}/.tmp2.xml" overwrite="true"/>
+		<replaceregexp file="${basedir}/.tmp2.xml" match="${line.separator}" flags="g" replace="\\\\n"/>
+		<replaceregexp file="${basedir}/.tmp2.xml" match="'" flags="g" replace="\\\\'" byline="true"/>
+		
+		<delete file="${basedir}/Graph-Resources.js"/>
+		<echo file="${basedir}/Graph-Resources.js">mxResources.parse('</echo>
+		<concat destfile="${basedir}/Graph-Resources.js" fixlastline="no" append="true">
+			<filelist dir="${basedir}">
+				<file name=".tmp2.xml" />
+			</filelist>
+    	</concat>
+		<echo file="${basedir}/Graph-Resources.js" append="true">');</echo>
+		
 		<jscomp compilationLevel="simple" forceRecompile="true" debug="false" output="${basedir}/grapheditor.min.js">
 			<sources dir="${grapheditor.dir}">
 				<file name="Editor.js" />
@@ -162,6 +176,7 @@
 			</sources>
 					
 			<sources dir="${basedir}">
+				<file name="Graph-Resources.js" />
 				<file name="Graph-Stylesheet.js" />
 			</sources>
 
@@ -171,6 +186,7 @@
 		</jscomp>
 		
 		<delete file="${basedir}/.tmp1.xml"/>
+		<delete file="${basedir}/.tmp2.xml"/>
 
 		<echo file="${basedir}/.tmp1.js">
 			(function()
@@ -346,6 +362,7 @@
 		<replace file="${war.dir}/js/app.min.js" token="@DRAWIO-VERSION@" value="${version}"/>
 
 		<delete file="${basedir}/Graph-Stylesheet.js"/>
+		<delete file="${basedir}/Graph-Resources.js"/>
 		<delete file="${basedir}/grapheditor.min.js"/>
 		<delete file="${basedir}/sidebar.min.js"/>
 	</target>

+ 0 - 2
etc/electron/ElectronApp.js

@@ -95,8 +95,6 @@ FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
 		
 		this.put('extras', new Menu(mxUtils.bind(this, function(menu, parent)
 		{
-			this.addSubmenu('insert', menu, parent);
-			menu.addSeparator(parent);
 			this.addMenuItems(menu, ['copyConnect', 'collapseExpand', '-', 'mathematicalTypesetting', 'autosave', '-',
 			                         'createShape', 'editDiagram', '-', 'tags', '-', 'online'], parent);
 		})));

+ 1 - 1
war/cache.manifest

@@ -1,7 +1,7 @@
 CACHE MANIFEST
 
 # THIS FILE WAS GENERATED. DO NOT MODIFY!
-# 05/24/2017 04:23 PM
+# 05/26/2017 12:24 PM
 
 app.html
 index.html?offline=1

文件差異過大導致無法顯示
+ 597 - 597
war/js/app.min.js


文件差異過大導致無法顯示
+ 448 - 392
war/js/atlas-viewer.min.js


文件差異過大導致無法顯示
+ 606 - 606
war/js/atlas.min.js


+ 0 - 552
war/js/diagramly/Dialogs.js

@@ -3674,558 +3674,6 @@ var ImageDialog = function(editorUi, title, initialValue, fn, ignoreExisting, co
 	this.container = div;
 };
 
-/**
- * Constructs a new print dialog.
- */
-PrintDialog.prototype.create = function(editorUi, titleText)
-{
-	var graph = editorUi.editor.graph;
-	var div = document.createElement('div');
-	
-	var title = document.createElement('h3');
-	title.style.width = '100%';
-	title.style.textAlign = 'center';
-	title.style.marginTop = '0px';
-	mxUtils.write(title, titleText || mxResources.get('print'));
-	div.appendChild(title);
-	
-	var pageCount = 1;
-	var currentPage = 1;
-
-	// Pages
-	var pagesSection = document.createElement('div');
-	pagesSection.style.cssText = 'border-bottom:1px solid lightGray;padding-bottom:12px;margin-bottom:12px;';
-	
-	var allPagesRadio = document.createElement('input');
-	allPagesRadio.style.cssText = 'margin-right:8px;margin-bottom:8px;';
-	allPagesRadio.setAttribute('value', 'all');
-	allPagesRadio.setAttribute('type', 'radio');
-	allPagesRadio.setAttribute('name', 'pages-printdialog');
-	
-	pagesSection.appendChild(allPagesRadio);
-
-	var span = document.createElement('span');
-	mxUtils.write(span, mxResources.get('printAllPages'));
-	pagesSection.appendChild(span);
-
-	mxUtils.br(pagesSection);
-
-	// Pages ... to ...
-	var pagesRadio = allPagesRadio.cloneNode(true);
-	allPagesRadio.setAttribute('checked', 'checked');
-	pagesRadio.setAttribute('value', 'range');
-	pagesSection.appendChild(pagesRadio);
-	
-	var span = document.createElement('span');
-	mxUtils.write(span, mxResources.get('pages') + ':');
-	pagesSection.appendChild(span);
-	
-	var pagesFromInput = document.createElement('input');
-	pagesFromInput.style.cssText = 'margin:0 8px 0 8px;'
-	pagesFromInput.setAttribute('value', '1');
-	pagesFromInput.setAttribute('type', 'number');
-	pagesFromInput.setAttribute('min', '1');
-	pagesFromInput.style.width = '50px';
-	pagesSection.appendChild(pagesFromInput);
-	
-	var span = document.createElement('span');
-	mxUtils.write(span, mxResources.get('to'));
-	pagesSection.appendChild(span);
-	
-	var pagesToInput = pagesFromInput.cloneNode(true);
-	pagesSection.appendChild(pagesToInput);
-
-	mxEvent.addListener(pagesFromInput, 'focus', function()
-	{
-		pagesRadio.checked = true;
-	});
-	
-	mxEvent.addListener(pagesToInput, 'focus', function()
-	{
-		pagesRadio.checked = true;
-	});
-	
-	function validatePageRange()
-	{
-		pagesToInput.value = Math.max(1, Math.min(pageCount, Math.max(parseInt(pagesToInput.value), parseInt(pagesFromInput.value))));
-		pagesFromInput.value = Math.max(1, Math.min(pageCount, Math.min(parseInt(pagesToInput.value), parseInt(pagesFromInput.value))));
-	};
-	
-	mxEvent.addListener(pagesFromInput, 'change', validatePageRange);
-	mxEvent.addListener(pagesToInput, 'change', validatePageRange);
-	
-	if (editorUi.pages != null)
-	{
-		pageCount = editorUi.pages.length;
-
-		if (editorUi.currentPage != null)
-		{
-			for (var i = 0; i < editorUi.pages.length; i++)
-			{
-				if (editorUi.currentPage == editorUi.pages[i])
-				{
-					currentPage = i + 1;
-					pagesFromInput.value = currentPage;
-					pagesToInput.value = currentPage;
-					break;
-				}
-			}
-		}
-	}
-	
-	pagesFromInput.setAttribute('max', pageCount);
-	pagesToInput.setAttribute('max', pageCount);		
-	
-	if (pageCount > 1)
-	{
-		div.appendChild(pagesSection);
-	}
-	
-	// Adjust to ...
-	var adjustSection = document.createElement('div');
-	adjustSection.style.marginBottom = '10px';
-	
-	var adjustRadio = document.createElement('input');
-	adjustRadio.style.marginRight = '8px';
-	
-	adjustRadio.setAttribute('value', 'adjust');
-	adjustRadio.setAttribute('type', 'radio');
-	adjustRadio.setAttribute('name', 'printZoom');
-	adjustSection.appendChild(adjustRadio);
-
-	var span = document.createElement('span');
-	mxUtils.write(span, mxResources.get('adjustTo'));
-	adjustSection.appendChild(span);
-	
-	var zoomInput = document.createElement('input');
-	zoomInput.style.cssText = 'margin:0 8px 0 8px;';
-	zoomInput.setAttribute('value', '100 %');
-	zoomInput.style.width = '50px';
-	adjustSection.appendChild(zoomInput);
-	
-	mxEvent.addListener(zoomInput, 'focus', function()
-	{
-		adjustRadio.checked = true;
-	});
-	
-	div.appendChild(adjustSection);
-
-	// Fit to ...
-	var fitSection = pagesSection.cloneNode(false);
-
-	var fitRadio = adjustRadio.cloneNode(true);
-	fitRadio.setAttribute('value', 'fit');
-	adjustRadio.setAttribute('checked', 'checked');
-	
-	var spanFitRadio = document.createElement('div');
-	spanFitRadio.style.cssText = 'display:inline-block;height:100%;vertical-align:top;padding-top:2px;';
-	spanFitRadio.appendChild(fitRadio);
-	fitSection.appendChild(spanFitRadio);
-	
-	var table = document.createElement('table');
-	table.style.display = 'inline-block';
-	var tbody = document.createElement('tbody');
-	
-	var row1 = document.createElement('tr');
-	var row2 = row1.cloneNode(true);
-	
-	var td1 = document.createElement('td');
-	var td2 = td1.cloneNode(true);
-	var td3 = td1.cloneNode(true);
-	
-	var td4 = td1.cloneNode(true);
-	var td5 = td1.cloneNode(true);
-	var td6 = td1.cloneNode(true);
-	
-	td1.style.textAlign = 'right';
-	td4.style.textAlign = 'right';
-
-	mxUtils.write(td1, mxResources.get('fitTo'));
-	
-	var sheetsAcrossInput = document.createElement('input');
-	sheetsAcrossInput.style.cssText = 'margin:0 8px 0 8px;';
-	sheetsAcrossInput.setAttribute('value', '1');
-	sheetsAcrossInput.setAttribute('min', '1');
-	sheetsAcrossInput.setAttribute('type', 'number');
-	sheetsAcrossInput.style.width = '40px';
-	td2.appendChild(sheetsAcrossInput);
-	
-	var span = document.createElement('span');
-	mxUtils.write(span, mxResources.get('fitToSheetsAcross'));
-	td3.appendChild(span);
-
-	mxUtils.write(td4, mxResources.get('fitToBy'));
-	
-	var sheetsDownInput = sheetsAcrossInput.cloneNode(true);
-	td5.appendChild(sheetsDownInput);
-	
-	mxEvent.addListener(sheetsAcrossInput, 'focus', function()
-	{
-		fitRadio.checked = true;
-	});
-
-	mxEvent.addListener(sheetsDownInput, 'focus', function()
-	{
-		fitRadio.checked = true;
-	});
-
-	var span = document.createElement('span');
-	mxUtils.write(span, mxResources.get('fitToSheetsDown'));
-	td6.appendChild(span);
-	
-	row1.appendChild(td1);
-	row1.appendChild(td2);
-	row1.appendChild(td3);
-	
-	row2.appendChild(td4);
-	row2.appendChild(td5);
-	row2.appendChild(td6);
-	
-	tbody.appendChild(row1);
-	tbody.appendChild(row2);
-	table.appendChild(tbody);
-	fitSection.appendChild(table);
-	
-	div.appendChild(fitSection);
-	
-	// Page scale ...
-	var pageScaleSection = document.createElement('div');
-
-	var span = document.createElement('div');
-	span.style.fontWeight = 'bold';
-	span.style.marginBottom = '12px';
-	mxUtils.write(span, mxResources.get('paperSize'));
-	pageScaleSection.appendChild(span);
-	
-	var span = document.createElement('div');
-	span.style.marginBottom = '12px';
-
-	var accessor = PageSetupDialog.addPageFormatPanel(span, 'printdialog',
-		editorUi.editor.graph.pageFormat || mxConstants.PAGE_FORMAT_A4_PORTRAIT);
-	pageScaleSection.appendChild(span);
-	
-	var span = document.createElement('span');
-	mxUtils.write(span, mxResources.get('pageScale'));
-	pageScaleSection.appendChild(span);
-	
-	var pageScaleInput = document.createElement('input');
-	pageScaleInput.style.cssText = 'margin:0 8px 0 8px;';
-	pageScaleInput.setAttribute('value', '100 %');
-	pageScaleInput.style.width = '60px';
-	pageScaleSection.appendChild(pageScaleInput);
-	
-	div.appendChild(pageScaleSection);
-	
-	// Buttons
-	var buttons = document.createElement('div');
-	buttons.style.cssText = 'text-align:right;margin:62px 0 0 0;';
-	
-	// Overall scale for print-out to account for print borders in dialogs etc
-	function preview(print)
-	{
-		var printScale = parseInt(pageScaleInput.value) / 100;
-		
-		if (isNaN(printScale))
-		{
-			printScale = 1;
-			pageScaleInput.value = '100 %';
-		}
-		
-		// Workaround to match available paper size in actual print output
-		printScale *= 0.75;
-		
-		function printGraph(thisGraph, pv, forcePageBreaks)
-		{
-			// Negative coordinates are cropped or shifted if page visible
-			var gb = thisGraph.getGraphBounds();
-			var border = 0;
-			var x0 = 0;
-			var y0 = 0;
-	
-			var pf = accessor.get();
-			var scale = 1 / thisGraph.pageScale;
-			var autoOrigin = fitRadio.checked;
-	
-			if (autoOrigin)
-			{
-				var h = parseInt(sheetsAcrossInput.value);
-				var v = parseInt(sheetsDownInput.value);
-				
-				scale = Math.min((pf.height * v) / (gb.height / thisGraph.view.scale),
-					(pf.width * h) / (gb.width / thisGraph.view.scale));
-			}
-			else
-			{
-				scale = parseInt(zoomInput.value) / (100 * thisGraph.pageScale);
-				
-				if (isNaN(scale))
-				{
-					printScale = 1 / thisGraph.pageScale;
-					zoomInput.value = '100 %';
-				}
-			}
-	
-			// Applies print scale
-			pf = mxRectangle.fromRectangle(pf);
-			pf.width = Math.ceil(pf.width * printScale);
-			pf.height = Math.ceil(pf.height * printScale);
-			scale *= printScale;
-			
-			// Starts at first visible page
-			if (!autoOrigin && thisGraph.pageVisible)
-			{
-				var layout = thisGraph.getPageLayout();
-				x0 -= layout.x * pf.width;
-				y0 -= layout.y * pf.height;
-			}
-			else
-			{
-				autoOrigin = true;
-			}
-
-			if (pv == null)
-			{
-				pv = PrintDialog.createPrintPreview(thisGraph, scale, pf, border, x0, y0, autoOrigin);
-				pv.pageSelector = false;
-				pv.mathEnabled = false;
-				
-				if (typeof(MathJax) !== 'undefined')
-				{
-					// Adds class to ignore if math is disabled
-					var printPreviewRenderPage = pv.renderPage;
-					
-					pv.renderPage = function(w, h, dx, dy, content, pageNumber)
-					{
-						var result = printPreviewRenderPage.apply(this, arguments);
-						
-						if (this.graph.mathEnabled)
-						{
-							this.mathEnabled = true;
-						}
-						else
-						{
-							result.className = 'geDisableMathJax';
-						}
-						
-						return result;
-					};
-				}
-				
-				pv.open(null, null, forcePageBreaks, true);
-			}
-			else
-			{				
-				var bg = thisGraph.background;
-				
-				if (bg == null || bg == '' || bg == mxConstants.NONE)
-				{
-					bg = '#ffffff';
-				}
-				
-				pv.backgroundColor = bg;
-				pv.autoOrigin = autoOrigin;
-				pv.appendGraph(thisGraph, scale, x0, y0, forcePageBreaks, true);
-			}
-			
-			return pv;
-		};
-		
-		var pagesFrom = pagesFromInput.value;
-		var pagesTo = pagesToInput.value;
-		var ignorePages = !allPagesRadio.checked;
-		var pv = null;
-					
-		if (ignorePages)
-		{
-			ignorePages = pagesFrom == currentPage && pagesTo == currentPage;
-		}
-		
-		if (!ignorePages && editorUi.pages != null && editorUi.pages.length)
-		{
-			var i0 = 0;
-			var imax = editorUi.pages.length - 1;
-			
-			if (!allPagesRadio.checked)
-			{
-				i0 = parseInt(pagesFrom) - 1;
-				imax = parseInt(pagesTo) - 1;
-			}
-			
-			for (var i = i0; i <= imax; i++)
-			{
-				var page = editorUi.pages[i];
-				var tempGraph = (page == editorUi.currentPage) ? graph : null;
-				
-				if (tempGraph == null)
-				{
-					tempGraph = editorUi.createTemporaryGraph(graph.getStylesheet());
-
-					// Restores graph settings that are relevant for printing
-					var pageVisible = true;
-					var mathEnabled = false;
-					var bg = null;
-					var bgImage = null;
-					
-					if (page.viewState == null && page.mapping == null)
-					{
-						// Workaround to extract view state from XML node
-						// This changes the state of the page and parses
-						// the XML for the graph model even if not needed.
-						if (page.root == null)
-						{
-							editorUi.updatePageRoot(page);
-						}
-					}
-					
-					if (page.viewState != null)
-					{
-						pageVisible = page.viewState.pageVisible;
-						mathEnabled = page.viewState.mathEnabled;
-						bg = page.viewState.background;
-						bgImage = page.viewState.backgroundImage;
-					}
-					else if (page.mapping != null && page.mapping.diagramMap != null)
-					{
-						// Default pageVisible in realtime is true
-						mathEnabled = page.mapping.diagramMap.get('mathEnabled') != '0';
-						bg = page.mapping.diagramMap.get('background');
-						
-						var temp = page.mapping.diagramMap.get('backgroundImage');
-						bgImage = (temp != null && temp.length > 0) ? JSON.parse(temp) : null;
-					}
-				
-					tempGraph.background = bg;
-					tempGraph.backgroundImage = (bgImage != null) ? new mxImage(bgImage.src, bgImage.width, bgImage.height) : null;
-					tempGraph.pageVisible = pageVisible;
-					tempGraph.mathEnabled = mathEnabled;
-					
-					// Redirects placeholders to current page
-					var graphGetGlobalVariable = tempGraph.getGlobalVariable;
-	
-					tempGraph.getGlobalVariable = function(name)
-					{
-						if (name == 'page')
-						{
-							return page.getName();
-						}
-						else if (name == 'pagenumber')
-						{
-							return i + 1;
-						}
-						
-						return graphGetGlobalVariable.apply(this, arguments);
-					};
-					
-					document.body.appendChild(tempGraph.container);
-					editorUi.updatePageRoot(page);
-					tempGraph.model.setRoot(page.root);
-				}
-
-				pv = printGraph(tempGraph, pv, i != imax);
-
-				if (tempGraph != graph)
-				{
-					tempGraph.container.parentNode.removeChild(tempGraph.container);
-				}
-			}
-		}
-		else
-		{
-			pv = printGraph(graph);
-		}
-		
-		if (pv.mathEnabled)
-		{
-			var doc = pv.wnd.document;
-	
-			doc.writeln('<script type="text/x-mathjax-config">');
-			doc.writeln('MathJax.Hub.Config({');
-			doc.writeln('messageStyle: "none",');
-			doc.writeln('jax: ["input/TeX", "input/MathML", "input/AsciiMath", "output/HTML-CSS"],');
-			doc.writeln('extensions: ["tex2jax.js", "mml2jax.js", "asciimath2jax.js"],');
-			doc.writeln('TeX: {');
-			doc.writeln('extensions: ["AMSmath.js", "AMSsymbols.js", "noErrors.js", "noUndefined.js"]');
-			doc.writeln('},');
-						// Ignores math in in-place editor
-			doc.writeln('tex2jax: {');
-			doc.writeln('	ignoreClass: "geDisableMathJax"');
-		  	doc.writeln('},');
-		  	doc.writeln('asciimath2jax: {');
-			doc.writeln('	ignoreClass: "geDisableMathJax"');
-		  	doc.writeln('}');
-			doc.writeln('});');
-			
-			// Adds asynchronous printing when MathJax finished rendering
-			if (print)
-			{
-				doc.writeln('MathJax.Hub.Queue(function () {');
-				doc.writeln('window.print();');
-				doc.writeln('});');
-			}
-			
-			doc.writeln('</script>');
-			doc.writeln('<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>');
-		}
-		
-		pv.closeDocument();
-		
-		if (!pv.mathEnabled && print)
-		{
-			PrintDialog.printPreview(pv);
-		}
-	};
-	
-	var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
-	{
-		editorUi.hideDialog();
-	});
-	cancelBtn.className = 'geBtn';
-	
-	if (editorUi.editor.cancelFirst)
-	{
-		buttons.appendChild(cancelBtn);
-	}
-	
-	if (!editorUi.isOffline())
-	{
-		var helpBtn = mxUtils.button(mxResources.get('help'), function()
-		{
-			window.open('https://desk.draw.io/support/solutions/articles/16000048947');
-		});
-		
-		helpBtn.className = 'geBtn';
-		buttons.appendChild(helpBtn);
-	}
-	
-	if (PrintDialog.previewEnabled)
-	{
-		var previewBtn = mxUtils.button(mxResources.get('preview'), function()
-		{
-			editorUi.hideDialog();
-			preview(false);
-		});
-		previewBtn.className = 'geBtn';
-		buttons.appendChild(previewBtn);
-	}
-	
-	var printBtn = mxUtils.button(mxResources.get((!PrintDialog.previewEnabled) ? 'ok' : 'print'), function()
-	{
-		editorUi.hideDialog();
-		preview(true);
-	});
-	printBtn.className = 'geBtn gePrimaryBtn';
-	buttons.appendChild(printBtn);
-	
-	if (!editorUi.editor.cancelFirst)
-	{
-		buttons.appendChild(cancelBtn);
-	}
-
-	div.appendChild(buttons);
-
-	this.container = div;
-};
-
 /**
  * Overrides link dialog to add Google Picker.
  */

+ 552 - 0
war/js/diagramly/Editor.js

@@ -1322,4 +1322,556 @@
 		
 		return mxMarkerCreateMarker.apply(this, arguments);
 	};
+
+	/**
+	 * Constructs a new print dialog.
+	 */
+	PrintDialog.prototype.create = function(editorUi, titleText)
+	{
+		var graph = editorUi.editor.graph;
+		var div = document.createElement('div');
+		
+		var title = document.createElement('h3');
+		title.style.width = '100%';
+		title.style.textAlign = 'center';
+		title.style.marginTop = '0px';
+		mxUtils.write(title, titleText || mxResources.get('print'));
+		div.appendChild(title);
+		
+		var pageCount = 1;
+		var currentPage = 1;
+
+		// Pages
+		var pagesSection = document.createElement('div');
+		pagesSection.style.cssText = 'border-bottom:1px solid lightGray;padding-bottom:12px;margin-bottom:12px;';
+		
+		var allPagesRadio = document.createElement('input');
+		allPagesRadio.style.cssText = 'margin-right:8px;margin-bottom:8px;';
+		allPagesRadio.setAttribute('value', 'all');
+		allPagesRadio.setAttribute('type', 'radio');
+		allPagesRadio.setAttribute('name', 'pages-printdialog');
+		
+		pagesSection.appendChild(allPagesRadio);
+
+		var span = document.createElement('span');
+		mxUtils.write(span, mxResources.get('printAllPages'));
+		pagesSection.appendChild(span);
+
+		mxUtils.br(pagesSection);
+
+		// Pages ... to ...
+		var pagesRadio = allPagesRadio.cloneNode(true);
+		allPagesRadio.setAttribute('checked', 'checked');
+		pagesRadio.setAttribute('value', 'range');
+		pagesSection.appendChild(pagesRadio);
+		
+		var span = document.createElement('span');
+		mxUtils.write(span, mxResources.get('pages') + ':');
+		pagesSection.appendChild(span);
+		
+		var pagesFromInput = document.createElement('input');
+		pagesFromInput.style.cssText = 'margin:0 8px 0 8px;'
+		pagesFromInput.setAttribute('value', '1');
+		pagesFromInput.setAttribute('type', 'number');
+		pagesFromInput.setAttribute('min', '1');
+		pagesFromInput.style.width = '50px';
+		pagesSection.appendChild(pagesFromInput);
+		
+		var span = document.createElement('span');
+		mxUtils.write(span, mxResources.get('to'));
+		pagesSection.appendChild(span);
+		
+		var pagesToInput = pagesFromInput.cloneNode(true);
+		pagesSection.appendChild(pagesToInput);
+
+		mxEvent.addListener(pagesFromInput, 'focus', function()
+		{
+			pagesRadio.checked = true;
+		});
+		
+		mxEvent.addListener(pagesToInput, 'focus', function()
+		{
+			pagesRadio.checked = true;
+		});
+		
+		function validatePageRange()
+		{
+			pagesToInput.value = Math.max(1, Math.min(pageCount, Math.max(parseInt(pagesToInput.value), parseInt(pagesFromInput.value))));
+			pagesFromInput.value = Math.max(1, Math.min(pageCount, Math.min(parseInt(pagesToInput.value), parseInt(pagesFromInput.value))));
+		};
+		
+		mxEvent.addListener(pagesFromInput, 'change', validatePageRange);
+		mxEvent.addListener(pagesToInput, 'change', validatePageRange);
+		
+		if (editorUi.pages != null)
+		{
+			pageCount = editorUi.pages.length;
+
+			if (editorUi.currentPage != null)
+			{
+				for (var i = 0; i < editorUi.pages.length; i++)
+				{
+					if (editorUi.currentPage == editorUi.pages[i])
+					{
+						currentPage = i + 1;
+						pagesFromInput.value = currentPage;
+						pagesToInput.value = currentPage;
+						break;
+					}
+				}
+			}
+		}
+		
+		pagesFromInput.setAttribute('max', pageCount);
+		pagesToInput.setAttribute('max', pageCount);		
+		
+		if (pageCount > 1)
+		{
+			div.appendChild(pagesSection);
+		}
+		
+		// Adjust to ...
+		var adjustSection = document.createElement('div');
+		adjustSection.style.marginBottom = '10px';
+		
+		var adjustRadio = document.createElement('input');
+		adjustRadio.style.marginRight = '8px';
+		
+		adjustRadio.setAttribute('value', 'adjust');
+		adjustRadio.setAttribute('type', 'radio');
+		adjustRadio.setAttribute('name', 'printZoom');
+		adjustSection.appendChild(adjustRadio);
+
+		var span = document.createElement('span');
+		mxUtils.write(span, mxResources.get('adjustTo'));
+		adjustSection.appendChild(span);
+		
+		var zoomInput = document.createElement('input');
+		zoomInput.style.cssText = 'margin:0 8px 0 8px;';
+		zoomInput.setAttribute('value', '100 %');
+		zoomInput.style.width = '50px';
+		adjustSection.appendChild(zoomInput);
+		
+		mxEvent.addListener(zoomInput, 'focus', function()
+		{
+			adjustRadio.checked = true;
+		});
+		
+		div.appendChild(adjustSection);
+
+		// Fit to ...
+		var fitSection = pagesSection.cloneNode(false);
+
+		var fitRadio = adjustRadio.cloneNode(true);
+		fitRadio.setAttribute('value', 'fit');
+		adjustRadio.setAttribute('checked', 'checked');
+		
+		var spanFitRadio = document.createElement('div');
+		spanFitRadio.style.cssText = 'display:inline-block;height:100%;vertical-align:top;padding-top:2px;';
+		spanFitRadio.appendChild(fitRadio);
+		fitSection.appendChild(spanFitRadio);
+		
+		var table = document.createElement('table');
+		table.style.display = 'inline-block';
+		var tbody = document.createElement('tbody');
+		
+		var row1 = document.createElement('tr');
+		var row2 = row1.cloneNode(true);
+		
+		var td1 = document.createElement('td');
+		var td2 = td1.cloneNode(true);
+		var td3 = td1.cloneNode(true);
+		
+		var td4 = td1.cloneNode(true);
+		var td5 = td1.cloneNode(true);
+		var td6 = td1.cloneNode(true);
+		
+		td1.style.textAlign = 'right';
+		td4.style.textAlign = 'right';
+
+		mxUtils.write(td1, mxResources.get('fitTo'));
+		
+		var sheetsAcrossInput = document.createElement('input');
+		sheetsAcrossInput.style.cssText = 'margin:0 8px 0 8px;';
+		sheetsAcrossInput.setAttribute('value', '1');
+		sheetsAcrossInput.setAttribute('min', '1');
+		sheetsAcrossInput.setAttribute('type', 'number');
+		sheetsAcrossInput.style.width = '40px';
+		td2.appendChild(sheetsAcrossInput);
+		
+		var span = document.createElement('span');
+		mxUtils.write(span, mxResources.get('fitToSheetsAcross'));
+		td3.appendChild(span);
+
+		mxUtils.write(td4, mxResources.get('fitToBy'));
+		
+		var sheetsDownInput = sheetsAcrossInput.cloneNode(true);
+		td5.appendChild(sheetsDownInput);
+		
+		mxEvent.addListener(sheetsAcrossInput, 'focus', function()
+		{
+			fitRadio.checked = true;
+		});
+
+		mxEvent.addListener(sheetsDownInput, 'focus', function()
+		{
+			fitRadio.checked = true;
+		});
+
+		var span = document.createElement('span');
+		mxUtils.write(span, mxResources.get('fitToSheetsDown'));
+		td6.appendChild(span);
+		
+		row1.appendChild(td1);
+		row1.appendChild(td2);
+		row1.appendChild(td3);
+		
+		row2.appendChild(td4);
+		row2.appendChild(td5);
+		row2.appendChild(td6);
+		
+		tbody.appendChild(row1);
+		tbody.appendChild(row2);
+		table.appendChild(tbody);
+		fitSection.appendChild(table);
+		
+		div.appendChild(fitSection);
+		
+		// Page scale ...
+		var pageScaleSection = document.createElement('div');
+
+		var span = document.createElement('div');
+		span.style.fontWeight = 'bold';
+		span.style.marginBottom = '12px';
+		mxUtils.write(span, mxResources.get('paperSize'));
+		pageScaleSection.appendChild(span);
+		
+		var span = document.createElement('div');
+		span.style.marginBottom = '12px';
+
+		var accessor = PageSetupDialog.addPageFormatPanel(span, 'printdialog',
+			editorUi.editor.graph.pageFormat || mxConstants.PAGE_FORMAT_A4_PORTRAIT);
+		pageScaleSection.appendChild(span);
+		
+		var span = document.createElement('span');
+		mxUtils.write(span, mxResources.get('pageScale'));
+		pageScaleSection.appendChild(span);
+		
+		var pageScaleInput = document.createElement('input');
+		pageScaleInput.style.cssText = 'margin:0 8px 0 8px;';
+		pageScaleInput.setAttribute('value', '100 %');
+		pageScaleInput.style.width = '60px';
+		pageScaleSection.appendChild(pageScaleInput);
+		
+		div.appendChild(pageScaleSection);
+		
+		// Buttons
+		var buttons = document.createElement('div');
+		buttons.style.cssText = 'text-align:right;margin:62px 0 0 0;';
+		
+		// Overall scale for print-out to account for print borders in dialogs etc
+		function preview(print)
+		{
+			var printScale = parseInt(pageScaleInput.value) / 100;
+			
+			if (isNaN(printScale))
+			{
+				printScale = 1;
+				pageScaleInput.value = '100 %';
+			}
+			
+			// Workaround to match available paper size in actual print output
+			printScale *= 0.75;
+			
+			function printGraph(thisGraph, pv, forcePageBreaks)
+			{
+				// Negative coordinates are cropped or shifted if page visible
+				var gb = thisGraph.getGraphBounds();
+				var border = 0;
+				var x0 = 0;
+				var y0 = 0;
+		
+				var pf = accessor.get();
+				var scale = 1 / thisGraph.pageScale;
+				var autoOrigin = fitRadio.checked;
+		
+				if (autoOrigin)
+				{
+					var h = parseInt(sheetsAcrossInput.value);
+					var v = parseInt(sheetsDownInput.value);
+					
+					scale = Math.min((pf.height * v) / (gb.height / thisGraph.view.scale),
+						(pf.width * h) / (gb.width / thisGraph.view.scale));
+				}
+				else
+				{
+					scale = parseInt(zoomInput.value) / (100 * thisGraph.pageScale);
+					
+					if (isNaN(scale))
+					{
+						printScale = 1 / thisGraph.pageScale;
+						zoomInput.value = '100 %';
+					}
+				}
+		
+				// Applies print scale
+				pf = mxRectangle.fromRectangle(pf);
+				pf.width = Math.ceil(pf.width * printScale);
+				pf.height = Math.ceil(pf.height * printScale);
+				scale *= printScale;
+				
+				// Starts at first visible page
+				if (!autoOrigin && thisGraph.pageVisible)
+				{
+					var layout = thisGraph.getPageLayout();
+					x0 -= layout.x * pf.width;
+					y0 -= layout.y * pf.height;
+				}
+				else
+				{
+					autoOrigin = true;
+				}
+
+				if (pv == null)
+				{
+					pv = PrintDialog.createPrintPreview(thisGraph, scale, pf, border, x0, y0, autoOrigin);
+					pv.pageSelector = false;
+					pv.mathEnabled = false;
+					
+					if (typeof(MathJax) !== 'undefined')
+					{
+						// Adds class to ignore if math is disabled
+						var printPreviewRenderPage = pv.renderPage;
+						
+						pv.renderPage = function(w, h, dx, dy, content, pageNumber)
+						{
+							var result = printPreviewRenderPage.apply(this, arguments);
+							
+							if (this.graph.mathEnabled)
+							{
+								this.mathEnabled = true;
+							}
+							else
+							{
+								result.className = 'geDisableMathJax';
+							}
+							
+							return result;
+						};
+					}
+					
+					pv.open(null, null, forcePageBreaks, true);
+				}
+				else
+				{				
+					var bg = thisGraph.background;
+					
+					if (bg == null || bg == '' || bg == mxConstants.NONE)
+					{
+						bg = '#ffffff';
+					}
+					
+					pv.backgroundColor = bg;
+					pv.autoOrigin = autoOrigin;
+					pv.appendGraph(thisGraph, scale, x0, y0, forcePageBreaks, true);
+				}
+				
+				return pv;
+			};
+			
+			var pagesFrom = pagesFromInput.value;
+			var pagesTo = pagesToInput.value;
+			var ignorePages = !allPagesRadio.checked;
+			var pv = null;
+						
+			if (ignorePages)
+			{
+				ignorePages = pagesFrom == currentPage && pagesTo == currentPage;
+			}
+			
+			if (!ignorePages && editorUi.pages != null && editorUi.pages.length)
+			{
+				var i0 = 0;
+				var imax = editorUi.pages.length - 1;
+				
+				if (!allPagesRadio.checked)
+				{
+					i0 = parseInt(pagesFrom) - 1;
+					imax = parseInt(pagesTo) - 1;
+				}
+				
+				for (var i = i0; i <= imax; i++)
+				{
+					var page = editorUi.pages[i];
+					var tempGraph = (page == editorUi.currentPage) ? graph : null;
+					
+					if (tempGraph == null)
+					{
+						tempGraph = editorUi.createTemporaryGraph(graph.getStylesheet());
+
+						// Restores graph settings that are relevant for printing
+						var pageVisible = true;
+						var mathEnabled = false;
+						var bg = null;
+						var bgImage = null;
+						
+						if (page.viewState == null && page.mapping == null)
+						{
+							// Workaround to extract view state from XML node
+							// This changes the state of the page and parses
+							// the XML for the graph model even if not needed.
+							if (page.root == null)
+							{
+								editorUi.updatePageRoot(page);
+							}
+						}
+						
+						if (page.viewState != null)
+						{
+							pageVisible = page.viewState.pageVisible;
+							mathEnabled = page.viewState.mathEnabled;
+							bg = page.viewState.background;
+							bgImage = page.viewState.backgroundImage;
+						}
+						else if (page.mapping != null && page.mapping.diagramMap != null)
+						{
+							// Default pageVisible in realtime is true
+							mathEnabled = page.mapping.diagramMap.get('mathEnabled') != '0';
+							bg = page.mapping.diagramMap.get('background');
+							
+							var temp = page.mapping.diagramMap.get('backgroundImage');
+							bgImage = (temp != null && temp.length > 0) ? JSON.parse(temp) : null;
+						}
+					
+						tempGraph.background = bg;
+						tempGraph.backgroundImage = (bgImage != null) ? new mxImage(bgImage.src, bgImage.width, bgImage.height) : null;
+						tempGraph.pageVisible = pageVisible;
+						tempGraph.mathEnabled = mathEnabled;
+						
+						// Redirects placeholders to current page
+						var graphGetGlobalVariable = tempGraph.getGlobalVariable;
+		
+						tempGraph.getGlobalVariable = function(name)
+						{
+							if (name == 'page')
+							{
+								return page.getName();
+							}
+							else if (name == 'pagenumber')
+							{
+								return i + 1;
+							}
+							
+							return graphGetGlobalVariable.apply(this, arguments);
+						};
+						
+						document.body.appendChild(tempGraph.container);
+						editorUi.updatePageRoot(page);
+						tempGraph.model.setRoot(page.root);
+					}
+
+					pv = printGraph(tempGraph, pv, i != imax);
+
+					if (tempGraph != graph)
+					{
+						tempGraph.container.parentNode.removeChild(tempGraph.container);
+					}
+				}
+			}
+			else
+			{
+				pv = printGraph(graph);
+			}
+			
+			if (pv.mathEnabled)
+			{
+				var doc = pv.wnd.document;
+		
+				doc.writeln('<script type="text/x-mathjax-config">');
+				doc.writeln('MathJax.Hub.Config({');
+				doc.writeln('messageStyle: "none",');
+				doc.writeln('jax: ["input/TeX", "input/MathML", "input/AsciiMath", "output/HTML-CSS"],');
+				doc.writeln('extensions: ["tex2jax.js", "mml2jax.js", "asciimath2jax.js"],');
+				doc.writeln('TeX: {');
+				doc.writeln('extensions: ["AMSmath.js", "AMSsymbols.js", "noErrors.js", "noUndefined.js"]');
+				doc.writeln('},');
+							// Ignores math in in-place editor
+				doc.writeln('tex2jax: {');
+				doc.writeln('	ignoreClass: "geDisableMathJax"');
+			  	doc.writeln('},');
+			  	doc.writeln('asciimath2jax: {');
+				doc.writeln('	ignoreClass: "geDisableMathJax"');
+			  	doc.writeln('}');
+				doc.writeln('});');
+				
+				// Adds asynchronous printing when MathJax finished rendering
+				if (print)
+				{
+					doc.writeln('MathJax.Hub.Queue(function () {');
+					doc.writeln('window.print();');
+					doc.writeln('});');
+				}
+				
+				doc.writeln('</script>');
+				doc.writeln('<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>');
+			}
+			
+			pv.closeDocument();
+			
+			if (!pv.mathEnabled && print)
+			{
+				PrintDialog.printPreview(pv);
+			}
+		};
+		
+		var cancelBtn = mxUtils.button(mxResources.get('cancel'), function()
+		{
+			editorUi.hideDialog();
+		});
+		cancelBtn.className = 'geBtn';
+		
+		if (editorUi.editor.cancelFirst)
+		{
+			buttons.appendChild(cancelBtn);
+		}
+		
+		if (!editorUi.isOffline())
+		{
+			var helpBtn = mxUtils.button(mxResources.get('help'), function()
+			{
+				window.open('https://desk.draw.io/support/solutions/articles/16000048947');
+			});
+			
+			helpBtn.className = 'geBtn';
+			buttons.appendChild(helpBtn);
+		}
+		
+		if (PrintDialog.previewEnabled)
+		{
+			var previewBtn = mxUtils.button(mxResources.get('preview'), function()
+			{
+				editorUi.hideDialog();
+				preview(false);
+			});
+			previewBtn.className = 'geBtn';
+			buttons.appendChild(previewBtn);
+		}
+		
+		var printBtn = mxUtils.button(mxResources.get((!PrintDialog.previewEnabled) ? 'ok' : 'print'), function()
+		{
+			editorUi.hideDialog();
+			preview(true);
+		});
+		printBtn.className = 'geBtn gePrimaryBtn';
+		buttons.appendChild(printBtn);
+		
+		if (!editorUi.editor.cancelFirst)
+		{
+			buttons.appendChild(cancelBtn);
+		}
+
+		div.appendChild(buttons);
+
+		this.container = div;
+	};
 })();

+ 29 - 12
war/js/diagramly/EditorUi.js

@@ -5689,14 +5689,18 @@
 			this.editor.graph.addSvgShadow(graph.view.canvas.ownerSVGElement, null, true);
 		}
 
-		/**
-		 * Specifies the default filename.
-		 */
+		// Overrides print dialog size
+		ui.actions.get('print').funct = function()
+		{
+			ui.showDialog(new PrintDialog(ui).container, 360,
+				(ui.pages != null && ui.pages.length > 1) ?
+				420 : 360, true, true);
+		};
+
+		// Specifies the default filename
 		this.defaultFilename = mxResources.get('untitledDiagram');
 		
-		/**
-		 * Adds placeholder for %page% and %pagenumber%
-		 */
+		// Adds placeholder for %page% and %pagenumber%
 		var graphGetGlobalVariable = graph.getGlobalVariable;
 		
 		graph.getGlobalVariable = function(name)
@@ -5720,9 +5724,7 @@
 			return graphGetGlobalVariable.apply(this, arguments);
 		};
 
-		/**
-		 * Overrides editor filename.
-		 */
+		// Overrides editor filename
 		this.editor.getOrCreateFilename = function()
 		{
 			var filename = ui.defaultFilename;
@@ -8383,6 +8385,16 @@
 				
 				this.menubarContainer.appendChild(this.offlineStatus);
 				
+				mxEvent.addListener(this.offlineStatus, 'click', mxUtils.bind(this, function()
+				{
+					var img = this.offlineStatus.getElementsByTagName('img');
+					
+					if (img != null && img.length > 0)
+					{
+						this.alert(img[0].getAttribute('title'));
+					}
+				}));
+				
 				var appCache = window.applicationCache;
 
 				function getImageTagForStatus(status)
@@ -8396,10 +8408,10 @@
 					    return '<img title="Cached" border="0" src="' + IMAGE_PATH + '/checkmark.gif"/>';
 					    break;
 					  case appCache.CHECKING: // CHECKING == 2
-					    return '<img title="Checking..." border="0" src="' + IMAGE_PATH + '/spin.gif"/>';
+					    return '<img title="Checking/Downloading..." border="0" src="' + IMAGE_PATH + '/spin.gif"/>';
 					    break;
 					  case appCache.DOWNLOADING: // DOWNLOADING == 3
-					    return '<img title="Downloading..." border="0" src="' + IMAGE_PATH + '/spin.gif"/>';
+					    return '<img title="Checking/Downloading..." border="0" src="' + IMAGE_PATH + '/spin.gif"/>';
 					    break;
 					  case appCache.UPDATEREADY:  // UPDATEREADY == 4
 					    return '<img title="Update ready" border="0" src="' + IMAGE_PATH + '/download.png"/>';
@@ -8415,7 +8427,12 @@
 
 				var updateStatus = mxUtils.bind(this, function()
 				{
-					this.offlineStatus.innerHTML = getImageTagForStatus(appCache.status);
+					var tmp = getImageTagForStatus(appCache.status);
+					
+					if (this.offlineStatus.innerHTML != tmp)
+					{
+						this.offlineStatus.innerHTML = tmp;
+					}
 				});
 				
 				mxEvent.addListener(appCache, 'checking', updateStatus);

文件差異過大導致無法顯示
+ 24 - 1
war/js/diagramly/GraphViewer.js


+ 0 - 23
war/js/diagramly/Menus.js

@@ -81,13 +81,6 @@
 			dlg.init();
 		});
 		
-		editorUi.actions.get('print').funct = function()
-		{
-			editorUi.showDialog(new PrintDialog(editorUi).container, 360,
-				(editorUi.pages != null && editorUi.pages.length > 1) ?
-				420 : 360, true, true);
-		};
-
 		// Export PDF action for chrome OS (same as print with different dialog title)
 		editorUi.actions.addAction('exportPdf', function()
 		{
@@ -1843,20 +1836,6 @@
 			}
 		})));
 
-		// Overrides arrange menu to add insert submenu
-		this.put('arrange', new Menu(mxUtils.bind(this, function(menu, parent)
-		{
-			this.addMenuItems(menu, ['toFront', 'toBack', '-'], parent);
-			this.addSubmenu('direction', menu, parent);
-			this.addMenuItems(menu, ['turn', '-'], parent);
-			this.addSubmenu('align', menu, parent);
-			this.addSubmenu('distribute', menu, parent);
-			menu.addSeparator(parent);
-			this.addSubmenu('navigation', menu, parent);
-			this.addSubmenu('layout', menu, parent);
-			this.addMenuItems(menu, ['-', 'group', 'ungroup', 'removeFromGroup', '-', 'editGeometry', 'clearWaypoints', 'autosize'], parent);
-		})));
-		
 		var methods = ['horizontalFlow', 'verticalFlow', '-', 'horizontalTree', 'verticalTree', '-', 'organic', 'circle', '-', 'fromText'];
 
 		var addInsertItem = function(menu, parent, title, method)
@@ -2324,8 +2303,6 @@
 				menu.addSeparator(parent);
 			}
 			
-			this.addSubmenu('insert', menu, parent);
-			menu.addSeparator(parent);
 			this.addMenuItems(menu, ['copyConnect', 'collapseExpand', '-'], parent);
 
 			if (typeof(MathJax) !== 'undefined')

+ 237 - 57
war/js/diagramly/vsdx/VsdxExport.js

@@ -105,8 +105,8 @@ function VsdxExport(editorUi, resDir)
 		var row = xmlDoc.createElement("Row");
 		row.setAttribute("T", type);
 		row.setAttribute("IX", index);
-		row.appendChild(createCellElem("X", x, xmlDoc));
-		row.appendChild(createCellElem("Y", y, xmlDoc));
+		row.appendChild(createCellElemScaled("X", x, xmlDoc));
+		row.appendChild(createCellElemScaled("Y", y, xmlDoc));
 		return row;
 	};
 
@@ -294,6 +294,131 @@ function VsdxExport(editorUi, resDir)
 		
 		return shape;
 	};
+
+	function getArrowType(arrow, isFilled)
+	{
+		isFilled = isFilled == null? "1" : isFilled;
+		arrow = arrow == null? "none" : arrow;
+		var key = arrow + "|" + isFilled;
+		var type = that.ARROWS_MAP[key];
+		if (type != null)
+			return type;
+		else
+			return 1;
+	};
+	
+	function getArrowSize(size)
+	{
+		if (size == null) return 2;
+		
+		if (size <=2)
+			return 0;
+		else if (size <= 3)
+			return 1;
+		else if (size <= 5)
+			return 2;
+		else if (size <= 7)
+			return 3;
+		else if (size <= 9)
+			return 4;
+		else if (size <= 22)
+			return 5;
+		else
+			return 6;
+	};
+
+	function convertMxEdge2Shape(cell, graph, xmlDoc, parentHeight, parentGeo)
+	{
+		var state = graph.view.getState(cell);
+		
+		var shape = xmlDoc.createElement("Shape");
+		shape.setAttribute("ID", cell.id);
+		shape.setAttribute("NameU", "Edge" + cell.id);
+		shape.setAttribute("LineStyle", "0");
+		shape.setAttribute("FillStyle", "0");
+		shape.setAttribute("TextStyle", "0");
+		
+		var points = state.absolutePoints;
+		var bounds = state.cellBounds;
+		
+		var hw = bounds.width/2, hh = bounds.height/2;
+		
+		shape.appendChild(createCellElemScaled("PinX", bounds.x + hw, xmlDoc));
+		shape.appendChild(createCellElemScaled("PinY", parentHeight - bounds.y - hh, xmlDoc));
+		shape.appendChild(createCellElemScaled("Width", bounds.width, xmlDoc));
+		shape.appendChild(createCellElemScaled("Height", bounds.height, xmlDoc));
+		shape.appendChild(createCellElemScaled("LocPinX", hw, xmlDoc));
+		shape.appendChild(createCellElemScaled("LocPinY", hh, xmlDoc));
+
+		var s = vsdxCanvas.state;
+		
+		var calcVsdxPoint = function(p, noHeight) 
+		{
+			var x = p.x, y = p.y;
+			x = (x - bounds.x + s.dx) * s.scale;
+			y = ((noHeight? 0 : bounds.height) - y + bounds.y - s.dy) * s.scale;
+			return {x: x, y: y};
+		};
+
+		var p0 = calcVsdxPoint(points[0], true);
+		
+		shape.appendChild(createCellElemScaled("BeginX", bounds.x + p0.x, xmlDoc));
+		shape.appendChild(createCellElemScaled("BeginY", parentHeight - bounds.y + p0.y, xmlDoc));
+
+		var pe = calcVsdxPoint(points[points.length - 1], true);
+		
+		shape.appendChild(createCellElemScaled("EndX", bounds.x + pe.x, xmlDoc));
+		shape.appendChild(createCellElemScaled("EndY", parentHeight - bounds.y + pe.y, xmlDoc));
+
+		shape.appendChild(createCellElem("BegTrigger", "2", xmlDoc));
+		shape.appendChild(createCellElem("EndTrigger", "2", xmlDoc));
+		shape.appendChild(createCellElem("ConFixedCode", "6", xmlDoc));
+		shape.appendChild(createCellElem("LockHeight", "1", xmlDoc));
+		shape.appendChild(createCellElem("LockCalcWH", "1", xmlDoc));
+		shape.appendChild(createCellElem("NoAlignBox", "1", xmlDoc));
+		shape.appendChild(createCellElem("DynFeedback", "2", xmlDoc));
+		shape.appendChild(createCellElem("GlueType", "2", xmlDoc));
+		shape.appendChild(createCellElem("ObjType", "2", xmlDoc));
+		shape.appendChild(createCellElem("NoLiveDynamics", "1", xmlDoc));
+		shape.appendChild(createCellElem("ShapeSplittable", "1", xmlDoc));
+		shape.appendChild(createCellElem("LayerMember", "0", xmlDoc));
+
+		applyMxCellStyle(state, shape, xmlDoc);
+		
+		//Edge special styles
+		var startFill =  state.style[mxConstants.STYLE_STARTFILL];
+		var startArrow = state.style[mxConstants.STYLE_STARTARROW];
+		var startSize =  state.style[mxConstants.STYLE_STARTSIZE];
+		
+		var type = getArrowType(startArrow, startFill);
+		shape.appendChild(createCellElem("BeginArrow", type, xmlDoc));
+		shape.appendChild(createCellElem("BeginArrowSize", getArrowSize(startSize), xmlDoc));
+		
+		var endFill =  state.style[mxConstants.STYLE_ENDFILL];
+		var endArrow = state.style[mxConstants.STYLE_ENDARROW];
+		var endSize =  state.style[mxConstants.STYLE_ENDSIZE];
+		
+		var type = getArrowType(endArrow, endFill);
+		shape.appendChild(createCellElem("EndArrow", type, xmlDoc));
+		shape.appendChild(createCellElem("EndArrowSize", getArrowSize(endSize), xmlDoc));
+		
+		var geoSec = xmlDoc.createElement("Section");
+		
+		geoSec.setAttribute("N", "Geometry");
+		geoSec.setAttribute("IX", "0");
+
+		for (var i = 0; i < points.length; i++)
+		{
+			var p = calcVsdxPoint(points[i]);
+			geoSec.appendChild(createRow(i==0 ? "MoveTo" : "LineTo", (i + 1), p.x, p.y, xmlDoc));
+		}
+		
+		geoSec.appendChild(createCellElem("NoFill", "1", xmlDoc));
+		geoSec.appendChild(createCellElem("NoLine", "0", xmlDoc));
+		shape.appendChild(geoSec);
+		
+		return shape;
+	};
 	
 	function convertMxCell2Shape(cell, graph, xmlDoc, parentHeight, parentGeo)
 	{
@@ -301,6 +426,7 @@ function VsdxExport(editorUi, resDir)
 		
 		if (geo != null)
 		{
+			//fix relative geo coordinates
 			if (geo.relative && parentGeo)
 			{
 				geo = geo.clone();
@@ -308,49 +434,90 @@ function VsdxExport(editorUi, resDir)
 				geo.y *= parentGeo.height;
 				geo.relative = 0;
 			}
-
-			var shape = createShape(cell.id, geo, xmlDoc, parentHeight);
-			
-			var state = graph.view.getState(cell);
-
-			applyMxCellStyle(state, shape, xmlDoc);
 			
-			vsdxCanvas.newShape(shape, geo, xmlDoc);
-
-			if (state.text != null && state.text.checkBounds())
+			if (!cell.treatAsSingle && cell.getChildCount() > 0) //Group 
 			{
+				//Create group shape as an empty shape with no geo
+				var shape = createShape(cell.id+"10000", geo, xmlDoc, parentHeight);
+				shape.setAttribute("Type", "Group");
+				
+				//Create group shape
+				var gShapes = xmlDoc.createElement("Shapes");
+
+				//translate the canvas using the group coordinates
 				vsdxCanvas.save();
+				vsdxCanvas.translate(-geo.x, -geo.y);
+
+				//Draw the actual group shape as a child (so change its geo coord to 0,0). 
+				//	In mxGraph group shape can have styles and stencil
+				var newGeo = geo.clone();
+				newGeo.x = 0;
+				newGeo.y = 0;
+				cell.setGeometry(newGeo);
+				cell.treatAsSingle = true;
+				var subShape = convertMxCell2Shape(cell, graph, xmlDoc, geo.height, geo);
+				cell.treatAsSingle = false;
+				cell.setGeometry(geo);
+				gShapes.appendChild(subShape);
 				
-				if (parentGeo)
+				//add group children
+				for (var i = 0; i < cell.children.length; i++)
 				{
-					vsdxCanvas.translate(-parentGeo.x, -parentGeo.y);
+					var child = cell.children[i];
+					var subShape;
+					
+					if (child.vertex)
+						subShape = convertMxCell2Shape(child, graph, xmlDoc, geo.height, geo);
+					else
+						subShape = convertMxEdge2Shape(child, graph, xmlDoc, geo.height, geo);
+					
+					gShapes.appendChild(subShape);
 				}
 				
-				state.text.paint(vsdxCanvas);
+				shape.appendChild(gShapes);
+				
+				//restore the canvas to before group translation 
 				vsdxCanvas.restore();
+				
+				return shape;
 			}
-			if (state.shape != null && state.shape.checkBounds())
+			else
 			{
-				vsdxCanvas.save();
+	
+				var shape = createShape(cell.id, geo, xmlDoc, parentHeight);
 				
-				if (parentGeo)
+				var state = graph.view.getState(cell);
+
+				applyMxCellStyle(state, shape, xmlDoc);
+				
+				vsdxCanvas.newShape(shape, state, xmlDoc);
+
+				//Draw text first to have its shape cell elements before visio geo.
+				if (state.text != null && state.text.checkBounds())
 				{
-					vsdxCanvas.translate(-parentGeo.x, -parentGeo.y);
+					vsdxCanvas.save();
+					state.text.paint(vsdxCanvas);
+					vsdxCanvas.restore();
+				}
+				if (state.shape != null && state.shape.checkBounds())
+				{
+					vsdxCanvas.save();
+					state.shape.paint(vsdxCanvas);
+					vsdxCanvas.restore();
 				}
-				
-				state.shape.paint(vsdxCanvas);
-				vsdxCanvas.restore();
-			}
 
-			shape.appendChild(vsdxCanvas.getShapeGeo());
+				shape.appendChild(vsdxCanvas.getShapeGeo());
 
-			vsdxCanvas.endShape();
-			shape.setAttribute("Type", vsdxCanvas.getShapeType());
+				vsdxCanvas.endShape();
+				shape.setAttribute("Type", vsdxCanvas.getShapeType());
 
-			return shape;
+				return shape;
+			}
+		}
+		else
+		{
+			return null;
 		}
-		
-		return null;
 	};
 
 	
@@ -379,45 +546,52 @@ function VsdxExport(editorUi, resDir)
 		
 		for (var id in model.cells) 
 		{
-			var c = model.cells[id];
+			var cell = model.cells[id];
 			//top-most cells
-			if (c.parent == defParent)
+			if (cell.parent == defParent)
 			{
 				var shape;
-				if (c.getChildCount() > 0) //Group 
-				{
-					var geo = c.geometry;
-					shape = createShape(c.id+"10000", geo, xmlDoc, modelAttrib.pageHeight);
-					shape.setAttribute("Type", "Group");
-					
-					var gShapes = xmlDoc.createElement("Shapes");
-
-					var newGeo = geo.clone();
-					newGeo.x = 0;
-					newGeo.y = 0;
-					c.setGeometry(newGeo);
-					var subShape = convertMxCell2Shape(c, graph, xmlDoc, geo.height, geo);
-					c.setGeometry(geo);
-					gShapes.appendChild(subShape);
-					
-					for (var i = 0; i < c.children.length; i++)
-					{
-						var subShape = convertMxCell2Shape(c.children[i], graph, xmlDoc, geo.height, geo);
-						gShapes.appendChild(subShape);
-					}
-					
-					shape.appendChild(gShapes);
-				}
+				
+				if (cell.vertex)
+					shape = convertMxCell2Shape(cell, graph, xmlDoc, modelAttrib.pageHeight);
 				else
-				{
-					shape = convertMxCell2Shape(c, graph, xmlDoc, modelAttrib.pageHeight);
-				}
+					shape = convertMxEdge2Shape(cell, graph, xmlDoc, modelAttrib.pageHeight);
 				
 				if (shape != null)
 					shapes.appendChild(shape);
 			}
 		}
 		
+        var connects = xmlDoc.createElement("Connects");
+        root.appendChild(connects);
+
+        //Second pass to add edges (connections)
+		for (var id in model.cells) 
+		{
+			var cell = model.cells[id];
+
+			if (cell.edge)
+			{
+				if (cell.source)
+				{
+					var connect = xmlDoc.createElement("Connect");
+					connect.setAttribute("FromSheet", cell.id);
+					connect.setAttribute("FromCell", "BeginX");
+					connect.setAttribute("ToSheet", cell.source.id);
+					connects.appendChild(connect);
+				}
+				
+				if (cell.target)
+				{
+					var connect = xmlDoc.createElement("Connect");
+					connect.setAttribute("FromSheet", cell.id);
+					connect.setAttribute("FromCell", "EndX");
+					connect.setAttribute("ToSheet", cell.target.id);
+					connects.appendChild(connect);
+				}
+			}
+		}
+
 		xmlDoc.appendChild(root);
 
 		return xmlDoc;
@@ -608,3 +782,9 @@ VsdxExport.prototype.VSDX_ENC = "ISO-8859-1";
 VsdxExport.prototype.PART_NAME = "PartName";
 VsdxExport.prototype.CONTENT_TYPES_XML = "[Content_Types].xml";
 VsdxExport.prototype.VISIO_PAGES_RELS = "visio/pages/_rels/";
+VsdxExport.prototype.ARROWS_MAP = {
+	"none|1": 0, "none|0": 0, "open|1": 1, "open|0": 1, "block|1": 4, "block|1": 14, "classic|1": 5, "classic|0": 17,
+	"oval|1": 10, "oval|0": 20, "diamond|1": 11, "diamond|0": 22, "blockThin|1": 2, "blockThin|0": 2, "dash|1": 23, "dash|0": 23,
+	"ERone|1": 24, "ERone|0": 24, "ERmandOne|1": 25, "ERmandOne|0": 25, "ERmany|1": 27, "ERmany|0": 27, "ERoneToMany|1": 28, "ERoneToMany|0": 28,
+	"ERzeroToMany|1": 29, "ERzeroToMany|0": 29, "ERzeroToOne|1": 30, "ERzeroToOne|1": 30, "openAsync|1": 9, "openAsync|0": 9
+};

+ 20 - 2
war/js/diagramly/vsdx/mxVsdxCanvas2D.js

@@ -68,11 +68,12 @@ mxVsdxCanvas2D.prototype.createGeoSec = function ()
  *  
  * Create a new shape.
  */
-mxVsdxCanvas2D.prototype.newShape = function (shape, xmGeo, xmlDoc)
+mxVsdxCanvas2D.prototype.newShape = function (shape, cellState, xmlDoc)
 {
 	this.geoIndex = 0;
 	this.shape = shape;
-	this.xmGeo = xmGeo;
+	this.cellState = cellState;
+	this.xmGeo = cellState.cell.geometry;
 	this.xmlDoc = xmlDoc;
 	this.geoSec = null;
 	this.shapeImg = null;
@@ -557,6 +558,23 @@ mxVsdxCanvas2D.prototype.text = function(x, y, w, h, str, align, valign, wrap, f
 		}
 
 		//TODO support HTML text formatting and remaining attributes
+		if (this.cellState.style['html'] == '1')
+    	{
+    		if (mxUtils.getValue(this.cellState.style, 'nl2Br', '1') != '0')
+			{
+				// Removes newlines from HTML and converts breaks to newlines
+				// to match the HTML output in plain text
+    			str = str.replace(/\n/g, '').replace(/<br\s*.?>/g, '\n');
+			}
+    		
+    		// Removes HTML tags
+			if (this.html2txtDiv == null)
+				this.html2txtDiv = document.createElement('div');
+			
+			this.html2txtDiv.innerHTML = str;
+			str = mxUtils.extractTextWithWhitespace(this.html2txtDiv.childNodes);
+    	}
+		
 		var s = this.state;
 		var geo = this.xmGeo;
 

文件差異過大導致無法顯示
+ 1 - 1
war/js/embed-static.min.js


文件差異過大導致無法顯示
+ 0 - 898
war/js/mxgraph/Dialogs.js


文件差異過大導致無法顯示
+ 903 - 0
war/js/mxgraph/Editor.js


+ 24 - 14
war/js/mxgraph/EditorUi.js

@@ -1374,8 +1374,12 @@ EditorUi.prototype.initCanvas = function()
 		this.chromelessToolbar.style.backgroundColor = '#000000';
 		this.chromelessToolbar.style.padding = '10px 10px 8px 10px';
 		this.chromelessToolbar.style.left = '50%';
-		mxUtils.setPrefixedStyle(this.chromelessToolbar.style, 'borderRadius', '20px');
-		mxUtils.setPrefixedStyle(this.chromelessToolbar.style, 'transition', 'opacity 600ms ease-in-out');
+		
+		if (!mxClient.IS_VML)
+		{
+			mxUtils.setPrefixedStyle(this.chromelessToolbar.style, 'borderRadius', '20px');
+			mxUtils.setPrefixedStyle(this.chromelessToolbar.style, 'transition', 'opacity 600ms ease-in-out');
+		}
 		
 		var updateChromelessToolbarPosition = mxUtils.bind(this, function()
 		{
@@ -1418,7 +1422,7 @@ EditorUi.prototype.initCanvas = function()
 		{
 			this.actions.get('previousPage').funct();
 			mxEvent.consume(evt);
-		}), Editor.previousLargeImage, mxResources.get('previousPage') || 'Previous Page');
+		}), Editor.previousLargeImage, mxResources.get('previousPage'));
 		
 		
 		var pageInfo = document.createElement('div');
@@ -1433,7 +1437,7 @@ EditorUi.prototype.initCanvas = function()
 		{
 			this.actions.get('nextPage').funct();
 			mxEvent.consume(evt);
-		}), Editor.nextLargeImage, mxResources.get('nextPage') || 'Next Page');
+		}), Editor.nextLargeImage, mxResources.get('nextPage'));
 		
 		var updatePageInfo = mxUtils.bind(this, function()
 		{
@@ -1474,13 +1478,13 @@ EditorUi.prototype.initCanvas = function()
 		{
 			this.actions.get('zoomOut').funct();
 			mxEvent.consume(evt);
-		}), Editor.zoomOutLargeImage, (mxResources.get('zoomOut') || 'Zoom Out') + ' (Alt+Mousewheel)');
+		}), Editor.zoomOutLargeImage, mxResources.get('zoomOut') + ' (Alt+Mousewheel)');
 		
 		addButton(mxUtils.bind(this, function(evt)
 		{
 			this.actions.get('zoomIn').funct();
 			mxEvent.consume(evt);
-		}), Editor.zoomInLargeImage, (mxResources.get('zoomIn') || 'Zoom In') + ' (Alt+Mousewheel)');
+		}), Editor.zoomInLargeImage, mxResources.get('zoomIn') + ' (Alt+Mousewheel)');
 		
 		addButton(mxUtils.bind(this, function(evt)
 		{
@@ -1503,7 +1507,7 @@ EditorUi.prototype.initCanvas = function()
 			}
 			
 			mxEvent.consume(evt);
-		}), Editor.actualSizeLargeImage, mxResources.get('fit') || 'Fit');
+		}), Editor.actualSizeLargeImage, mxResources.get('fit'));
 
 		// Changes toolbar opacity on hover
 		var fadeThread = null;
@@ -1597,7 +1601,7 @@ EditorUi.prototype.initCanvas = function()
 				}
 				
 				mxEvent.consume(evt);
-			}), Editor.layersLargeImage, mxResources.get('layers') || 'Layers');
+			}), Editor.layersLargeImage, mxResources.get('layers'));
 			
 			// Shows/hides layers button depending on content
 			var model = graph.getModel();
@@ -1607,7 +1611,13 @@ EditorUi.prototype.initCanvas = function()
 				 layersButton.style.display = (model.getChildCount(model.root) > 1) ? '' : 'none';
 			});
 		}
-
+		
+		addButton(mxUtils.bind(this, function(evt)
+		{
+			this.actions.get('print').funct();
+			mxEvent.consume(evt);
+		}), Editor.printLargeImage, mxResources.get('print'));
+		
 		if (this.editor.editButtonLink != null)
 		{
 			addButton(mxUtils.bind(this, function(evt)
@@ -1622,9 +1632,9 @@ EditorUi.prototype.initCanvas = function()
 				}
 				
 				mxEvent.consume(evt);
-			}), Editor.editLargeImage, mxResources.get('openInNewWindow') || 'Open in New Window');
+			}), Editor.editLargeImage, mxResources.get('openInNewWindow'));
 		}
-		
+
 		if (graph.lightbox && this.container != document.body)
 		{
 			addButton(mxUtils.bind(this, function(evt)
@@ -1638,14 +1648,14 @@ EditorUi.prototype.initCanvas = function()
 					this.destroy();
 					mxEvent.consume(evt);
 				}
-			}), Editor.closeLargeImage, (mxResources.get('close') || 'Close') + ' (Escape)');
+			}), Editor.closeLargeImage, mxResources.get('close') + ' (Escape)');
 		}
 
 		// Initial state invisible
 		this.chromelessToolbar.style.display = 'none';
+		mxUtils.setPrefixedStyle(this.chromelessToolbar.style, 'transform', 'translate(-50%,0)');
 		graph.container.appendChild(this.chromelessToolbar);
-		this.chromelessToolbar.style.marginLeft = -(btnCount * 24 + 10) + 'px';
-		
+
 		// Installs handling of hightligh and handling links to relative links and anchors
 		this.addChromelessClickHandler();
 		

文件差異過大導致無法顯示
+ 1 - 1
war/js/reader.min.js


文件差異過大導致無法顯示
+ 461 - 403
war/js/viewer.min.js