VsdxExport.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /**
  2. * Export mxFile as Vsdx file
  3. */
  4. function VsdxExport(editorUi, resDir)
  5. {
  6. var that = this;
  7. resDir = resDir || "js/diagramly/vsdx/resources"
  8. var vsdxCanvas = new mxVsdxCanvas2D();
  9. /**
  10. * Fill the required files in vsdx format which are constants in our exporter
  11. * @param zip JSZip of vsdx file
  12. * @param pageCount The number of pages in the mxFile
  13. * @callback called when all files are loaded in the zip
  14. */
  15. function createVsdxSkeleton(zip, pageCount, callback)
  16. {
  17. mxUtils.get(resDir + "/allConstants.json", function(req)
  18. {
  19. var files = JSON.parse(req.request.responseText);
  20. for (var id in files)
  21. {
  22. if (pageCount > 1 && id == that.CONTENT_TYPES_XML)
  23. {
  24. //Add the remaining pages
  25. var doc = mxUtils.parseXml(files[id]);
  26. var root = doc.documentElement;
  27. var children = root.children;
  28. var page1 = null;
  29. for (var i = 0; i < children.length; i++)
  30. {
  31. var child = children[i];
  32. if ("/visio/pages/page1.xml" == child.getAttribute(that.PART_NAME))
  33. {
  34. page1 = child;
  35. }
  36. }
  37. for (var i = 2; i <= pageCount; i++)
  38. {
  39. var newPage = page1.cloneNode();
  40. newPage.setAttribute(that.PART_NAME, "/visio/pages/page" + i + ".xml");
  41. root.appendChild(newPage);
  42. }
  43. writeXmlDoc2Zip(zip, id, doc, true);
  44. }
  45. else
  46. {
  47. zip.file(id, files[id]);
  48. }
  49. }
  50. if (callback) callback();
  51. });
  52. };
  53. function getGraphAttributes(graph)
  54. {
  55. var attr = {};
  56. try
  57. {
  58. //This doesn't work when pageView is off
  59. // // Computes the horizontal and vertical page count
  60. // var bounds = graph.getGraphBounds();
  61. // var sc = graph.view.scale;
  62. // var bgBounds = graph.view.getBackgroundPageBounds();
  63. //
  64. // var x0 = Math.round((bounds.x - bgBounds.x) / sc);
  65. // var y0 = Math.round((bounds.y - bgBounds.y) / sc);
  66. //
  67. // var hpages = Math.max(1, Math.ceil((bounds.width / sc + x0) / graph.pageFormat.width));
  68. // var vpages = Math.max(1, Math.ceil((bounds.height / sc + y0) / graph.pageFormat.height));
  69. // Computes the horizontal and vertical page count
  70. var bounds = graph.getGraphBounds().clone();
  71. var sc = graph.view.scale;
  72. var tr = graph.view.translate;
  73. var x0 = Math.round(bounds.x / sc) - tr.x;
  74. var y0 = Math.round(bounds.y / sc) - tr.y;
  75. // Store the available page area
  76. var availableWidth = graph.pageFormat.width;
  77. var availableHeight = graph.pageFormat.height;
  78. if (x0 < 0)
  79. {
  80. x0 += Math.ceil((tr.x - bounds.x / sc) / availableWidth) * availableWidth;
  81. }
  82. if (y0 < 0)
  83. {
  84. y0 += Math.ceil((tr.y - bounds.y / sc) / availableHeight) * availableHeight;
  85. }
  86. var hpages = Math.max(1, Math.ceil((bounds.width / sc + x0) / availableWidth));
  87. var vpages = Math.max(1, Math.ceil((bounds.height / sc + y0) / availableHeight));
  88. attr['gridEnabled'] = graph.gridEnabled;
  89. attr['gridSize'] = graph.gridSize;
  90. attr['guidesEnabled'] = graph.graphHandler.guidesEnabled
  91. attr['pageVisible'] = graph.pageVisible;
  92. attr['pageScale'] = graph.pageScale;
  93. attr['pageWidth'] = graph.pageFormat.width * hpages;
  94. attr['pageHeight'] = graph.pageFormat.height * vpages;
  95. attr['backgroundClr'] = graph.background;
  96. attr['mathEnabled'] = graph.mathEnabled;
  97. attr['shadowVisible'] = graph.shadowVisible;
  98. }
  99. catch(e)
  100. {
  101. //nothing
  102. }
  103. return attr;
  104. };
  105. function createCellElemScaled(name, val, xmlDoc)
  106. {
  107. return createCellElem(name, val / that.CONVERSION_FACTOR, xmlDoc);
  108. };
  109. function createCellElem(name, val, xmlDoc)
  110. {
  111. var cell = xmlDoc.createElement("Cell");
  112. cell.setAttribute("N", name);
  113. cell.setAttribute("V", val);
  114. return cell;
  115. };
  116. function createRow(type, index, x, y, xmlDoc)
  117. {
  118. var row = xmlDoc.createElement("Row");
  119. row.setAttribute("T", type);
  120. row.setAttribute("IX", index);
  121. row.appendChild(createCellElemScaled("X", x, xmlDoc));
  122. row.appendChild(createCellElemScaled("Y", y, xmlDoc));
  123. return row;
  124. };
  125. function applyMxCellStyle(state, shape, xmlDoc)
  126. {
  127. var fillClr = state.style[mxConstants.STYLE_FILLCOLOR];
  128. if (!fillClr || fillClr == "none")
  129. {
  130. shape.appendChild(createCellElem("FillPattern", 0, xmlDoc));
  131. }
  132. else
  133. {
  134. shape.appendChild(createCellElem("FillForegnd", fillClr, xmlDoc));
  135. var gradClr = state.style[mxConstants.STYLE_GRADIENTCOLOR];
  136. if (gradClr && gradClr != "none")
  137. {
  138. shape.appendChild(createCellElem("FillBkgnd", gradClr, xmlDoc));
  139. var gradDir = state.style[mxConstants.STYLE_GRADIENT_DIRECTION];
  140. var dir = 28;
  141. if (gradDir)
  142. {
  143. switch(gradDir)
  144. {
  145. case mxConstants.DIRECTION_EAST:
  146. dir = 25;
  147. break
  148. case mxConstants.DIRECTION_WEST:
  149. dir = 27;
  150. break
  151. case mxConstants.DIRECTION_NORTH:
  152. dir = 30;
  153. break
  154. }
  155. }
  156. shape.appendChild(createCellElem("FillPattern", dir, xmlDoc));
  157. }
  158. }
  159. var strokeClr = state.style[mxConstants.STYLE_STROKECOLOR];
  160. if (!strokeClr || strokeClr == "none")
  161. shape.appendChild(createCellElem("LinePattern", 0, xmlDoc));
  162. else
  163. shape.appendChild(createCellElem("LineColor", strokeClr, xmlDoc));
  164. var strokeW = state.style[mxConstants.STYLE_STROKEWIDTH];
  165. if (strokeW) shape.appendChild(createCellElemScaled("LineWeight", strokeW, xmlDoc));
  166. var opacity = state.style[mxConstants.STYLE_OPACITY];
  167. var fillOpaq;
  168. var strkOpaq;
  169. if (opacity)
  170. {
  171. fillOpaq = opacity;
  172. strkOpaq = opacity;
  173. }
  174. else
  175. {
  176. fillOpaq = state.style[mxConstants.STYLE_FILL_OPACITY];
  177. strkOpaq = state.style[mxConstants.STYLE_STROKE_OPACITY];
  178. }
  179. if (fillOpaq) shape.appendChild(createCellElem("FillForegndTrans", 1 - parseInt(fillOpaq)/100.0, xmlDoc));
  180. if (strkOpaq) shape.appendChild(createCellElem("LineColorTrans", 1 - parseInt(strkOpaq)/100.0, xmlDoc));
  181. var isDashed = state.style[mxConstants.STYLE_DASHED];
  182. if (isDashed == 1)
  183. {
  184. var dashPatrn = state.style[mxConstants.STYLE_DASH_PATTERN];
  185. var pattern = 9
  186. if (dashPatrn)
  187. {
  188. //We only support the patterns of draw.io UI
  189. switch(dashPatrn)
  190. {
  191. case "1 1":
  192. pattern = 10;
  193. break;
  194. case "1 2":
  195. pattern = 3;
  196. break;
  197. case "1 4":
  198. pattern = 17;
  199. break;
  200. }
  201. }
  202. shape.appendChild(createCellElem("LinePattern", pattern, xmlDoc));
  203. }
  204. var hasShadow = state.style[mxConstants.STYLE_SHADOW];
  205. if (hasShadow == 1)
  206. {
  207. shape.appendChild(createCellElem("ShdwPattern", 1, xmlDoc));
  208. shape.appendChild(createCellElem("ShdwForegnd", '#000000', xmlDoc));
  209. shape.appendChild(createCellElem("ShdwForegndTrans", 0.6, xmlDoc));
  210. shape.appendChild(createCellElem("ShapeShdwType", 1, xmlDoc));
  211. shape.appendChild(createCellElem("ShapeShdwOffsetX", '0.02946278254943948', xmlDoc));
  212. shape.appendChild(createCellElem("ShapeShdwOffsetY", '-0.02946278254943948', xmlDoc));
  213. shape.appendChild(createCellElem("ShapeShdwScaleFactor", '1', xmlDoc));
  214. shape.appendChild(createCellElem("ShapeShdwBlur", '0.05555555555555555', xmlDoc));
  215. shape.appendChild(createCellElem("ShapeShdwShow", 2, xmlDoc));
  216. }
  217. //Probably we don't need margins as the canvas get the modified position?
  218. /*
  219. var topMargin = state.style[mxConstants.STYLE_SPACING_TOP];
  220. if (topMargin) shape.appendChild(createCellElemScaled("TopMargin", parseFloat(topMargin) * 2 + 2.8 , xmlDoc));
  221. /* //Defines label bottom spacing
  222. double bottomMargin = getBottomSpacing() * 100/100;
  223. if (bottomMargin != 0)
  224. {
  225. styleMap.put(mxConstants.STYLE_SPACING_BOTTOM, Double.toString(bottomMargin));
  226. }
  227. //Defines label left spacing
  228. double leftMargin = getLeftSpacing() * 100/100;
  229. if (leftMargin != 0)
  230. {
  231. styleMap.put(mxConstants.STYLE_SPACING_LEFT, Double.toString(leftMargin));
  232. }
  233. //Defines label right spacing
  234. double rightMargin = getRightSpacing() * 100/100;
  235. if(rightMargin !=0)
  236. {
  237. styleMap.put(mxConstants.STYLE_SPACING_RIGHT, Double.toString(rightMargin));
  238. }*/
  239. //Direction is not clear that we need it
  240. /*
  241. var direction = state.style[mxConstants.STYLE_DIRECTION];
  242. if (direction != mxConstants.DIRECTION_EAST)
  243. {
  244. styleMap.put(mxConstants.STYLE_DIRECTION, direction);
  245. }
  246. */
  247. var flibX = state.style[mxConstants.STYLE_FLIPH];
  248. if (flibX == 1) shape.appendChild(createCellElem("FlipX", 1, xmlDoc));
  249. var flibY = state.style[mxConstants.STYLE_FLIPV];
  250. if (flibY == 1) shape.appendChild(createCellElem("FlipY", 1, xmlDoc));
  251. var rounded = state.style[mxConstants.STYLE_ROUNDED];
  252. if (rounded == 1) shape.appendChild(createCellElemScaled("Rounding", state.cell.geometry.width*0.1, xmlDoc));
  253. //TODO for some reason, visio doesn't show the label (text) background color!
  254. //May be we need mxSvgCanvas2D.prototype.addTextBackground = function(node, str, x, y, w, h, align, valign, overflow)
  255. var lbkgnd = state.style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR];
  256. if (lbkgnd) shape.appendChild(createCellElem("TextBkgnd", lbkgnd, xmlDoc));
  257. };
  258. function createShape(id, geo, xmlDoc, parentHeight)
  259. {
  260. var shape = xmlDoc.createElement("Shape");
  261. shape.setAttribute("ID", id);
  262. shape.setAttribute("NameU", "Shape" + id);
  263. shape.setAttribute("LineStyle", "0");
  264. shape.setAttribute("FillStyle", "0");
  265. shape.setAttribute("TextStyle", "0");
  266. var hw = geo.width/2, hh = geo.height/2;
  267. shape.appendChild(createCellElemScaled("PinX", geo.x + hw, xmlDoc));
  268. shape.appendChild(createCellElemScaled("PinY", parentHeight - geo.y - hh, xmlDoc));
  269. shape.appendChild(createCellElemScaled("Width", geo.width, xmlDoc));
  270. shape.appendChild(createCellElemScaled("Height", geo.height, xmlDoc));
  271. shape.appendChild(createCellElemScaled("LocPinX", hw, xmlDoc));
  272. shape.appendChild(createCellElemScaled("LocPinY", hh, xmlDoc));
  273. return shape;
  274. };
  275. function getArrowType(arrow, isFilled)
  276. {
  277. isFilled = isFilled == null? "1" : isFilled;
  278. arrow = arrow == null? "none" : arrow;
  279. var key = arrow + "|" + isFilled;
  280. var type = that.ARROWS_MAP[key];
  281. if (type != null)
  282. return type;
  283. else
  284. return 1;
  285. };
  286. function getArrowSize(size)
  287. {
  288. if (size == null) return 2;
  289. if (size <=2)
  290. return 0;
  291. else if (size <= 3)
  292. return 1;
  293. else if (size <= 5)
  294. return 2;
  295. else if (size <= 7)
  296. return 3;
  297. else if (size <= 9)
  298. return 4;
  299. else if (size <= 22)
  300. return 5;
  301. else
  302. return 6;
  303. };
  304. function createEdge(cell, graph, xmlDoc, parentHeight)
  305. {
  306. var state = graph.view.getState(cell);
  307. var shape = xmlDoc.createElement("Shape");
  308. shape.setAttribute("ID", cell.id);
  309. shape.setAttribute("NameU", "Edge" + cell.id);
  310. shape.setAttribute("LineStyle", "0");
  311. shape.setAttribute("FillStyle", "0");
  312. shape.setAttribute("TextStyle", "0");
  313. var s = vsdxCanvas.state;
  314. var points = state.absolutePoints;
  315. var bounds = state.cellBounds;
  316. var hw = bounds.width/2, hh = bounds.height/2;
  317. shape.appendChild(createCellElemScaled("PinX", bounds.x + hw, xmlDoc));
  318. shape.appendChild(createCellElemScaled("PinY", parentHeight - bounds.y - hh, xmlDoc));
  319. shape.appendChild(createCellElemScaled("Width", bounds.width, xmlDoc));
  320. shape.appendChild(createCellElemScaled("Height", bounds.height, xmlDoc));
  321. shape.appendChild(createCellElemScaled("LocPinX", hw, xmlDoc));
  322. shape.appendChild(createCellElemScaled("LocPinY", hh, xmlDoc));
  323. vsdxCanvas.newEdge(shape, state, xmlDoc);
  324. var calcVsdxPoint = function(p, noHeight)
  325. {
  326. var x = p.x, y = p.y;
  327. x = (x * s.scale - bounds.x + s.dx) ;
  328. y = ((noHeight? 0 : bounds.height) - y * s.scale + bounds.y - s.dy) ;
  329. return {x: x, y: y};
  330. };
  331. var p0 = calcVsdxPoint(points[0], true);
  332. shape.appendChild(createCellElemScaled("BeginX", bounds.x + p0.x, xmlDoc));
  333. shape.appendChild(createCellElemScaled("BeginY", parentHeight - bounds.y + p0.y, xmlDoc));
  334. var pe = calcVsdxPoint(points[points.length - 1], true);
  335. shape.appendChild(createCellElemScaled("EndX", bounds.x + pe.x, xmlDoc));
  336. shape.appendChild(createCellElemScaled("EndY", parentHeight - bounds.y + pe.y, xmlDoc));
  337. shape.appendChild(createCellElem("BegTrigger", "2", xmlDoc));
  338. shape.appendChild(createCellElem("EndTrigger", "2", xmlDoc));
  339. shape.appendChild(createCellElem("ConFixedCode", "6", xmlDoc));
  340. shape.appendChild(createCellElem("LockHeight", "1", xmlDoc));
  341. shape.appendChild(createCellElem("LockCalcWH", "1", xmlDoc));
  342. shape.appendChild(createCellElem("NoAlignBox", "1", xmlDoc));
  343. shape.appendChild(createCellElem("DynFeedback", "2", xmlDoc));
  344. shape.appendChild(createCellElem("GlueType", "2", xmlDoc));
  345. shape.appendChild(createCellElem("ObjType", "2", xmlDoc));
  346. shape.appendChild(createCellElem("NoLiveDynamics", "1", xmlDoc));
  347. shape.appendChild(createCellElem("ShapeSplittable", "1", xmlDoc));
  348. shape.appendChild(createCellElem("LayerMember", "0", xmlDoc));
  349. applyMxCellStyle(state, shape, xmlDoc);
  350. //Edge special styles
  351. var startFill = state.style[mxConstants.STYLE_STARTFILL];
  352. var startArrow = state.style[mxConstants.STYLE_STARTARROW];
  353. var startSize = state.style[mxConstants.STYLE_STARTSIZE];
  354. var type = getArrowType(startArrow, startFill);
  355. shape.appendChild(createCellElem("BeginArrow", type, xmlDoc));
  356. shape.appendChild(createCellElem("BeginArrowSize", getArrowSize(startSize), xmlDoc));
  357. var endFill = state.style[mxConstants.STYLE_ENDFILL];
  358. var endArrow = state.style[mxConstants.STYLE_ENDARROW];
  359. var endSize = state.style[mxConstants.STYLE_ENDSIZE];
  360. var type = getArrowType(endArrow, endFill);
  361. shape.appendChild(createCellElem("EndArrow", type, xmlDoc));
  362. shape.appendChild(createCellElem("EndArrowSize", getArrowSize(endSize), xmlDoc));
  363. //Draw text first to have its shape cell elements before visio geo.
  364. if (state.text != null && state.text.checkBounds())
  365. {
  366. vsdxCanvas.save();
  367. state.text.paint(vsdxCanvas);
  368. vsdxCanvas.restore();
  369. }
  370. var geoSec = xmlDoc.createElement("Section");
  371. geoSec.setAttribute("N", "Geometry");
  372. geoSec.setAttribute("IX", "0");
  373. for (var i = 0; i < points.length; i++)
  374. {
  375. var p = calcVsdxPoint(points[i]);
  376. geoSec.appendChild(createRow(i==0 ? "MoveTo" : "LineTo", (i + 1), p.x, p.y, xmlDoc));
  377. }
  378. geoSec.appendChild(createCellElem("NoFill", "1", xmlDoc));
  379. geoSec.appendChild(createCellElem("NoLine", "0", xmlDoc));
  380. shape.appendChild(geoSec);
  381. return shape;
  382. };
  383. function convertMxCell2Shape(cell, graph, xmlDoc, parentHeight, parentGeo)
  384. {
  385. var geo = cell.geometry;
  386. if (geo != null)
  387. {
  388. //fix relative geo coordinates
  389. if (geo.relative && parentGeo)
  390. {
  391. geo = geo.clone();
  392. geo.x *= parentGeo.width;
  393. geo.y *= parentGeo.height;
  394. geo.relative = 0;
  395. }
  396. if (!cell.treatAsSingle && cell.getChildCount() > 0) //Group
  397. {
  398. //Create group shape as an empty shape with no geo
  399. var shape = createShape(cell.id+"10000", geo, xmlDoc, parentHeight);
  400. shape.setAttribute("Type", "Group");
  401. //Create group shape
  402. var gShapes = xmlDoc.createElement("Shapes");
  403. //translate the canvas using the group coordinates
  404. vsdxCanvas.save();
  405. vsdxCanvas.translate(-geo.x, -geo.y);
  406. //Draw the actual group shape as a child (so change its geo coord to 0,0).
  407. // In mxGraph group shape can have styles and stencil
  408. var newGeo = geo.clone();
  409. newGeo.x = 0;
  410. newGeo.y = 0;
  411. cell.setGeometry(newGeo);
  412. cell.treatAsSingle = true;
  413. var subShape = convertMxCell2Shape(cell, graph, xmlDoc, geo.height, geo);
  414. cell.treatAsSingle = false;
  415. cell.setGeometry(geo);
  416. gShapes.appendChild(subShape);
  417. //add group children
  418. for (var i = 0; i < cell.children.length; i++)
  419. {
  420. var child = cell.children[i];
  421. var subShape = convertMxCell2Shape(child, graph, xmlDoc, geo.height, geo);
  422. gShapes.appendChild(subShape);
  423. }
  424. shape.appendChild(gShapes);
  425. //restore the canvas to before group translation
  426. vsdxCanvas.restore();
  427. return shape;
  428. }
  429. else if (cell.vertex)
  430. {
  431. var shape = createShape(cell.id, geo, xmlDoc, parentHeight);
  432. var state = graph.view.getState(cell);
  433. applyMxCellStyle(state, shape, xmlDoc);
  434. vsdxCanvas.newShape(shape, state, xmlDoc);
  435. //Draw text first to have its shape cell elements before visio geo.
  436. if (state.text != null && state.text.checkBounds())
  437. {
  438. vsdxCanvas.save();
  439. state.text.paint(vsdxCanvas);
  440. vsdxCanvas.restore();
  441. }
  442. if (state.shape != null && state.shape.checkBounds())
  443. {
  444. vsdxCanvas.save();
  445. state.shape.paint(vsdxCanvas);
  446. vsdxCanvas.restore();
  447. }
  448. shape.appendChild(vsdxCanvas.getShapeGeo());
  449. vsdxCanvas.endShape();
  450. shape.setAttribute("Type", vsdxCanvas.getShapeType());
  451. return shape;
  452. }
  453. else
  454. {
  455. return createEdge(cell, graph, xmlDoc, parentHeight);
  456. }
  457. }
  458. else
  459. {
  460. return null;
  461. }
  462. };
  463. function convertMxModel2Page(graph, modelAttrib)
  464. {
  465. var xmlDoc = mxUtils.createXmlDocument();
  466. var root = xmlDoc.createElement("PageContents");
  467. root.setAttribute("xmlns", that.XMLNS);
  468. root.setAttribute("xmlns:r", that.XMLNS_R);
  469. root.setAttribute("xml:space", that.XML_SPACE);
  470. var shapes = xmlDoc.createElement("Shapes");
  471. root.appendChild(shapes);
  472. var model = graph.model;
  473. var t = graph.view.translate;
  474. var s = graph.view.scale;
  475. var bounds = graph.getGraphBounds();
  476. var shiftX = 0, shiftY = 0;
  477. //-ve pages
  478. if (bounds.x / s < t.x || bounds.y / s < t.y)
  479. {
  480. shiftX = Math.ceil((t.x - bounds.x / s) / graph.pageFormat.width) * graph.pageFormat.width;
  481. shiftY = Math.ceil((t.y - bounds.y / s) / graph.pageFormat.height) * graph.pageFormat.height;
  482. }
  483. vsdxCanvas.save();
  484. vsdxCanvas.translate(-t.x + shiftX, -t.y + shiftY);
  485. vsdxCanvas.scale(1 / s);
  486. vsdxCanvas.newPage();
  487. var defParent = graph.getDefaultParent();
  488. for (var id in model.cells)
  489. {
  490. var cell = model.cells[id];
  491. //top-most cells
  492. if (cell.parent == defParent)
  493. {
  494. var shape = convertMxCell2Shape(cell, graph, xmlDoc, modelAttrib.pageHeight);
  495. if (shape != null)
  496. shapes.appendChild(shape);
  497. }
  498. }
  499. var connects = xmlDoc.createElement("Connects");
  500. root.appendChild(connects);
  501. //Second pass to add edges (connections)
  502. for (var id in model.cells)
  503. {
  504. var cell = model.cells[id];
  505. if (cell.edge)
  506. {
  507. if (cell.source)
  508. {
  509. var connect = xmlDoc.createElement("Connect");
  510. connect.setAttribute("FromSheet", cell.id);
  511. connect.setAttribute("FromCell", "BeginX");
  512. connect.setAttribute("ToSheet", cell.source.id);
  513. connects.appendChild(connect);
  514. }
  515. if (cell.target)
  516. {
  517. var connect = xmlDoc.createElement("Connect");
  518. connect.setAttribute("FromSheet", cell.id);
  519. connect.setAttribute("FromCell", "EndX");
  520. connect.setAttribute("ToSheet", cell.target.id);
  521. connects.appendChild(connect);
  522. }
  523. }
  524. }
  525. xmlDoc.appendChild(root);
  526. vsdxCanvas.restore();
  527. return xmlDoc;
  528. };
  529. function writeXmlDoc2Zip(zip, name, xmlDoc, noHeader)
  530. {
  531. zip.file(name, (noHeader? "" : "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>") + mxUtils.getXml(xmlDoc));
  532. };
  533. function addPagesXML(zip, pages, modelsAttr)
  534. {
  535. var pagesXmlDoc = mxUtils.createXmlDocument();
  536. var pagesRelsXmlDoc = mxUtils.createXmlDocument();
  537. var pagesRoot = pagesXmlDoc.createElement("Pages");
  538. pagesRoot.setAttribute("xmlns", that.XMLNS);
  539. pagesRoot.setAttribute("xmlns:r", that.XMLNS_R);
  540. pagesRoot.setAttribute("xml:space", that.XML_SPACE);
  541. var pagesRelsRoot = pagesRelsXmlDoc.createElement("Relationships");
  542. pagesRelsRoot.setAttribute("xmlns", that.RELS_XMLNS);
  543. var i = 1;
  544. for (var name in pages)
  545. {
  546. var pageName = "page" + i + ".xml";
  547. var pageE = pagesXmlDoc.createElement("Page");
  548. pageE.setAttribute("ID", i-1);
  549. pageE.setAttribute("NameU", name);
  550. pageE.setAttribute("Name", name);
  551. var pageSheet = pagesXmlDoc.createElement("PageSheet");
  552. var modelAttr = modelsAttr[name];
  553. pageSheet.appendChild(createCellElemScaled("PageWidth", modelAttr['pageWidth'], pagesXmlDoc));
  554. pageSheet.appendChild(createCellElemScaled("PageHeight", modelAttr['pageHeight'], pagesXmlDoc));
  555. pageSheet.appendChild(createCellElem("PageScale", modelAttr['pageScale'], pagesXmlDoc));
  556. pageSheet.appendChild(createCellElem("DrawingScale", 1, pagesXmlDoc));
  557. var relE = pagesXmlDoc.createElement("Rel");
  558. relE.setAttribute("r:id", "rId" + i);
  559. pageE.appendChild(pageSheet);
  560. pageE.appendChild(relE);
  561. pagesRoot.appendChild(pageE);
  562. var relationship = pagesRelsXmlDoc.createElement("Relationship");
  563. relationship.setAttribute("Id", "rId" + i);
  564. relationship.setAttribute("Type", that.PAGES_TYPE);
  565. relationship.setAttribute("Target", pageName);
  566. pagesRelsRoot.appendChild(relationship);
  567. //Note:Each page rels is created with the skeleton as they are constants
  568. //write the page docs
  569. var xmlDoc = pages[name];
  570. writeXmlDoc2Zip(zip, that.VISIO_PAGES + pageName, xmlDoc);
  571. i++;
  572. }
  573. pagesXmlDoc.appendChild(pagesRoot);
  574. pagesRelsXmlDoc.appendChild(pagesRelsRoot);
  575. writeXmlDoc2Zip(zip, that.VISIO_PAGES + "pages.xml", pagesXmlDoc);
  576. writeXmlDoc2Zip(zip, that.VISIO_PAGES + "_rels/pages.xml.rels", pagesRelsXmlDoc);
  577. }
  578. function addImagesRels(zip, pIndex)
  579. {
  580. //create a new page rels file
  581. var fId = that.VISIO_PAGES_RELS + "page" + pIndex + ".xml.rels";
  582. var pageRelDoc = mxUtils.createXmlDocument();
  583. var relationships = pageRelDoc.createElement("Relationships");
  584. relationships.setAttribute("xmlns", that.RELS_XMLNS);
  585. var imgs = vsdxCanvas.images;
  586. //create rels of image files
  587. if (imgs.length > 0)
  588. {
  589. for (var i = 0; i < imgs.length; i++)
  590. {
  591. var relationship = pageRelDoc.createElement("Relationship");
  592. relationship.setAttribute("Type", that.XMLNS_R + "/image");
  593. relationship.setAttribute("Id", "rId" + (i+1));
  594. relationship.setAttribute("Target", "../media/" + imgs[i]);
  595. relationships.appendChild(relationship);
  596. }
  597. }
  598. pageRelDoc.appendChild(relationships);
  599. writeXmlDoc2Zip(zip, fId, pageRelDoc);
  600. };
  601. /**
  602. *
  603. * Convert current Editor UI pages into a vdsx file
  604. * @return true if successful, false otherwise
  605. */
  606. this.exportCurrentDiagrams = function ()
  607. {
  608. try
  609. {
  610. var zip = new JSZip();
  611. vsdxCanvas.init(zip);
  612. pages = {};
  613. modelsAttr = {};
  614. var pagesCount = editorUi.pages != null? editorUi.pages.length : 1;
  615. if (editorUi.pages != null)
  616. {
  617. var currentPage = editorUi.currentPage;
  618. for (var i=0; i < editorUi.pages.length; i++)
  619. {
  620. var page = editorUi.pages[i];
  621. editorUi.selectPage(page);
  622. var diagramName = page.getName();
  623. var graph = editorUi.editor.graph;
  624. var modelAttrib = getGraphAttributes(graph);
  625. pages[diagramName] = convertMxModel2Page(graph, modelAttrib);
  626. addImagesRels(zip, i+1);
  627. modelsAttr[diagramName] = modelAttrib;
  628. }
  629. editorUi.selectPage(currentPage);
  630. }
  631. else
  632. {
  633. var graph = editorUi.editor.graph;
  634. var modelAttrib = getGraphAttributes(graph);
  635. var diagramName = "Page1";
  636. pages[diagramName] = convertMxModel2Page(graph, modelAttrib);
  637. addImagesRels(zip, 1);
  638. modelsAttr[diagramName] = modelAttrib;
  639. }
  640. createVsdxSkeleton(zip, pagesCount, function() {
  641. addPagesXML(zip, pages, modelsAttr);
  642. //wait until all media files are loaded
  643. var createZipFile = function()
  644. {
  645. if (vsdxCanvas.filesLoading > 0)
  646. {
  647. setTimeout(createZipFile, vsdxCanvas.filesLoading * 200);
  648. }
  649. else
  650. {
  651. zip.generateAsync({type:"base64"}).then(
  652. function(content)
  653. {
  654. var basename = editorUi.getBaseFilename();
  655. editorUi.saveData(basename+".vsdx", 'vsdx', content, 'application/vnd.visio2013', true);
  656. }
  657. );
  658. }
  659. };
  660. createZipFile();
  661. });
  662. return true;
  663. }
  664. catch(e)
  665. {
  666. console.log(e);
  667. return false;
  668. }
  669. };
  670. }
  671. VsdxExport.prototype.CONVERSION_FACTOR = 40 * 2.54; //screenCoordinatesPerCm (40) x CENTIMETERS_PER_INCHES (2.54)
  672. VsdxExport.prototype.PAGES_TYPE = "http://schemas.microsoft.com/visio/2010/relationships/page";
  673. VsdxExport.prototype.RELS_XMLNS = "http://schemas.openxmlformats.org/package/2006/relationships";
  674. VsdxExport.prototype.XML_SPACE = "preserve";
  675. VsdxExport.prototype.XMLNS_R = "http://schemas.openxmlformats.org/officeDocument/2006/relationships";
  676. VsdxExport.prototype.XMLNS = "http://schemas.microsoft.com/office/visio/2012/main";
  677. VsdxExport.prototype.VISIO_PAGES = "visio/pages/";
  678. VsdxExport.prototype.PREFEX = "com/mxgraph/io/vsdx/resources/export/";
  679. VsdxExport.prototype.VSDX_ENC = "ISO-8859-1";
  680. VsdxExport.prototype.PART_NAME = "PartName";
  681. VsdxExport.prototype.CONTENT_TYPES_XML = "[Content_Types].xml";
  682. VsdxExport.prototype.VISIO_PAGES_RELS = "visio/pages/_rels/";
  683. VsdxExport.prototype.ARROWS_MAP = {
  684. "none|1": 0, "none|0": 0, "open|1": 1, "open|0": 1, "block|1": 4, "block|0": 14, "classic|1": 5, "classic|0": 17,
  685. "oval|1": 10, "oval|0": 20, "diamond|1": 11, "diamond|0": 22, "blockThin|1": 2, "blockThin|0": 15, "dash|1": 23, "dash|0": 23,
  686. "ERone|1": 24, "ERone|0": 24, "ERmandOne|1": 25, "ERmandOne|0": 25, "ERmany|1": 27, "ERmany|0": 27, "ERoneToMany|1": 28, "ERoneToMany|0": 28,
  687. "ERzeroToMany|1": 29, "ERzeroToMany|0": 29, "ERzeroToOne|1": 30, "ERzeroToOne|0": 30, "openAsync|1": 9, "openAsync|0": 9
  688. };