12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184 |
- window.OPEN_URL = 'https://www.draw.io/open';
- window.TEMPLATE_PATH = 'templates';
- window.DRAW_MATH_URL = 'mathjax/src/main/webapp/current';
- FeedbackDialog.feedbackUrl = 'https://log.draw.io/email';
- (function()
- {
- // Overrides default mode
- App.mode = App.MODE_DEVICE;
- // Disables new window option in edit diagram dialog
- EditDiagramDialog.showNewWindowOption = false;
- // Redirects printing to iframe to avoid document.write
- var printDialogCreatePrintPreview = PrintDialog.createPrintPreview;
-
- PrintDialog.createPrintPreview = function()
- {
- var iframe = document.createElement('iframe');
- document.body.appendChild(iframe);
- var result = printDialogCreatePrintPreview.apply(this, arguments);
- result.wnd = iframe.contentWindow;
- result.iframe = iframe;
-
- // Workaround for lost gradients in print output
- result.previousGetBaseUrl = mxSvgCanvas2D.prototype.getBaseUrl;
-
- mxSvgCanvas2D.prototype.getBaseUrl = function()
- {
- return '';
- };
-
- return result;
- };
-
- var oldWindowOpen = window.open;
- window.open = function(url)
- {
- if (url != null && url.startsWith('http'))
- {
- const {shell} = require('electron');
- shell.openExternal(url);
- }
- else
- {
- return oldWindowOpen(url);
- }
- }
- mxPrintPreview.prototype.addPageBreak = function(doc)
- {
- // Do nothing
- };
- mxPrintPreview.prototype.closeDocument = function()
- {
- var doc = this.wnd.document;
-
- // Removes all event handlers in the print output
- mxEvent.release(doc.body);
- };
-
- PrintDialog.printPreview = function(preview)
- {
- if (preview.iframe != null)
- {
- preview.iframe.contentWindow.print();
- preview.iframe.parentNode.removeChild(preview.iframe);
-
- mxSvgCanvas2D.prototype.getBaseUrl = preview.previousGetBaseUrl;
- preview.iframe = null;
- }
- };
-
- PrintDialog.previewEnabled = false;
-
- var menusInit = Menus.prototype.init;
- Menus.prototype.init = function()
- {
- menusInit.apply(this, arguments);
- var editorUi = this.editorUi;
- editorUi.actions.put('useOffline', new Action(mxResources.get('useOffline') + '...', function()
- {
- editorUi.openLink('https://www.draw.io/')
- }));
-
- // Replaces file menu to replace openFrom menu with open and rename downloadAs to export
- this.put('file', new Menu(mxUtils.bind(this, function(menu, parent)
- {
- this.addMenuItems(menu, ['new', 'open', '-', 'synchronize', '-', 'save', 'saveAs', '-', 'import'], parent);
- this.addSubmenu('exportAs', menu, parent);
- menu.addSeparator(parent);
- this.addSubmenu('embed', menu, parent);
- menu.addSeparator(parent);
- this.addMenuItems(menu, ['newLibrary', 'openLibrary', '-', 'pageSetup',
- 'print', '-', 'close'], parent);
- // LATER: Find API for application.quit
- })));
- };
-
- var graphCreateLinkForHint = Graph.prototype.createLinkForHint;
-
- Graph.prototype.createLinkForHint = function(href, label)
- {
- var a = graphCreateLinkForHint.call(this, href, label);
-
- if (href != null && !this.isCustomLink(href))
- {
- // KNOWN: Event with gesture handler mouseUp the middle click opens a framed window
- mxEvent.addListener(a, 'click', mxUtils.bind(this, function(evt)
- {
- this.openLink(a.getAttribute('href'), a.getAttribute('target'));
- mxEvent.consume(evt);
- }));
- }
-
- return a;
- };
-
- Graph.prototype.openLink = function(url, target)
- {
- require('electron').shell.openExternal(url);
- };
-
- // Initializes the user interface
- var editorUiInit = EditorUi.prototype.init;
- EditorUi.prototype.init = function()
- {
- editorUiInit.apply(this, arguments);
- var editorUi = this;
- var graph = this.editor.graph;
-
- global.__emt_isModified =
- e => {
- if (this.getCurrentFile())
- {
- return this.getCurrentFile().isModified()
- }
- return false
- }
-
- // global.__emt_getCurrentFile = e => {
- // return this.getCurrentFile()
- // }
- // Adds support for libraries
- this.actions.addAction('newLibrary...', mxUtils.bind(this, function()
- {
- editorUi.showLibraryDialog(null, null, null, null, App.MODE_DEVICE);
- }));
-
- this.actions.addAction('openLibrary...', mxUtils.bind(this, function()
- {
- editorUi.pickLibrary(App.MODE_DEVICE);
- }));
- // Replaces import action
- this.actions.addAction('import...', mxUtils.bind(this, function()
- {
- if (editorUi.getCurrentFile() != null)
- {
- const electron = require('electron');
- var remote = electron.remote;
- var dialog = remote.dialog;
- var paths = dialog.showOpenDialog({properties: ['openFile']});
-
- if (paths !== undefined && paths[0] != null)
- {
- var path = paths[0];
- var asImage = /\.png$/i.test(path) || /\.gif$/i.test(path) || /\.jpe?g$/i.test(path);
- var encoding = (asImage || /\.vsdx$/i.test(path) || /\.vssx$/i.test(path)) ?
- 'base64' : 'utf-8';
- if (editorUi.spinner.spin(document.body, mxResources.get('loading')))
- {
- var fs = require('fs');
- fs.readFile(path, encoding, mxUtils.bind(this, function (e, data)
- {
- if (e)
- {
- editorUi.spinner.stop();
- editorUi.handleError(e);
- }
- else
- {
- try
- {
- if (editorUi.isLucidChartData(data))
- {
- editorUi.convertLucidChart(data, function(xml)
- {
- editorUi.spinner.stop();
- graph.setSelectionCells(editorUi.importXml(xml));
- }, function(e)
- {
- editorUi.spinner.stop();
- editorUi.handleError(e);
- });
- }
- else if (/(\.vsdx)($|\?)/i.test(path))
- {
- editorUi.importVisio(editorUi.base64ToBlob(data, 'application/octet-stream'), function(xml)
- {
- editorUi.spinner.stop();
- graph.setSelectionCells(editorUi.importXml(xml));
- });
- }
- else if (!editorUi.isOffline() && new XMLHttpRequest().upload && editorUi.isRemoteFileFormat(data, path))
- {
- // Asynchronous parsing via server
- editorUi.parseFile(new Blob([data], {type : 'application/octet-stream'}), mxUtils.bind(this, function(xhr)
- {
- if (xhr.readyState == 4)
- {
- editorUi.spinner.stop();
-
- if (xhr.status >= 200 && xhr.status <= 299)
- {
- graph.setSelectionCells(editorUi.importXml(xhr.responseText));
- }
- }
- }), path);
- }
- else
- {
- if (/\.png$/i.test(path))
- {
- var tmp = editorUi.extractGraphModelFromPng(data);
-
- if (tmp != null)
- {
- asImage = false;
- data = tmp;
- }
- }
- else if (/\.svg$/i.test(path))
- {
- // LATER: Use importXml without throwing exception if no data
- // Checks if SVG contains content attribute
- var root = mxUtils.parseXml(data);
- var svgs = root.getElementsByTagName('svg');
-
- if (svgs.length > 0)
- {
- var svgRoot = svgs[0];
- var cont = svgRoot.getAttribute('content');
-
- if (cont != null && cont.charAt(0) != '<' && cont.charAt(0) != '%')
- {
- cont = unescape((window.atob) ? atob(cont) : Base64.decode(cont, true));
- }
-
- if (cont != null && cont.charAt(0) == '%')
- {
- cont = decodeURIComponent(cont);
- }
-
- if (cont != null && (cont.substring(0, 8) === '<mxfile ' ||
- cont.substring(0, 14) === '<mxGraphModel '))
- {
- asImage = false;
- data = cont;
- }
- else
- {
- asImage = true;
- data = btoa(data);
- }
- }
- }
-
- if (asImage)
- {
- var img = new Image();
- img.onload = function()
- {
- editorUi.resizeImage(img, img.src, function(data2, w, h)
- {
- editorUi.spinner.stop();
- var pt = graph.getInsertPoint();
- graph.setSelectionCell(graph.insertVertex(null, null, '', pt.x, pt.y, w, h,
- 'shape=image;aspect=fixed;image=' + editorUi.convertDataUri(data2) + ';'));
- }, true);
- };
-
- img.onerror = function(e)
- {
- editorUi.spinner.stop();
- editorUi.handleError();
- };
-
- var format = path.substring(path.lastIndexOf('.') + 1);
-
- if (format == 'svg')
- {
- format = 'svg+xml';
- }
-
- img.src = 'data:image/' + format + ';base64,' + data;
- }
- else
- {
- editorUi.spinner.stop();
-
- if (data != null)
- {
- graph.setSelectionCells(editorUi.importXml(data));
- }
- }
- }
- }
- catch(e)
- {
- editorUi.spinner.stop();
- editorUi.handleError(e);
- }
- }
- }));
- }
- }
- }
- }));
-
- // Replaces new action
- var oldNew = this.actions.get('new').funct;
-
- this.actions.addAction('new...', mxUtils.bind(this, function()
- {
- if (this.getCurrentFile() == null)
- {
- oldNew();
- }
- else
- {
- const ipc = require('electron').ipcRenderer
- ipc.sendSync('winman', {action: 'newfile', opt: {width: 1600}})
- }
- }), null, null, Editor.ctrlKey + '+N');
-
- this.actions.get('open').shortcut = Editor.ctrlKey + '+O';
-
- // Adds shortcut keys for file operations
- editorUi.keyHandler.bindAction(78, true, 'new'); // Ctrl+N
- editorUi.keyHandler.bindAction(79, true, 'open'); // Ctrl+O
- }
-
- var appLoad = App.prototype.load;
- App.prototype.load = function()
- {
- appLoad.apply(this, arguments);
- const {ipcRenderer} = require('electron');
-
- ipcRenderer.on('args-obj', (event, argsObj) =>
- {
- this.loadArgs(argsObj)
- })
- }
-
- App.prototype.loadArgs = function(argsObj)
- {
- var paths = argsObj.args;
-
- // If a file is passed
- if (paths !== undefined && paths[0] != null)
- {
- var path = paths[0];
-
- var success = mxUtils.bind(this, function(fileEntry, data, stat)
- {
- var file = new LocalFile(this, data, '');
- file.fileObject = fileEntry;
- file.stat = stat;
- this.fileLoaded(file);
- });
-
- var error = mxUtils.bind(this, function(e)
- {
- if (e.code === 'ENOENT')
- {
- var title = path.replace(/^.*[\\\/]/, '');
- var data = this.emptyDiagramXml;
- var file = new LocalFile(this, data, title, null);
-
- file.fileObject = new Object();
- file.fileObject.path = path;
- file.fileObject.name = title;
- file.fileObject.type = 'utf-8';
- this.fileCreated(file, null, null, null);
- this.saveFile();
- }
- else
- {
- this.handleError(e);
- }
-
- });
-
- // Tries to open the file
- this.readGraphFile(success, error, path);
- }
- // If no file is passed, but there is the "create-if-not-exists" flag
- else if (argsObj.create != null)
- {
- var title = 'Untitled document';
- var data = this.emptyDiagramXml;
- var file = new LocalFile(this, data, title, null);
- this.fileCreated(file, null, null, null);
- }
- }
- // Uses local picker
- App.prototype.pickFile = function()
- {
- var doPickFile = mxUtils.bind(this, function()
- {
- this.chooseFileEntry(mxUtils.bind(this, function(fileEntry, data, stat)
- {
- var file = new LocalFile(this, data, '');
- file.fileObject = fileEntry;
- file.stat = stat;
- this.fileLoaded(file);
- }));
- });
- var file = this.getCurrentFile();
-
- if (file != null && file.isModified())
- {
- this.confirm(mxResources.get('allChangesLost'), null, doPickFile,
- mxResources.get('cancel'), mxResources.get('discardChanges'));
- }
- else
- {
- doPickFile();
- }
- };
-
- /**
- * Selects a library to load from a picker
- *
- * @param mode the device mode, ignored in this case
- */
- App.prototype.pickLibrary = function(mode)
- {
- this.chooseFileEntry(mxUtils.bind(this, function(fileEntry, data, stat)
- {
- try
- {
- var library = new LocalLibrary(this, data, fileEntry.name);
- library.fileObject = fileEntry;
- this.loadLibrary(library);
- }
- catch (e)
- {
- this.handleError(e, mxResources.get('errorLoadingFile'));
- }
- }));
- };
-
- // Uses local picker
- App.prototype.chooseFileEntry = function(fn)
- {
- const electron = require('electron');
- var remote = electron.remote;
- var dialog = remote.dialog;
- var paths = dialog.showOpenDialog({properties: ['openFile']});
-
- if (paths !== undefined && paths[0] != null)
- {
- this.readGraphFile(fn, mxUtils.bind(this, function(err)
- {
- this.handleError(err);
- }), paths[0]);
- }
- else
- {
- this.spinner.stop();
- }
- };
- App.prototype.readGraphFile = function(fn, fnErr, path)
- {
- var fs = require('fs');
- var index = path.lastIndexOf('.png');
- var isPng = index > -1 && index == path.length - 4;
- var encoding = isPng ? 'base64' : 'utf-8'
- fs.readFile(path, encoding, mxUtils.bind(this, function (e, data)
- {
- if (e)
- {
- fnErr(e);
- }
- else
- {
- if (isPng)
- {
- // Detecting png by extension. Would need https://github.com/mscdex/mmmagic
- // to do it by inspection
- data = this.extractGraphModelFromPng('data:image/png;base64,' + data);
- }
- var fileEntry = new Object();
- fileEntry.path = path;
- fileEntry.name = path.replace(/^.*[\\\/]/, '');
- fileEntry.type = encoding;
- fs.stat(path, function(err, stat)
- {
- if (err)
- {
- fnErr(err);
- }
- else
- {
- fn(fileEntry, data, stat);
- }
- });
- }
- }));
- };
- // Disables temp files in Electron
- var LocalFileCtor = LocalFile;
-
- LocalFile = function(ui, data, title, temp)
- {
- LocalFileCtor.call(this, ui, data, title, false);
- };
- mxUtils.extend(LocalFile, LocalFileCtor);
- LocalFile.prototype.getLatestVersion = function(success, error)
- {
- if (this.fileObject == null)
- {
- if (error != null)
- {
- error({message: mxResources.get('fileNotFound')});
- }
- }
- else
- {
- this.ui.readGraphFile(mxUtils.bind(this, function(fileEntry, data, stat)
- {
- var file = new LocalFile(this, data, '');
- file.stat = stat;
- success(file);
- }), error, this.fileObject.path);
- }
- };
-
- // Call save as for copy
- LocalFile.prototype.copyFile = function(success, error)
- {
- this.saveAs(this.ui.getCopyFilename(this), success, error);
- };
-
- /**
- * Adds all listeners.
- */
- LocalFile.prototype.getDescriptor = function()
- {
- return this.stat;
- };
- /**
- * Updates the descriptor of this file with the one from the given file.
- */
- LocalFile.prototype.setDescriptor = function(stat)
- {
- this.stat = stat;
- };
-
- LocalFile.prototype.reloadFile = function(success)
- {
- if (this.fileObject == null)
- {
- this.ui.handleError({message: mxResources.get('fileNotFound')});
- }
- else
- {
- this.ui.spinner.stop();
-
- var fn = mxUtils.bind(this, function()
- {
- this.setModified(false);
- var page = this.ui.currentPage;
- var viewState = this.ui.editor.graph.getViewState();
- var selection = this.ui.editor.graph.getSelectionCells();
-
- if (this.ui.spinner.spin(document.body, mxResources.get('loading')))
- {
- this.ui.readGraphFile(mxUtils.bind(this, function(fileEntry, data, stat)
- {
- this.ui.spinner.stop();
-
- var file = new LocalFile(this.ui, data, '');
- file.fileObject = fileEntry;
- file.stat = stat;
-
- this.ui.fileLoaded(file);
- this.ui.restoreViewState(page, viewState, selection);
-
- if (this.backupPatch != null)
- {
- this.patch([this.backupPatch]);
- }
-
- if (success != null)
- {
- success();
- }
- }), mxUtils.bind(this, function(err)
- {
- this.handleFileError(err);
- }), this.fileObject.path);
- }
- });
-
- if (this.isModified() && this.backupPatch == null)
- {
- this.ui.confirm(mxResources.get('allChangesLost'), mxUtils.bind(this, function()
- {
- this.handleFileSuccess(DrawioFile.SYNC == 'manual');
- }), fn, mxResources.get('cancel'), mxResources.get('discardChanges'));
- }
- else
- {
- fn();
- }
- }
- };
- LocalFile.prototype.isAutosave = function()
- {
- return this.fileObject != null && DrawioFile.prototype.isAutosave.apply(this, arguments);
- };
-
- LocalFile.prototype.isAutosaveOptional = function()
- {
- return this.fileObject != null;
- };
-
- LocalLibrary.prototype.isAutosave = function()
- {
- return this.fileObject != null;
- };
-
- LocalFile.prototype.getTitle = function()
- {
- return (this.fileObject != null) ? this.fileObject.name : this.title;
- };
- LocalFile.prototype.isRenamable = function()
- {
- return false;
- };
-
- // Restores default implementation of open with autosave
- LocalFile.prototype.open = DrawioFile.prototype.open;
- LocalFile.prototype.save = function(revision, success, error, unloading, overwrite)
- {
- DrawioFile.prototype.save.apply(this, arguments);
-
- this.saveFile(revision, success, error, unloading, overwrite);
- };
- LocalLibrary.prototype.save = function(revision, success, error)
- {
- LocalFile.prototype.saveFile.apply(this, arguments);
- };
-
- LocalFile.prototype.isConflict = function(stat)
- {
- return stat != null && this.stat != null && stat.mtimeMs != this.stat.mtimeMs;
- };
-
- LocalFile.prototype.saveFile = function(revision, success, error, unloading, overwrite)
- {
- if (!this.savingFile)
- {
- var fn = mxUtils.bind(this, function()
- {
- var doSave = mxUtils.bind(this, function(data, enc)
- {
- var savedData = this.data;
-
- // Makes sure no changes get lost while the file is saved
- var prevModified = this.isModified;
- var modified = this.isModified();
- this.setModified(false);
- this.savingFile = true;
- var fs = require('fs');
-
- var errorWrapper = mxUtils.bind(this, function()
- {
- this.savingFile = false;
- this.isModified = prevModified;
- this.setModified(modified || this.isModified());
-
- if (error != null)
- {
- error();
- }
- });
-
- var writeFile = mxUtils.bind(this, function()
- {
- if (data == null || data.length == 0)
- {
- this.ui.handleError({message: mxResources.get('errorSavingFile')});
- errorWrapper();
- }
- else
- {
- fs.writeFile(this.fileObject.path, data, enc || this.fileObject.encoding,
- mxUtils.bind(this, function (e)
- {
- if (e)
- {
- errorWrapper();
- }
- else
- {
- fs.stat(this.fileObject.path, mxUtils.bind(this, function(e2, stat2)
- {
- if (e2)
- {
- errorWrapper();
- }
- else
- {
- this.savingFile = false;
- this.isModified = prevModified;
- var lastDesc = this.stat;
- this.stat = stat2;
-
- this.fileSaved(savedData, lastDesc, mxUtils.bind(this, function()
- {
- this.contentChanged();
-
- if (success != null)
- {
- success();
- }
- }), error);
- }
- }));
- }
- }));
- }
- });
-
- if (overwrite)
- {
- writeFile();
- }
- else
- {
- fs.stat(this.fileObject.path, mxUtils.bind(this, function(err, stat)
- {
- if (this.isConflict(stat))
- {
- this.inConflictState = true;
- errorWrapper();
- }
- else if (err != null && err.code !== 'ENOENT')
- {
- errorWrapper();
- }
- else
- {
- writeFile();
- }
- }));
- }
- });
-
- if (!/(\.png)$/i.test(this.fileObject.name))
- {
- doSave(this.getData());
- }
- else
- {
- this.ui.getEmbeddedPng(function(data)
- {
- doSave(atob(data), 'binary');
- }, error);
- }
- });
-
- if (this.fileObject == null)
- {
- const electron = require('electron');
- var remote = electron.remote;
- var dialog = remote.dialog;
-
- var path = dialog.showSaveDialog({defaultPath: this.title});
-
- if (path != null)
- {
- this.fileObject = new Object();
- this.fileObject.path = path;
- this.fileObject.name = path.replace(/^.*[\\\/]/, '');
- this.fileObject.type = 'utf-8';
- fn();
- }
- else
- {
- this.ui.spinner.stop();
- }
- }
- else
- {
- fn();
- }
- }
- };
- LocalFile.prototype.saveAs = function(title, success, error)
- {
- const electron = require('electron');
- var remote = electron.remote;
- var dialog = remote.dialog;
- var filename = this.title;
-
- // Adds default extension
- if (filename.length > 0 && (!/(\.xml)$/i.test(filename) && !/(\.html)$/i.test(filename) &&
- !/(\.svg)$/i.test(filename) && !/(\.png)$/i.test(filename) && !/(\.drawio)$/i.test(filename)))
- {
- filename += '.drawio';
- }
-
- var path = dialog.showSaveDialog({defaultPath: filename});
-
- if (path != null)
- {
- this.fileObject = new Object();
- this.fileObject.path = path;
- this.fileObject.name = path.replace(/^.*[\\\/]/, '');
- this.fileObject.type = 'utf-8';
-
- this.save(false, success, error, null, true);
- }
- };
-
- App.prototype.saveFile = function(forceDialog)
- {
- var file = this.getCurrentFile();
-
- if (file != null)
- {
- if (!forceDialog && file.getTitle() != null)
- {
- file.save(true, mxUtils.bind(this, function()
- {
- file.handleFileSuccess(true);
- }), mxUtils.bind(this, function(err)
- {
- file.handleFileError(err, true);
- }));
- }
- else
- {
- file.saveAs(null, mxUtils.bind(this, function()
- {
- file.handleFileSuccess(true);
- }), mxUtils.bind(this, function(err)
- {
- file.handleFileError(err, true);
- }));
- }
- }
- };
-
- /**
- * Translates this point by the given vector.
- *
- * @param {number} dx X-coordinate of the translation.
- * @param {number} dy Y-coordinate of the translation.
- */
- App.prototype.saveLibrary = function(name, images, file, mode, noSpin, noReload, fn)
- {
- mode = (mode != null) ? mode : this.mode;
- noSpin = (noSpin != null) ? noSpin : false;
- noReload = (noReload != null) ? noReload : false;
- var xml = this.createLibraryDataFromImages(images);
-
- var error = mxUtils.bind(this, function(resp)
- {
- this.spinner.stop();
-
- if (fn != null)
- {
- fn();
- }
-
- // Null means cancel by user and is ignored
- if (resp != null)
- {
- this.handleError(resp, mxResources.get('errorSavingFile'));
- }
- });
-
- // Handles special case for local libraries
- if (file == null)
- {
- file = new LocalLibrary(this, xml, name);
- }
-
- if (noSpin || this.spinner.spin(document.body, mxResources.get('saving')))
- {
- file.setData(xml);
-
- var doSave = mxUtils.bind(this, function()
- {
- file.save(true, mxUtils.bind(this, function(resp)
- {
- this.spinner.stop();
- this.hideDialog(true);
-
- if (!noReload)
- {
- this.libraryLoaded(file, images)
- }
-
- if (fn != null)
- {
- fn();
- }
- }), error);
- });
-
- if (name != file.getTitle())
- {
- var oldHash = file.getHash();
-
- file.rename(name, mxUtils.bind(this, function(resp)
- {
- // Change hash in stored settings
- if (file.constructor != LocalLibrary && oldHash != file.getHash())
- {
- mxSettings.removeCustomLibrary(oldHash);
- mxSettings.addCustomLibrary(file.getHash());
- }
-
- // Workaround for library files changing hash so
- // the old library cannot be removed from the
- // sidebar using the updated file in libraryLoaded
- this.removeLibrarySidebar(oldHash);
-
- doSave();
- }), error)
- }
- else
- {
- doSave();
- }
- }
- };
-
-
- /**
- * Updates action states depending on the selection.
- */
- var editorUiUpdateActionStates = EditorUi.prototype.updateActionStates;
- EditorUi.prototype.updateActionStates = function()
- {
- editorUiUpdateActionStates.apply(this, arguments);
- var file = this.getCurrentFile();
- var syncEnabled = file != null && file.fileObject != null;
- this.actions.get('synchronize').setEnabled(syncEnabled);
- };
-
- EditorUi.prototype.saveLocalFile = function(data, filename, mimeType, base64Encoded, format, allowBrowser)
- {
- this.saveData(filename, format, data, mimeType, base64Encoded);
- };
-
- EditorUi.prototype.saveRequest = function(filename, format, fn, data, base64Encoded, mimeType)
- {
- var xhr = fn(null, '1');
-
- if (xhr != null && this.spinner.spin(document.body, mxResources.get('saving')))
- {
- xhr.send(mxUtils.bind(this, function()
- {
- this.spinner.stop();
-
- if (xhr.getStatus() >= 200 && xhr.getStatus() <= 299)
- {
- this.saveData(filename, format, xhr.getText(), mimeType, true);
- }
- else
- {
- this.handleError({message: mxResources.get('errorSavingFile')});
- }
- }), function(resp)
- {
- this.spinner.stop();
- this.handleError(resp);
- });
- }
- };
- function mxElectronRequest(reqType, reqObj)
- {
- this.reqType = reqType;
- this.reqObj = reqObj;
- };
- //Extends mxXmlRequest
- mxUtils.extend(mxElectronRequest, mxXmlRequest);
-
- mxElectronRequest.prototype.send = function(callback, error)
- {
- const ipcRenderer = require('electron').ipcRenderer;
- ipcRenderer.send(this.reqType, this.reqObj);
-
- ipcRenderer.once(this.reqType + '-success', (event, data) =>
- {
- this.response = data;
- callback();
- })
- ipcRenderer.once(this.reqType + '-error', (event, err) =>
- {
- this.hasError = true;
- error(err);
- })
- };
-
- mxElectronRequest.prototype.getStatus = function()
- {
- return this.hasError? 500 : 200;
- }
-
- mxElectronRequest.prototype.getText = function()
- {
- return this.response;
- }
-
- if (mxIsElectron5)
- {
- //Direct export to pdf
- var origCreateDownloadRequest = EditorUi.prototype.createDownloadRequest;
-
- EditorUi.prototype.createDownloadRequest = function(filename, format, ignoreSelection, base64, transparent, currentPage)
- {
- if (format == 'pdf')
- {
- var bounds = this.editor.graph.getGraphBounds();
-
- // Exports only current page for images that does not contain file data, but for
- // the other formats with XML included or pdf with all pages, we need to send the complete data and use
- // the from/to URL parameters to specify the page to be exported.
- var data = this.getFileData(true, null, null, null, ignoreSelection, currentPage == false? false : format != 'xmlpng');
- var allPages = null;
-
- if (bounds.width * bounds.height > MAX_AREA || data.length > MAX_REQUEST_SIZE)
- {
- throw {message: mxResources.get('drawingTooLarge')};
- }
-
- if (currentPage == false)
- {
- allPages = '1';
- }
-
- var bg = this.editor.graph.background;
-
- return new mxElectronRequest('pdf-export', {
- xml: data,
- bg: (bg != null) ? bg : mxConstants.NONE,
- filename: (filename != null) ? filename : null,
- allPages: allPages
- });
- }
- else
- {
- return origCreateDownloadRequest.apply(this, arguments);
- }
- };
-
- //Export Dialog Pdf case
- var origExportFile = ExportDialog.exportFile;
-
- ExportDialog.exportFile = function(editorUi, name, format, bg, s, b)
- {
- var graph = editorUi.editor.graph;
-
- if (format == 'pdf')
- {
- var data = editorUi.getFileData(true, null, null, null, null, true);
- var bounds = graph.getGraphBounds();
- var w = Math.floor(bounds.width * s / graph.view.scale);
- var h = Math.floor(bounds.height * s / graph.view.scale);
-
- if (data.length <= MAX_REQUEST_SIZE && w * h < MAX_AREA)
- {
- editorUi.hideDialog();
- editorUi.saveRequest(name, format,
- function(newTitle, base64)
- {
- return new mxElectronRequest('pdf-export', {
- xml: data,
- bg: (bg != null) ? bg : mxConstants.NONE,
- filename: (newTitle != null) ? newTitle : null,
- w: w,
- h: h,
- border: b
- });
- });
- }
- else
- {
- mxUtils.alert(mxResources.get('drawingTooLarge'));
- }
- }
- else
- {
- return origExportFile.apply(this, arguments);
- }
- };
- }
-
- EditorUi.prototype.saveData = function(filename, format, data, mimeType, base64Encoded)
- {
- const electron = require('electron');
- var remote = electron.remote;
- var dialog = remote.dialog;
- var resume = (this.spinner != null && this.spinner.pause != null) ? this.spinner.pause() : function() {};
-
- // Spinner.stop is asynchronous so we must invoke save dialog asynchronously
- // to give the spinner some time to stop spinning
- window.setTimeout(mxUtils.bind(this, function()
- {
- var path = dialog.showSaveDialog({defaultPath: filename});
-
- if (path != null)
- {
- if (data == null || data.length == 0)
- {
- this.handleError({message: mxResources.get('errorSavingFile')});
- }
- else
- {
- var fs = require('fs');
- resume();
-
- var fileObject = new Object();
- fileObject.path = path;
- fileObject.name = path.replace(/^.*[\\\/]/, '');
- fileObject.type = (base64Encoded) ? 'base64' : 'utf-8';
-
- fs.writeFile(fileObject.path, data, fileObject.type, mxUtils.bind(this, function (e)
- {
- this.spinner.stop();
-
- if (e)
- {
- this.handleError({message: mxResources.get('errorSavingFile')});
- }
- }));
- }
- }
- }), 0);
- };
- EditorUi.prototype.addBeforeUnloadListener = function() {};
- })();
|