| 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 /** | 5 /** |
| 6 * @param {!Element} container Content container. | 6 * @param {!Element} container Content container. |
| 7 * @param {!ErrorBanner} errorBanner Error banner. | 7 * @param {!ErrorBanner} errorBanner Error banner. |
| 8 * @param {!cr.ui.ArrayDataModel} dataModel Data model. | 8 * @param {!cr.ui.ArrayDataModel} dataModel Data model. |
| 9 * @param {!cr.ui.ListSelectionModel} selectionModel Selection model. | 9 * @param {!cr.ui.ListSelectionModel} selectionModel Selection model. |
| 10 * @param {!VolumeManagerWrapper} volumeManager Volume manager. | 10 * @param {!VolumeManagerWrapper} volumeManager Volume manager. |
| (...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 517 | 517 |
| 518 // No items left, show the banner. | 518 // No items left, show the banner. |
| 519 if (this.getItemCount_() === 0) | 519 if (this.getItemCount_() === 0) |
| 520 this.errorBanner_.show('GALLERY_NO_IMAGES'); | 520 this.errorBanner_.show('GALLERY_NO_IMAGES'); |
| 521 | 521 |
| 522 this.scheduleLayout(Mosaic.LAYOUT_DELAY); | 522 this.scheduleLayout(Mosaic.LAYOUT_DELAY); |
| 523 } | 523 } |
| 524 | 524 |
| 525 if (event.added.length) { | 525 if (event.added.length) { |
| 526 var newTiles = []; | 526 var newTiles = []; |
| 527 for (var t = 0; t !== event.added.length; t++) | 527 for (var t = 0; t !== event.added.length; t++) { |
| 528 newTiles.push(new Mosaic.Tile(this, | 528 newTiles.push(new Mosaic.Tile( |
| 529 assertInstanceof(this.dataModel_.item(index + t), Gallery.Item))); | 529 this, |
| 530 assertInstanceof(this.dataModel_.item(index + t), |
| 531 Gallery.Item))); |
| 532 } |
| 530 | 533 |
| 531 this.tiles_.splice.apply(this.tiles_, [index, 0].concat(newTiles)); | 534 this.tiles_.splice.apply(this.tiles_, [index, 0].concat(newTiles)); |
| 532 this.initTiles_(newTiles); | 535 this.initTiles_(newTiles); |
| 533 this.scheduleLayout(Mosaic.LAYOUT_DELAY); | 536 this.scheduleLayout(Mosaic.LAYOUT_DELAY); |
| 534 } | 537 } |
| 535 | 538 |
| 536 if (this.tiles_.length !== this.dataModel_.length) | 539 if (this.tiles_.length !== this.dataModel_.length) |
| 537 console.error('Mosaic is out of sync'); | 540 console.error('Mosaic is out of sync'); |
| 538 }; | 541 }; |
| 539 | 542 |
| 540 /** | 543 /** |
| 541 * Content change handler. | 544 * Content change handler. |
| 542 * | 545 * |
| 543 * @param {!Event} event Event. | 546 * @param {!Event} event Event. |
| 544 * @private | 547 * @private |
| 545 */ | 548 */ |
| 546 Mosaic.prototype.onContentChange_ = function(event) { | 549 Mosaic.prototype.onContentChange_ = function(event) { |
| 547 if (!this.tiles_) | 550 if (!this.tiles_) |
| 548 return; | 551 return; |
| 549 | 552 |
| 550 if (!event.thumbnailChanged) | 553 if (!event.thumbnailChanged) |
| 551 return; // Thumbnail unchanged, nothing to do. | 554 return; // Thumbnail unchanged, nothing to do. |
| 552 | 555 |
| 553 var index = this.dataModel_.indexOf(event.item); | 556 var index = this.dataModel_.indexOf(event.item); |
| 554 if (index !== this.selectionModel_.selectedIndex) | |
| 555 console.error('Content changed for unselected item'); | |
| 556 | |
| 557 this.layoutModel_.invalidateFromTile_(index); | 557 this.layoutModel_.invalidateFromTile_(index); |
| 558 this.tiles_[index].init(); | 558 this.tiles_[index].init(); |
| 559 this.tiles_[index].unload(); | 559 this.tiles_[index].unload(); |
| 560 this.tiles_[index].load( | 560 this.tiles_[index].load( |
| 561 Mosaic.Tile.LoadMode.HIGH_DPI, | 561 Mosaic.Tile.LoadMode.HIGH_DPI, |
| 562 this.scheduleLayout.bind(this, Mosaic.LAYOUT_DELAY)); | 562 this.scheduleLayout.bind(this, Mosaic.LAYOUT_DELAY)); |
| 563 }; | 563 }; |
| 564 | 564 |
| 565 /** | 565 /** |
| 566 * Keydown event handler. | 566 * Keydown event handler. |
| (...skipping 1486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2053 * Initializes the thumbnail in the tile. Does not load an image, but sets | 2053 * Initializes the thumbnail in the tile. Does not load an image, but sets |
| 2054 * target dimensions using metadata. | 2054 * target dimensions using metadata. |
| 2055 */ | 2055 */ |
| 2056 Mosaic.Tile.prototype.init = function() { | 2056 Mosaic.Tile.prototype.init = function() { |
| 2057 this.markUnloaded(); | 2057 this.markUnloaded(); |
| 2058 this.left_ = null; // Mark as not laid out. | 2058 this.left_ = null; // Mark as not laid out. |
| 2059 | 2059 |
| 2060 // Set higher priority for the selected elements to load them first. | 2060 // Set higher priority for the selected elements to load them first. |
| 2061 var priority = this.getAttribute('selected') ? 2 : 3; | 2061 var priority = this.getAttribute('selected') ? 2 : 3; |
| 2062 | 2062 |
| 2063 // Use embedded thumbnails on Drive, since they have higher resolution. | 2063 if (this.getItem().getThumbnailMetadataItem()) { |
| 2064 this.thumbnailLoader_ = new ThumbnailLoader( | 2064 // Use embedded thumbnails on Drive, since they have higher resolution. |
| 2065 this.getItem().getEntry(), | 2065 this.thumbnailLoader_ = new ThumbnailLoader( |
| 2066 ThumbnailLoader.LoaderType.CANVAS, | |
| 2067 this.getItem().getThumbnailMetadataItem(), | |
| 2068 undefined, // Media type. | |
| 2069 [ | |
| 2070 ThumbnailLoader.LoadTarget.EXTERNAL_METADATA, | |
| 2071 ThumbnailLoader.LoadTarget.FILE_ENTRY | |
| 2072 ]); | |
| 2073 | |
| 2074 // If no hidpi embedded thumbnail available, then use the low resolution | |
| 2075 // for preloading. | |
| 2076 if (this.thumbnailLoader_.getLoadTarget() === | |
| 2077 ThumbnailLoader.LoadTarget.FILE_ENTRY) { | |
| 2078 this.thumbnailPreloader_ = new ThumbnailLoader( | |
| 2079 this.getItem().getEntry(), | 2066 this.getItem().getEntry(), |
| 2080 ThumbnailLoader.LoaderType.CANVAS, | 2067 ThumbnailLoader.LoaderType.CANVAS, |
| 2081 this.getItem().getThumbnailMetadataItem(), | 2068 this.getItem().getThumbnailMetadataItem(), |
| 2082 undefined, // Media type. | 2069 undefined, // Media type. |
| 2083 [ | 2070 [ |
| 2084 ThumbnailLoader.LoadTarget.CONTENT_METADATA | 2071 ThumbnailLoader.LoadTarget.EXTERNAL_METADATA, |
| 2085 ], | 2072 ThumbnailLoader.LoadTarget.FILE_ENTRY |
| 2086 // Preloaders have always higher priotity, so the preload images | 2073 ]); |
| 2087 // are loaded as soon as possible. | 2074 |
| 2088 2); | 2075 // If no hidpi embedded thumbnail available, then use the low resolution |
| 2089 if (!this.thumbnailPreloader_.getLoadTarget()) | 2076 // for preloading. |
| 2090 this.thumbnailPreloader_ = null; | 2077 if (this.thumbnailLoader_.getLoadTarget() === |
| 2078 ThumbnailLoader.LoadTarget.FILE_ENTRY) { |
| 2079 this.thumbnailPreloader_ = new ThumbnailLoader( |
| 2080 this.getItem().getEntry(), |
| 2081 ThumbnailLoader.LoaderType.CANVAS, |
| 2082 this.getItem().getThumbnailMetadataItem(), |
| 2083 undefined, // Media type. |
| 2084 [ |
| 2085 ThumbnailLoader.LoadTarget.CONTENT_METADATA |
| 2086 ], |
| 2087 // Preloaders have always higher priotity, so the preload images |
| 2088 // are loaded as soon as possible. |
| 2089 2); |
| 2090 if (!this.thumbnailPreloader_.getLoadTarget()) |
| 2091 this.thumbnailPreloader_ = null; |
| 2092 } |
| 2091 } | 2093 } |
| 2092 | 2094 |
| 2093 // Dimensions are always acquired from the metadata. For local files, it is | 2095 // Dimensions are always acquired from the metadata. For local files, it is |
| 2094 // extracted from headers. For Drive files, it is received via the Drive API. | 2096 // extracted from headers. For Drive files, it is received via the Drive API. |
| 2095 // If the dimensions are not available, then the fallback dimensions will be | 2097 // If the dimensions are not available, then the fallback dimensions will be |
| 2096 // used (same as for the generic icon). | 2098 // used (same as for the generic icon). |
| 2097 var metadataItem = this.getItem().getMetadataItem(); | 2099 var metadataItem = this.getItem().getMetadataItem(); |
| 2098 var width; | 2100 var width; |
| 2099 var height; | 2101 var height; |
| 2100 if (metadataItem.imageWidth && metadataItem.imageHeight) { | 2102 if (metadataItem && metadataItem.imageWidth && metadataItem.imageHeight) { |
| 2101 width = metadataItem.imageWidth; | 2103 width = metadataItem.imageWidth; |
| 2102 height = metadataItem.imageHeight; | 2104 height = metadataItem.imageHeight; |
| 2103 } else { | 2105 } else { |
| 2104 // No dimensions in metadata, then use the generic dimensions. | 2106 // No dimensions in metadata, then use the generic dimensions. |
| 2105 width = Mosaic.Tile.GENERIC_ICON_SIZE; | 2107 width = Mosaic.Tile.GENERIC_ICON_SIZE; |
| 2106 height = Mosaic.Tile.GENERIC_ICON_SIZE; | 2108 height = Mosaic.Tile.GENERIC_ICON_SIZE; |
| 2107 } | 2109 } |
| 2108 | 2110 |
| 2109 if (width > height) { | 2111 if (width > height) { |
| 2110 if (width > Mosaic.Tile.MAX_CONTENT_SIZE) { | 2112 if (width > Mosaic.Tile.MAX_CONTENT_SIZE) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2140 // Attaches the image to the tile and finalizes loading process for the | 2142 // Attaches the image to the tile and finalizes loading process for the |
| 2141 // specified loader. | 2143 // specified loader. |
| 2142 var finalizeLoader = function(mode, success, loader) { | 2144 var finalizeLoader = function(mode, success, loader) { |
| 2143 if (success && this.wrapper_) { | 2145 if (success && this.wrapper_) { |
| 2144 // Show the fade-in animation only when previously there was no image | 2146 // Show the fade-in animation only when previously there was no image |
| 2145 // attached in this tile. | 2147 // attached in this tile. |
| 2146 if (!this.imageLoaded_ && !this.imagePreloaded_) | 2148 if (!this.imageLoaded_ && !this.imagePreloaded_) |
| 2147 this.wrapper_.classList.add('animated'); | 2149 this.wrapper_.classList.add('animated'); |
| 2148 else | 2150 else |
| 2149 this.wrapper_.classList.remove('animated'); | 2151 this.wrapper_.classList.remove('animated'); |
| 2152 |
| 2153 // Add debug mode classes. |
| 2154 this.wrapper_.classList.remove('load-target-content-metadata'); |
| 2155 this.wrapper_.classList.remove('load-target-external-metadata'); |
| 2156 this.wrapper_.classList.remove('load-target-file-entry'); |
| 2157 switch (loader.getLoadTarget()) { |
| 2158 case ThumbnailLoader.LoadTarget.CONTENT_METADATA: |
| 2159 this.wrapper_.classList.add('load-target-content-metadata'); |
| 2160 break; |
| 2161 case ThumbnailLoader.LoadTarget.EXTERNAL_METADATA: |
| 2162 this.wrapper_.classList.add('load-target-external-metadata'); |
| 2163 break; |
| 2164 case ThumbnailLoader.LoadTarget.FILE_ENTRY: |
| 2165 this.wrapper_.classList.add('load-target-file-entry'); |
| 2166 break; |
| 2167 } |
| 2168 |
| 2169 loader.attachImage(this.wrapper_, ThumbnailLoader.FillMode.OVER_FILL); |
| 2150 } | 2170 } |
| 2151 | 2171 |
| 2152 // Add debug mode classes. | |
| 2153 this.wrapper_.classList.remove('load-target-content-metadata'); | |
| 2154 this.wrapper_.classList.remove('load-target-external-metadata'); | |
| 2155 this.wrapper_.classList.remove('load-target-file-entry'); | |
| 2156 switch (loader.getLoadTarget()) { | |
| 2157 case ThumbnailLoader.LoadTarget.CONTENT_METADATA: | |
| 2158 this.wrapper_.classList.add('load-target-content-metadata'); | |
| 2159 break; | |
| 2160 case ThumbnailLoader.LoadTarget.EXTERNAL_METADATA: | |
| 2161 this.wrapper_.classList.add('load-target-external-metadata'); | |
| 2162 break; | |
| 2163 case ThumbnailLoader.LoadTarget.FILE_ENTRY: | |
| 2164 this.wrapper_.classList.add('load-target-file-entry'); | |
| 2165 break; | |
| 2166 } | |
| 2167 loader.attachImage(this.wrapper_, ThumbnailLoader.FillMode.OVER_FILL); | |
| 2168 onImageLoaded(success); | 2172 onImageLoaded(success); |
| 2169 | 2173 |
| 2170 switch (mode) { | 2174 switch (mode) { |
| 2171 case Mosaic.Tile.LoadMode.LOW_DPI: | 2175 case Mosaic.Tile.LoadMode.LOW_DPI: |
| 2172 this.imagePreloading_ = false; | 2176 this.imagePreloading_ = false; |
| 2173 this.imagePreloaded_ = true; | 2177 this.imagePreloaded_ = true; |
| 2174 break; | 2178 break; |
| 2175 case Mosaic.Tile.LoadMode.HIGH_DPI: | 2179 case Mosaic.Tile.LoadMode.HIGH_DPI: |
| 2176 this.imageLoading_ = false; | 2180 this.imageLoading_ = false; |
| 2177 this.imageLoaded_ = true; | 2181 this.imageLoaded_ = true; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2188 if (this.imageLoaded_) | 2192 if (this.imageLoaded_) |
| 2189 return; | 2193 return; |
| 2190 finalizeLoader(Mosaic.Tile.LoadMode.LOW_DPI, | 2194 finalizeLoader(Mosaic.Tile.LoadMode.LOW_DPI, |
| 2191 success, | 2195 success, |
| 2192 this.thumbnailPreloader_); | 2196 this.thumbnailPreloader_); |
| 2193 }.bind(this)); | 2197 }.bind(this)); |
| 2194 } | 2198 } |
| 2195 | 2199 |
| 2196 // Load the high-dpi image only when it is requested, or the low-dpi is not | 2200 // Load the high-dpi image only when it is requested, or the low-dpi is not |
| 2197 // available. | 2201 // available. |
| 2198 if (!this.imageLoading_ && | 2202 if (!this.imageLoading_ && this.thumbnailLoader_ && |
| 2199 (loadMode === Mosaic.Tile.LoadMode.HIGH_DPI || !this.imagePreloading_)) { | 2203 (loadMode === Mosaic.Tile.LoadMode.HIGH_DPI || !this.imagePreloading_)) { |
| 2200 this.imageLoading_ = true; | 2204 this.imageLoading_ = true; |
| 2201 this.thumbnailLoader_.loadDetachedImage(function(success) { | 2205 this.thumbnailLoader_.loadDetachedImage(function(success) { |
| 2202 // Cancel preloading, since the hi-dpi image is ready. | 2206 // Cancel preloading, since the hi-dpi image is ready. |
| 2203 if (this.thumbnailPreloader_) | 2207 if (this.thumbnailPreloader_) |
| 2204 this.thumbnailPreloader_.cancel(); | 2208 this.thumbnailPreloader_.cancel(); |
| 2205 finalizeLoader(Mosaic.Tile.LoadMode.HIGH_DPI, | 2209 finalizeLoader(Mosaic.Tile.LoadMode.HIGH_DPI, |
| 2206 success, | 2210 success, |
| 2207 this.thumbnailLoader_); | 2211 this.thumbnailLoader_); |
| 2208 }.bind(this)); | 2212 }.bind(this)); |
| 2209 } | 2213 } |
| 2210 }; | 2214 }; |
| 2211 | 2215 |
| 2212 /** | 2216 /** |
| 2213 * Unloads an image from the tile. | 2217 * Unloads an image from the tile. |
| 2214 */ | 2218 */ |
| 2215 Mosaic.Tile.prototype.unload = function() { | 2219 Mosaic.Tile.prototype.unload = function() { |
| 2216 this.thumbnailLoader_.cancel(); | 2220 if (this.thumbnailLoader_) |
| 2221 this.thumbnailLoader_.cancel(); |
| 2217 if (this.thumbnailPreloader_) | 2222 if (this.thumbnailPreloader_) |
| 2218 this.thumbnailPreloader_.cancel(); | 2223 this.thumbnailPreloader_.cancel(); |
| 2219 this.imagePreloaded_ = false; | 2224 this.imagePreloaded_ = false; |
| 2220 this.imageLoaded_ = false; | 2225 this.imageLoaded_ = false; |
| 2221 this.imagePreloading_ = false; | 2226 this.imagePreloading_ = false; |
| 2222 this.imageLoading_ = false; | 2227 this.imageLoading_ = false; |
| 2223 this.wrapper_.innerText = ''; | 2228 if (this.wrapper_) |
| 2229 this.wrapper_.innerText = ''; |
| 2224 }; | 2230 }; |
| 2225 | 2231 |
| 2226 /** | 2232 /** |
| 2227 * Selects/unselects the tile. | 2233 * Selects/unselects the tile. |
| 2228 * | 2234 * |
| 2229 * @param {boolean} on True if selected. | 2235 * @param {boolean} on True if selected. |
| 2230 */ | 2236 */ |
| 2231 Mosaic.Tile.prototype.select = function(on) { | 2237 Mosaic.Tile.prototype.select = function(on) { |
| 2232 if (on) | 2238 if (on) |
| 2233 this.setAttribute('selected', true); | 2239 this.setAttribute('selected', true); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2309 return new ImageRect(this.left_ - this.container_.scrollLeft, this.top_, | 2315 return new ImageRect(this.left_ - this.container_.scrollLeft, this.top_, |
| 2310 this.width_, this.height_).inflate(-margin, -margin); | 2316 this.width_, this.height_).inflate(-margin, -margin); |
| 2311 }; | 2317 }; |
| 2312 | 2318 |
| 2313 /** | 2319 /** |
| 2314 * @return {number} X coordinate of the tile center. | 2320 * @return {number} X coordinate of the tile center. |
| 2315 */ | 2321 */ |
| 2316 Mosaic.Tile.prototype.getCenterX = function() { | 2322 Mosaic.Tile.prototype.getCenterX = function() { |
| 2317 return this.left_ + Math.round(this.width_ / 2); | 2323 return this.left_ + Math.round(this.width_ / 2); |
| 2318 }; | 2324 }; |
| OLD | NEW |