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 |