Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Called from the main frame when unloading. | 8 * Called from the main frame when unloading. |
| 9 * @param {boolean=} opt_exiting True if the app is exiting. | 9 * @param {boolean=} opt_exiting True if the app is exiting. |
| 10 */ | 10 */ |
| 11 function unload(opt_exiting) { Gallery.instance.onUnload(opt_exiting); } | 11 function unload(opt_exiting) { Gallery.instance.onUnload(opt_exiting); } |
| 12 | 12 |
| 13 /** | 13 /** |
| 14 * Overrided metadata worker's path. | 14 * Overrided metadata worker's path. |
| 15 * @type {string} | 15 * @type {string} |
| 16 * @const | 16 * @const |
| 17 */ | 17 */ |
| 18 ContentProvider.WORKER_SCRIPT = '/js/metadata_worker.js'; | 18 ContentProvider.WORKER_SCRIPT = '/js/metadata_worker.js'; |
| 19 | 19 |
| 20 /** | 20 /** |
| 21 * Data model for gallery. | 21 * Data model for gallery. |
| 22 * | 22 * |
| 23 * @param {MetadataCache} metadataCache Metadata cache. | 23 * @param {MetadataCache} metadataCache Metadata cache. |
| 24 * @constructor | 24 * @constructor |
| 25 * @extends {cr.ui.ArrayDataModel} | 25 * @extends {cr.ui.ArrayDataModel} |
| 26 */ | 26 */ |
| 27 function GalleryDataModel(metadataCache) { | 27 function GalleryDataModel(metadataCache) { |
| 28 cr.ui.ArrayDataModel.call(this, []); | 28 cr.ui.ArrayDataModel.call(this, []); |
| 29 | |
| 30 /** | |
| 31 * Metadata cache. | |
| 32 * @type {MetadataCache} | |
| 33 * @private | |
| 34 */ | |
| 29 this.metadataCache_ = metadataCache; | 35 this.metadataCache_ = metadataCache; |
| 36 | |
| 37 /** | |
| 38 * Directory where the image is saved if the image is located in a read-only | |
| 39 * volume. | |
| 40 * @type {DirectoryEntry} | |
| 41 */ | |
| 42 this.fallbackSaveDirectory = null; | |
| 30 } | 43 } |
| 31 | 44 |
| 32 /** | 45 /** |
| 33 * Maximum number of full size image cache. | 46 * Maximum number of full size image cache. |
| 34 * @type {number} | 47 * @type {number} |
| 35 * @const | 48 * @const |
| 36 * @private | 49 * @private |
| 37 */ | 50 */ |
| 38 GalleryDataModel.MAX_FULL_IMAGE_CACHE_ = 3; | 51 GalleryDataModel.MAX_FULL_IMAGE_CACHE_ = 3; |
| 39 | 52 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 65 var newMetadata = ContentProvider.ConvertContentMetadata( | 78 var newMetadata = ContentProvider.ConvertContentMetadata( |
| 66 metadataEncoder.getMetadata(), | 79 metadataEncoder.getMetadata(), |
| 67 MetadataCache.cloneMetadata(item.getMetadata())); | 80 MetadataCache.cloneMetadata(item.getMetadata())); |
| 68 if (newMetadata.filesystem) | 81 if (newMetadata.filesystem) |
| 69 newMetadata.filesystem.modificationTime = new Date(); | 82 newMetadata.filesystem.modificationTime = new Date(); |
| 70 if (newMetadata.drive) | 83 if (newMetadata.drive) |
| 71 newMetadata.drive.present = true; | 84 newMetadata.drive.present = true; |
| 72 | 85 |
| 73 return new Promise(function(fulfill, reject) { | 86 return new Promise(function(fulfill, reject) { |
| 74 item.saveToFile( | 87 item.saveToFile( |
| 75 null, | 88 this.fallbackSaveDirectory, |
| 76 overwrite, | 89 overwrite, |
| 77 canvas, | 90 canvas, |
| 78 metadataEncoder, | 91 metadataEncoder, |
| 79 function(success) { | 92 function(success) { |
| 80 if (!success) { | 93 if (!success) { |
| 81 reject('Failed to save the image.'); | 94 reject('Failed to save the image.'); |
| 82 return; | 95 return; |
| 83 } | 96 } |
| 84 | 97 |
| 85 // The item's entry is updated to the latest entry. Update metadata. | 98 // The item's entry is updated to the latest entry. Update metadata. |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 96 if (util.isSameEntry(oldEntry, item.getEntry())) { | 109 if (util.isSameEntry(oldEntry, item.getEntry())) { |
| 97 // Need an update of metdataCache. | 110 // Need an update of metdataCache. |
| 98 this.metadataCache_.set( | 111 this.metadataCache_.set( |
| 99 item.getEntry(), | 112 item.getEntry(), |
| 100 Gallery.METADATA_TYPE, | 113 Gallery.METADATA_TYPE, |
| 101 newMetadata); | 114 newMetadata); |
| 102 } else { | 115 } else { |
| 103 // New entry is added and the item now tracks it. | 116 // New entry is added and the item now tracks it. |
| 104 // Add another item for the old entry. | 117 // Add another item for the old entry. |
| 105 var anotherItem = new Gallery.Item( | 118 var anotherItem = new Gallery.Item( |
| 106 oldEntry, oldMetadata, this.metadataCache_, item.isOriginal()); | 119 oldEntry, |
| 120 oldMetadata, | |
| 121 this.metadataCache_, | |
| 122 item.isOriginal(), | |
| 123 item.isReadOnly()); | |
| 107 // The item must be added behind the existing item so that it does | 124 // The item must be added behind the existing item so that it does |
| 108 // not change the index of the existing item. | 125 // not change the index of the existing item. |
| 109 // TODO(hirono): Update the item index of the selection model | 126 // TODO(hirono): Update the item index of the selection model |
| 110 // correctly. | 127 // correctly. |
| 111 this.splice(this.indexOf(item) + 1, 0, anotherItem); | 128 this.splice(this.indexOf(item) + 1, 0, anotherItem); |
| 112 } | 129 } |
| 113 | 130 |
| 114 fulfill(); | 131 fulfill(); |
| 115 }.bind(this)); | 132 }.bind(this)); |
| 116 }.bind(this)); | 133 }.bind(this)); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 184 }; | 201 }; |
| 185 this.container_ = document.querySelector('.gallery'); | 202 this.container_ = document.querySelector('.gallery'); |
| 186 this.document_ = document; | 203 this.document_ = document; |
| 187 this.metadataCache_ = this.context_.metadataCache; | 204 this.metadataCache_ = this.context_.metadataCache; |
| 188 this.volumeManager_ = volumeManager; | 205 this.volumeManager_ = volumeManager; |
| 189 this.selectedEntry_ = null; | 206 this.selectedEntry_ = null; |
| 190 this.metadataCacheObserverId_ = null; | 207 this.metadataCacheObserverId_ = null; |
| 191 this.onExternallyUnmountedBound_ = this.onExternallyUnmounted_.bind(this); | 208 this.onExternallyUnmountedBound_ = this.onExternallyUnmounted_.bind(this); |
| 192 | 209 |
| 193 this.dataModel_ = new GalleryDataModel(this.context_.metadataCache); | 210 this.dataModel_ = new GalleryDataModel(this.context_.metadataCache); |
| 211 var downloadVolumeInfo = this.volumeManager_.getCurrentProfileVolumeInfo( | |
| 212 VolumeManagerCommon.VolumeType.DOWNLOADS); | |
| 213 downloadVolumeInfo.resolveDisplayRoot().then(function(entry) { | |
| 214 this.dataModel_.fallbackSaveDirectory = entry; | |
| 215 }.bind(this)).catch(function(error) { | |
| 216 console.error(error); | |
|
yoshiki
2014/08/15 03:37:14
Please show a short description of the error.
hirono
2014/08/15 08:04:15
Done.
| |
| 217 }); | |
| 194 this.selectionModel_ = new cr.ui.ListSelectionModel(); | 218 this.selectionModel_ = new cr.ui.ListSelectionModel(); |
| 195 | 219 |
| 196 this.initDom_(); | 220 this.initDom_(); |
| 197 this.initListeners_(); | 221 this.initListeners_(); |
| 198 } | 222 } |
| 199 | 223 |
| 200 /** | 224 /** |
| 201 * Gallery extends cr.EventTarget. | 225 * Gallery extends cr.EventTarget. |
| 202 */ | 226 */ |
| 203 Gallery.prototype.__proto__ = cr.EventTarget.prototype; | 227 Gallery.prototype.__proto__ = cr.EventTarget.prototype; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 this.filenameEdit_.addEventListener('focus', | 355 this.filenameEdit_.addEventListener('focus', |
| 332 this.onFilenameFocus_.bind(this)); | 356 this.onFilenameFocus_.bind(this)); |
| 333 | 357 |
| 334 this.filenameEdit_.addEventListener('keydown', | 358 this.filenameEdit_.addEventListener('keydown', |
| 335 this.onFilenameEditKeydown_.bind(this)); | 359 this.onFilenameEditKeydown_.bind(this)); |
| 336 | 360 |
| 337 var middleSpacer = this.filenameSpacer_ = | 361 var middleSpacer = this.filenameSpacer_ = |
| 338 this.toolbar_.querySelector('.middle-spacer'); | 362 this.toolbar_.querySelector('.middle-spacer'); |
| 339 var buttonSpacer = this.toolbar_.querySelector('button-spacer'); | 363 var buttonSpacer = this.toolbar_.querySelector('button-spacer'); |
| 340 | 364 |
| 341 this.prompt_ = new ImageEditor.Prompt(this.container_, str); | 365 this.prompt_ = new ImageEditor.Prompt(this.container_, strf); |
| 342 | 366 |
| 343 this.modeButton_ = this.toolbar_.querySelector('button.mode'); | 367 this.modeButton_ = this.toolbar_.querySelector('button.mode'); |
| 344 this.modeButton_.addEventListener('click', this.toggleMode_.bind(this, null)); | 368 this.modeButton_.addEventListener('click', this.toggleMode_.bind(this, null)); |
| 345 | 369 |
| 346 this.mosaicMode_ = new MosaicMode(content, | 370 this.mosaicMode_ = new MosaicMode(content, |
| 347 this.dataModel_, | 371 this.dataModel_, |
| 348 this.selectionModel_, | 372 this.selectionModel_, |
| 349 this.volumeManager_, | 373 this.volumeManager_, |
| 350 this.toggleMode_.bind(this, null)); | 374 this.toggleMode_.bind(this, null)); |
| 351 | 375 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 * @param {!Array.<Entry>} selectedEntries Array of selected entries. | 427 * @param {!Array.<Entry>} selectedEntries Array of selected entries. |
| 404 */ | 428 */ |
| 405 Gallery.prototype.load = function(entries, selectedEntries) { | 429 Gallery.prototype.load = function(entries, selectedEntries) { |
| 406 // Obtains max chank size. | 430 // Obtains max chank size. |
| 407 var maxChunkSize = 20; | 431 var maxChunkSize = 20; |
| 408 var volumeInfo = this.volumeManager_.getVolumeInfo(entries[0]); | 432 var volumeInfo = this.volumeManager_.getVolumeInfo(entries[0]); |
| 409 if (volumeInfo && | 433 if (volumeInfo && |
| 410 volumeInfo.volumeType === VolumeManagerCommon.VolumeType.MTP) { | 434 volumeInfo.volumeType === VolumeManagerCommon.VolumeType.MTP) { |
| 411 maxChunkSize = 1; | 435 maxChunkSize = 1; |
| 412 } | 436 } |
| 437 if (volumeInfo.isReadOnly) | |
| 438 this.context_.readonlyDirName = volumeInfo.label; | |
| 413 | 439 |
| 414 // Make loading list. | 440 // Make loading list. |
| 415 var entrySet = {}; | 441 var entrySet = {}; |
| 416 for (var i = 0; i < entries.length; i++) { | 442 for (var i = 0; i < entries.length; i++) { |
| 417 var entry = entries[i]; | 443 var entry = entries[i]; |
| 418 entrySet[entry.toURL()] = { | 444 entrySet[entry.toURL()] = { |
| 419 entry: entry, | 445 entry: entry, |
| 420 selected: false, | 446 selected: false, |
| 421 index: i | 447 index: i |
| 422 }; | 448 }; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 454 var entries = chunk.map(function(chunkItem) { | 480 var entries = chunk.map(function(chunkItem) { |
| 455 return chunkItem.entry; | 481 return chunkItem.entry; |
| 456 }); | 482 }); |
| 457 this.metadataCache_.get(entries, Gallery.METADATA_TYPE, fulfill); | 483 this.metadataCache_.get(entries, Gallery.METADATA_TYPE, fulfill); |
| 458 }.bind(this)).then(function(metadataList) { | 484 }.bind(this)).then(function(metadataList) { |
| 459 if (chunk.length !== metadataList.length) | 485 if (chunk.length !== metadataList.length) |
| 460 return Promise.reject('Failed to load metadata.'); | 486 return Promise.reject('Failed to load metadata.'); |
| 461 | 487 |
| 462 // Add items to the model. | 488 // Add items to the model. |
| 463 var items = chunk.map(function(chunkItem, index) { | 489 var items = chunk.map(function(chunkItem, index) { |
| 490 var volumeInfo = this.volumeManager_.getVolumeInfo(chunkItem.entry); | |
| 464 var clonedMetadata = MetadataCache.cloneMetadata(metadataList[index]); | 491 var clonedMetadata = MetadataCache.cloneMetadata(metadataList[index]); |
| 465 return new Gallery.Item( | 492 return new Gallery.Item( |
| 466 chunkItem.entry, | 493 chunkItem.entry, |
| 467 clonedMetadata, | 494 clonedMetadata, |
| 468 this.metadataCache_, | 495 this.metadataCache_, |
| 469 /* original */ true); | 496 /* original */ true, |
| 497 /* readonly */ !!(volumeInfo && volumeInfo.isReadOnly)); | |
| 470 }.bind(this)); | 498 }.bind(this)); |
| 471 this.dataModel_.push.apply(this.dataModel_, items); | 499 this.dataModel_.push.apply(this.dataModel_, items); |
| 472 | 500 |
| 473 // Apply the selection. | 501 // Apply the selection. |
| 474 var selectionUpdated = false; | 502 var selectionUpdated = false; |
| 475 for (var i = 0; i < chunk.length; i++) { | 503 for (var i = 0; i < chunk.length; i++) { |
| 476 if (!chunk[i].selected) | 504 if (!chunk[i].selected) |
| 477 continue; | 505 continue; |
| 478 var index = this.dataModel_.indexOf(items[i]); | 506 var index = this.dataModel_.indexOf(items[i]); |
| 479 if (index < 0) | 507 if (index < 0) |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 795 | 823 |
| 796 // Name box and rename support. | 824 // Name box and rename support. |
| 797 | 825 |
| 798 /** | 826 /** |
| 799 * Updates the UI related to the selected item and the persistent state. | 827 * Updates the UI related to the selected item and the persistent state. |
| 800 * | 828 * |
| 801 * @private | 829 * @private |
| 802 */ | 830 */ |
| 803 Gallery.prototype.updateSelectionAndState_ = function() { | 831 Gallery.prototype.updateSelectionAndState_ = function() { |
| 804 var numSelectedItems = this.selectionModel_.selectedIndexes.length; | 832 var numSelectedItems = this.selectionModel_.selectedIndexes.length; |
| 805 var displayName = ''; | |
| 806 var selectedEntryURL = null; | 833 var selectedEntryURL = null; |
| 807 | 834 |
| 808 // If it's selecting something, update the variable values. | 835 // If it's selecting something, update the variable values. |
| 809 if (numSelectedItems) { | 836 if (numSelectedItems) { |
| 810 // Obtains selected item. | 837 // Obtains selected item. |
| 811 var selectedItem = | 838 var selectedItem = |
| 812 this.dataModel_.item(this.selectionModel_.selectedIndex); | 839 this.dataModel_.item(this.selectionModel_.selectedIndex); |
| 813 this.selectedEntry_ = selectedItem.getEntry(); | 840 this.selectedEntry_ = selectedItem.getEntry(); |
| 814 selectedEntryURL = this.selectedEntry_.toURL(); | 841 selectedEntryURL = this.selectedEntry_.toURL(); |
| 815 | 842 |
| 816 // Update cache. | 843 // Update cache. |
| 817 selectedItem.touch(); | 844 selectedItem.touch(); |
| 818 this.dataModel_.evictCache(); | 845 this.dataModel_.evictCache(); |
| 819 | 846 |
| 820 // Update the title and the display name. | 847 // Update the title and the display name. |
| 821 if (numSelectedItems === 1) { | 848 if (numSelectedItems === 1) { |
| 822 window.top.document.title = this.selectedEntry_.name; | 849 window.top.document.title = this.selectedEntry_.name; |
| 823 displayName = ImageUtil.getDisplayNameFromName(this.selectedEntry_.name); | 850 this.filenameEdit_.disabled = selectedItem.isReadOnly(); |
| 851 this.filenameEdit_.value = | |
| 852 ImageUtil.getDisplayNameFromName(this.selectedEntry_.name); | |
| 824 } else if (this.context_.curDirEntry) { | 853 } else if (this.context_.curDirEntry) { |
| 825 // If the Gallery was opened on search results the search query will not | 854 // If the Gallery was opened on search results the search query will not |
| 826 // be recorded in the app state and the relaunch will just open the | 855 // be recorded in the app state and the relaunch will just open the |
| 827 // gallery in the curDirEntry directory. | 856 // gallery in the curDirEntry directory. |
| 828 window.top.document.title = this.context_.curDirEntry.name; | 857 window.top.document.title = this.context_.curDirEntry.name; |
| 829 displayName = strf('GALLERY_ITEMS_SELECTED', numSelectedItems); | 858 this.filenameEdit_.disabled = true; |
| 859 this.filenameEdit_.value = | |
| 860 strf('GALLERY_ITEMS_SELECTED', numSelectedItems); | |
| 830 } | 861 } |
| 831 } | 862 } |
| 832 | 863 |
| 833 window.top.util.updateAppState( | 864 window.top.util.updateAppState( |
| 834 null, // Keep the current directory. | 865 null, // Keep the current directory. |
| 835 selectedEntryURL, // Update the selection. | 866 selectedEntryURL, // Update the selection. |
| 836 {gallery: (this.currentMode_ === this.mosaicMode_ ? 'mosaic' : 'slide')}); | 867 {gallery: (this.currentMode_ === this.mosaicMode_ ? 'mosaic' : 'slide')}); |
| 837 | 868 |
| 838 // We can't rename files in readonly directory. | |
| 839 // We can only rename a single file. | |
| 840 this.filenameEdit_.disabled = numSelectedItems !== 1 || | |
| 841 this.context_.readonlyDirName; | |
| 842 this.filenameEdit_.value = displayName; | |
| 843 | |
| 844 // Update the share button. | 869 // Update the share button. |
| 845 var item = this.getSingleSelectedItem(); | 870 var item = this.getSingleSelectedItem(); |
| 846 this.shareButton_.hidden = !item || !item.isOnDrive(); | 871 this.shareButton_.hidden = !item || !item.isOnDrive(); |
| 847 }; | 872 }; |
| 848 | 873 |
| 849 /** | 874 /** |
| 850 * Click event handler on filename edit box | 875 * Click event handler on filename edit box |
| 851 * @private | 876 * @private |
| 852 */ | 877 */ |
| 853 Gallery.prototype.onFilenameFocus_ = function() { | 878 Gallery.prototype.onFilenameFocus_ = function() { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 981 window.loadTimeData.data = backgroundComponents.stringData; | 1006 window.loadTimeData.data = backgroundComponents.stringData; |
| 982 gallery = new Gallery(backgroundComponents.volumeManager); | 1007 gallery = new Gallery(backgroundComponents.volumeManager); |
| 983 }; | 1008 }; |
| 984 | 1009 |
| 985 /** | 1010 /** |
| 986 * Loads entries. | 1011 * Loads entries. |
| 987 */ | 1012 */ |
| 988 window.loadEntries = function(entries, selectedEntries) { | 1013 window.loadEntries = function(entries, selectedEntries) { |
| 989 gallery.load(entries, selectedEntries); | 1014 gallery.load(entries, selectedEntries); |
| 990 }; | 1015 }; |
| OLD | NEW |