1// $Id = LocalFile.js,v 1.12 2010-01-02 09 =45 =14 gaudenz Exp $ 2// Copyright (c) 2006-2014, JGraph Ltd 3/** 4 * Constructs a new point for the optional x and y coordinates. If no 5 * coordinates are given, then the default values for <x> and <y> are used. 6 * @constructor 7 * @class Implements a basic 2D point. Known subclassers = {@link mxRectangle}. 8 * @param {number} x X-coordinate of the point. 9 * @param {number} y Y-coordinate of the point. 10 */ 11LocalFile = function(ui, data, title, temp, fileHandle, desc) 12{ 13 DrawioFile.call(this, ui, data); 14 15 this.title = title; 16 this.mode = (temp) ? null : App.MODE_DEVICE; 17 this.fileHandle = fileHandle; 18 this.desc = desc; 19}; 20 21//Extends mxEventSource 22mxUtils.extend(LocalFile, DrawioFile); 23 24/** 25 * Translates this point by the given vector. 26 * 27 * @param {number} dx X-coordinate of the translation. 28 * @param {number} dy Y-coordinate of the translation. 29 */ 30LocalFile.prototype.isAutosave = function() 31{ 32 return this.fileHandle != null && !this.invalidFileHandle && DrawioFile.prototype.isAutosave.apply(this, arguments); 33}; 34 35/** 36 * Specifies if the autosave checkbox should be shown in the document 37 * properties dialog. Default is false. 38 */ 39LocalFile.prototype.isAutosaveOptional = function() 40{ 41 return this.fileHandle != null; 42}; 43 44/** 45 * Translates this point by the given vector. 46 * 47 * @param {number} dx X-coordinate of the translation. 48 * @param {number} dy Y-coordinate of the translation. 49 */ 50LocalFile.prototype.getMode = function() 51{ 52 return this.mode; 53}; 54 55/** 56 * Translates this point by the given vector. 57 * 58 * @param {number} dx X-coordinate of the translation. 59 * @param {number} dy Y-coordinate of the translation. 60 */ 61LocalFile.prototype.getTitle = function() 62{ 63 return this.title; 64}; 65 66/** 67 * Translates this point by the given vector. 68 * 69 * @param {number} dx X-coordinate of the translation. 70 * @param {number} dy Y-coordinate of the translation. 71 */ 72LocalFile.prototype.isRenamable = function() 73{ 74 return true; 75}; 76 77/** 78 * Translates this point by the given vector. 79 * 80 * @param {number} dx X-coordinate of the translation. 81 * @param {number} dy Y-coordinate of the translation. 82 */ 83LocalFile.prototype.save = function(revision, success, error) 84{ 85 this.saveAs(this.title, success, error); 86}; 87 88/** 89 * Translates this point by the given vector. 90 * 91 * @param {number} dx X-coordinate of the translation. 92 * @param {number} dy Y-coordinate of the translation. 93 */ 94LocalFile.prototype.saveAs = function(title, success, error) 95{ 96 this.saveFile(title, false, success, error); 97}; 98 99/** 100 * Translates this point by the given vector. 101 * 102 * @param {number} dx X-coordinate of the translation. 103 * @param {number} dy Y-coordinate of the translation. 104 */ 105LocalFile.prototype.saveAs = function(title, success, error) 106{ 107 this.saveFile(title, false, success, error); 108}; 109 110/** 111 * Adds all listeners. 112 */ 113LocalFile.prototype.getDescriptor = function() 114{ 115 return this.desc; 116}; 117 118/** 119* Updates the descriptor of this file with the one from the given file. 120*/ 121LocalFile.prototype.setDescriptor = function(desc) 122{ 123 this.desc = desc; 124}; 125 126/** 127 * Translates this point by the given vector. 128 * 129 * @param {number} dx X-coordinate of the translation. 130 * @param {number} dy Y-coordinate of the translation. 131 */ 132LocalFile.prototype.getLatestVersion = function(success, error) 133{ 134 if (this.fileHandle == null) 135 { 136 success(null); 137 } 138 else 139 { 140 this.ui.loadFileSystemEntry(this.fileHandle, success, error); 141 } 142}; 143 144/** 145 * Translates this point by the given vector. 146 * 147 * @param {number} dx X-coordinate of the translation. 148 * @param {number} dy Y-coordinate of the translation. 149 */ 150LocalFile.prototype.saveFile = function(title, revision, success, error, useCurrentData) 151{ 152 if (title != this.title) 153 { 154 this.fileHandle = null; 155 this.desc = null; 156 } 157 158 this.title = title; 159 160 // Updates data after changing file name 161 if (!useCurrentData) 162 { 163 this.updateFileData(); 164 } 165 166 var binary = this.ui.useCanvasForExport && /(\.png)$/i.test(this.getTitle()); 167 this.setShadowModified(false); 168 var savedData = this.getData(); 169 170 var done = mxUtils.bind(this, function() 171 { 172 this.setModified(this.getShadowModified()); 173 this.contentChanged(); 174 175 if (success != null) 176 { 177 success(); 178 } 179 }); 180 181 var doSave = mxUtils.bind(this, function(data) 182 { 183 if (this.fileHandle != null) 184 { 185 // Sets shadow modified state during save 186 if (!this.savingFile) 187 { 188 this.savingFileTime = new Date(); 189 this.savingFile = true; 190 191 var errorWrapper = mxUtils.bind(this, function(e) 192 { 193 this.savingFile = false; 194 195 if (error != null) 196 { 197 // Wraps error object to offer save status option 198 error({error: e}); 199 } 200 }); 201 202 // Saves a copy as a draft while saving 203 this.saveDraft(); 204 205 this.fileHandle.createWritable().then(mxUtils.bind(this, function(writable) 206 { 207 this.fileHandle.getFile().then(mxUtils.bind(this, function(newDesc) 208 { 209 this.invalidFileHandle = null; 210 211 if (this.desc.lastModified == newDesc.lastModified) 212 { 213 writable.write((binary) ? this.ui.base64ToBlob(data, 'image/png') : data).then(mxUtils.bind(this, function() 214 { 215 writable.close().then(mxUtils.bind(this, function() 216 { 217 this.fileHandle.getFile().then(mxUtils.bind(this, function(desc) 218 { 219 try 220 { 221 var lastDesc = this.desc; 222 this.savingFile = false; 223 this.desc = desc; 224 this.fileSaved(savedData, lastDesc, done, errorWrapper); 225 226 // Deletes draft after saving 227 this.removeDraft(); 228 } 229 catch (e) 230 { 231 errorWrapper(e); 232 } 233 }), errorWrapper); 234 }), errorWrapper); 235 }), errorWrapper); 236 } 237 else 238 { 239 this.inConflictState = true; 240 errorWrapper(); 241 } 242 }), mxUtils.bind(this, function(e) 243 { 244 this.invalidFileHandle = true; 245 errorWrapper(e); 246 })); 247 }), errorWrapper); 248 } 249 } 250 else 251 { 252 if (this.ui.isOfflineApp() || this.ui.isLocalFileSave()) 253 { 254 this.ui.doSaveLocalFile(data, title, (binary) ? 255 'image/png' : 'text/xml', binary); 256 } 257 else 258 { 259 if (data.length < MAX_REQUEST_SIZE) 260 { 261 var dot = title.lastIndexOf('.'); 262 var format = (dot > 0) ? title.substring(dot + 1) : 'xml'; 263 264 // Do not update modified flag 265 new mxXmlRequest(SAVE_URL, 'format=' + format + 266 '&xml=' + encodeURIComponent(data) + 267 '&filename=' + encodeURIComponent(title) + 268 ((binary) ? '&binary=1' : '')). 269 simulate(document, '_blank'); 270 } 271 else 272 { 273 this.ui.handleError({message: mxResources.get('drawingTooLarge')}, mxResources.get('error'), mxUtils.bind(this, function() 274 { 275 mxUtils.popup(data); 276 })); 277 } 278 } 279 280 done(); 281 } 282 }); 283 284 if (binary) 285 { 286 var p = this.ui.getPngFileProperties(this.ui.fileNode); 287 288 this.ui.getEmbeddedPng(mxUtils.bind(this, function(imageData) 289 { 290 doSave(imageData); 291 }), error, (this.ui.getCurrentFile() != this) ? 292 savedData : null, p.scale, p.border); 293 } 294 else 295 { 296 doSave(savedData); 297 } 298}; 299 300/** 301 * Translates this point by the given vector. 302 * 303 * @param {number} dx X-coordinate of the translation. 304 * @param {number} dy Y-coordinate of the translation. 305 */ 306LocalFile.prototype.rename = function(title, success, error) 307{ 308 this.title = title; 309 this.descriptorChanged(); 310 311 if (success != null) 312 { 313 success(); 314 } 315}; 316 317/** 318 * Returns the location as a new object. 319 * @type mx.Point 320 */ 321LocalFile.prototype.open = function() 322{ 323 this.ui.setFileData(this.getData()); 324 this.installListeners(); 325}; 326