Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(597)

Side by Side Diff: chrome/browser/resources/file_manager/js/photo/mosaic_mode.js

Issue 12316118: Enabled Mosaic view on each volume. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Cleaned up. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 {cr.ui.ArrayDataModel} dataModel Data model. 7 * @param {cr.ui.ArrayDataModel} dataModel Data model.
8 * @param {cr.ui.ListSelectionModel} selectionModel Selection model. 8 * @param {cr.ui.ListSelectionModel} selectionModel Selection model.
9 * @param {MetadataCache} metadataCache Metadata cache. 9 * @param {MetadataCache} metadataCache Metadata cache.
10 * @param {function} toggleMode Function to switch to the Slide mode. 10 * @param {function} toggleMode Function to switch to the Slide mode.
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 new Mosaic.SelectionController(this.selectionModel_, this.layoutModel_); 130 new Mosaic.SelectionController(this.selectionModel_, this.layoutModel_);
131 131
132 this.tiles_ = []; 132 this.tiles_ = [];
133 for (var i = 0; i != this.dataModel_.length; i++) 133 for (var i = 0; i != this.dataModel_.length; i++)
134 this.tiles_.push(new Mosaic.Tile(this, this.dataModel_.item(i))); 134 this.tiles_.push(new Mosaic.Tile(this, this.dataModel_.item(i)));
135 135
136 this.selectionModel_.selectedIndexes.forEach(function(index) { 136 this.selectionModel_.selectedIndexes.forEach(function(index) {
137 this.tiles_[index].select(true); 137 this.tiles_[index].select(true);
138 }.bind(this)); 138 }.bind(this));
139 139
140 this.loadTiles_(this.tiles_); 140 this.initTiles_(this.tiles_);
141 141
142 // The listeners might be called while some tiles are still loading. 142 // The listeners might be called while some tiles are still loading.
143 this.initListeners_(); 143 this.initListeners_();
144 }; 144 };
145 145
146 /** 146 /**
147 * @return {boolean} Whether mosaic is initialized. 147 * @return {boolean} Whether mosaic is initialized.
148 */ 148 */
149 Mosaic.prototype.isInitialized = function() { 149 Mosaic.prototype.isInitialized = function() {
150 return !!this.tiles_; 150 return !!this.tiles_;
151 }; 151 };
152 152
153 /** 153 /**
154 * Start listening to events. 154 * Start listening to events.
155 * 155 *
156 * We keep listening to events even when the mosaic is hidden in order to 156 * We keep listening to events even when the mosaic is hidden in order to
157 * keep the layout up to date. 157 * keep the layout up to date.
158 * 158 *
159 * @private 159 * @private
160 */ 160 */
161 Mosaic.prototype.initListeners_ = function() { 161 Mosaic.prototype.initListeners_ = function() {
162 this.ownerDocument.defaultView.addEventListener( 162 this.ownerDocument.defaultView.addEventListener(
163 'resize', this.onResize_.bind(this)); 163 'resize', this.onResize_.bind(this));
164 164
165 var mouseEventBound = this.onMouseEvent_.bind(this); 165 var mouseEventBound = this.onMouseEvent_.bind(this);
166 this.addEventListener('mousemove', mouseEventBound); 166 this.addEventListener('mousemove', mouseEventBound);
167 this.addEventListener('mousedown', mouseEventBound); 167 this.addEventListener('mousedown', mouseEventBound);
168 this.addEventListener('mouseup', mouseEventBound); 168 this.addEventListener('mouseup', mouseEventBound);
169 this.addEventListener('scroll', this.onScroll_.bind(this));
169 170
170 this.selectionModel_.addEventListener('change', this.onSelection_.bind(this)); 171 this.selectionModel_.addEventListener('change', this.onSelection_.bind(this));
171 this.selectionModel_.addEventListener('leadIndexChange', 172 this.selectionModel_.addEventListener('leadIndexChange',
172 this.onLeadChange_.bind(this)); 173 this.onLeadChange_.bind(this));
173 174
174 this.dataModel_.addEventListener('splice', this.onSplice_.bind(this)); 175 this.dataModel_.addEventListener('splice', this.onSplice_.bind(this));
175 this.dataModel_.addEventListener('content', this.onContentChange_.bind(this)); 176 this.dataModel_.addEventListener('content', this.onContentChange_.bind(this));
176 }; 177 };
177 178
178 /** 179 /**
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 /** 255 /**
255 * @param {number} index Tile index. 256 * @param {number} index Tile index.
256 * Scroll the given tile into the viewport. 257 * Scroll the given tile into the viewport.
257 */ 258 */
258 Mosaic.prototype.scrollIntoView = function(index) { 259 Mosaic.prototype.scrollIntoView = function(index) {
259 var tile = this.tiles_[index]; 260 var tile = this.tiles_[index];
260 if (tile) tile.scrollIntoView(); 261 if (tile) tile.scrollIntoView();
261 }; 262 };
262 263
263 /** 264 /**
264 * Load multiple tiles. 265 * Initializes multiple tiles.
265 * 266 *
266 * @param {Array.<Mosaic.Tile>} tiles Array of tiles. 267 * @param {Array.<Mosaic.Tile>} tiles Array of tiles.
267 * @param {function=} opt_callback Completion callback. 268 * @param {function=} opt_callback Completion callback.
268 * @private 269 * @private
269 */ 270 */
270 Mosaic.prototype.loadTiles_ = function(tiles, opt_callback) { 271 Mosaic.prototype.initTiles_ = function(tiles, opt_callback) {
271 // We do not want to use tile indices in asynchronous operations because they 272 // We do not want to use tile indices in asynchronous operations because they
272 // do not survive data model splices. Copy tile references instead. 273 // do not survive data model splices. Copy tile references instead.
273 tiles = tiles.slice(); 274 tiles = tiles.slice();
274 275
275 // Throttle the metadata access so that we do not overwhelm the file system. 276 // Throttle the metadata access so that we do not overwhelm the file system.
276 var MAX_CHUNK_SIZE = 10; 277 var MAX_CHUNK_SIZE = 10;
277 278
278 var loadChunk = function() { 279 var loadChunk = function() {
279 if (!tiles.length) { 280 if (!tiles.length) {
280 if (opt_callback) opt_callback(); 281 if (opt_callback) opt_callback();
281 return; 282 return;
282 } 283 }
283 var chunkSize = Math.min(tiles.length, MAX_CHUNK_SIZE); 284 var chunkSize = Math.min(tiles.length, MAX_CHUNK_SIZE);
284 var loaded = 0; 285 var loaded = 0;
285 for (var i = 0; i != chunkSize; i++) { 286 for (var i = 0; i != chunkSize; i++) {
286 this.loadTile_(tiles.shift(), function() { 287 this.initTile_(tiles.shift(), function() {
287 if (++loaded == chunkSize) { 288 if (++loaded == chunkSize) {
288 this.layout(); 289 this.layout();
289 loadChunk(); 290 loadChunk();
290 } 291 }
291 }.bind(this)); 292 }.bind(this));
292 } 293 }
293 }.bind(this); 294 }.bind(this);
294 295
295 loadChunk(); 296 loadChunk();
296 }; 297 };
297 298
298 /** 299 /**
299 * Load a single tile. 300 * Initializes a single tile.
300 * 301 *
301 * @param {Mosaic.Tile} tile Tile. 302 * @param {Mosaic.Tile} tile Tile.
302 * @param {function} callback Completion callback. 303 * @param {function} callback Completion callback.
yoshiki 2013/02/26 08:21:44 Please add function parameter.
mtomasz 2013/02/26 08:39:20 This callback has no arguments.
yoshiki 2013/02/26 08:50:27 Sorry for not being clear. Please add an empty par
mtomasz 2013/02/27 00:55:31 Done.
303 * @private 304 * @private
304 */ 305 */
305 Mosaic.prototype.loadTile_ = function(tile, callback) { 306 Mosaic.prototype.initTile_ = function(tile, callback) {
306 var url = tile.getItem().getUrl(); 307 var url = tile.getItem().getUrl();
307 var onImageLoaded = function(success) { 308 var onImageMeasured = callback;
308 if (!success && this.onThumbnailError_) {
309 this.onThumbnailError_(url);
310 }
311 callback();
312 }.bind(this);
313 this.metadataCache_.get(url, Gallery.METADATA_TYPE, 309 this.metadataCache_.get(url, Gallery.METADATA_TYPE,
314 function(metadata) { tile.load(metadata, onImageLoaded) }); 310 function(metadata) {
311 tile.init(metadata, onImageMeasured);
312 });
315 }; 313 };
316 314
317 /** 315 /**
318 * Reload all tiles. 316 * Reload all tiles.
319 */ 317 */
320 Mosaic.prototype.reload = function() { 318 Mosaic.prototype.reload = function() {
321 this.layoutModel_.reset_(); 319 this.layoutModel_.reset_();
322 this.tiles_.forEach(function(t) { t.markUnloaded() }); 320 this.tiles_.forEach(function(t) { t.markUnloaded() });
323 this.loadTiles_(this.tiles_); 321 this.initTiles_(this.tiles_);
324 }; 322 };
325 323
326 /** 324 /**
327 * Layout the tiles in the order of their indices. 325 * Layout the tiles in the order of their indices.
328 * 326 *
329 * Starts where it last stopped (at #0 the first time). 327 * Starts where it last stopped (at #0 the first time).
330 * Stops when all tiles are processed or when the next tile is still loading. 328 * Stops when all tiles are processed or when the next tile is still loading.
331 */ 329 */
332 Mosaic.prototype.layout = function() { 330 Mosaic.prototype.layout = function() {
333 if (this.layoutTimer_) { 331 if (this.layoutTimer_) {
334 clearTimeout(this.layoutTimer_); 332 clearTimeout(this.layoutTimer_);
335 this.layoutTimer_ = null; 333 this.layoutTimer_ = null;
336 } 334 }
337 while (true) { 335 while (true) {
338 var index = this.layoutModel_.getTileCount(); 336 var index = this.layoutModel_.getTileCount();
339 if (index == this.tiles_.length) 337 if (index == this.tiles_.length)
340 break; // All tiles done. 338 break; // All tiles done.
341 var tile = this.tiles_[index]; 339 var tile = this.tiles_[index];
342 if (!tile.isLoaded()) 340 if (!tile.isInitialized())
343 break; // Next layout will try to restart from here. 341 break; // Next layout will try to restart from here.
344 this.layoutModel_.add(tile, index + 1 == this.tiles_.length); 342 this.layoutModel_.add(tile, index + 1 == this.tiles_.length);
345 } 343 }
344 this.loadVisibleTiles_();
346 }; 345 };
347 346
348 /** 347 /**
349 * Schedule the layout. 348 * Schedule the layout.
350 * 349 *
351 * @param {number=} opt_delay Delay in ms. 350 * @param {number=} opt_delay Delay in ms.
352 */ 351 */
353 Mosaic.prototype.scheduleLayout = function(opt_delay) { 352 Mosaic.prototype.scheduleLayout = function(opt_delay) {
354 if (!this.layoutTimer_) { 353 if (!this.layoutTimer_) {
355 this.layoutTimer_ = setTimeout(function() { 354 this.layoutTimer_ = setTimeout(function() {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 target = target.parentNode) { 389 target = target.parentNode) {
391 if (target.classList.contains('mosaic-tile')) { 390 if (target.classList.contains('mosaic-tile')) {
392 index = this.dataModel_.indexOf(target.getItem()); 391 index = this.dataModel_.indexOf(target.getItem());
393 break; 392 break;
394 } 393 }
395 } 394 }
396 this.selectionController_.handlePointerDownUp(event, index); 395 this.selectionController_.handlePointerDownUp(event, index);
397 }; 396 };
398 397
399 /** 398 /**
399 * Scroll handler.
400 * @private
401 */
402 Mosaic.prototype.onScroll_ = function() {
403 this.loadVisibleTiles_();
404 };
405
406 /**
400 * Selection change handler. 407 * Selection change handler.
401 * 408 *
402 * @param {Event} event Event. 409 * @param {Event} event Event.
403 * @private 410 * @private
404 */ 411 */
405 Mosaic.prototype.onSelection_ = function(event) { 412 Mosaic.prototype.onSelection_ = function(event) {
406 for (var i = 0; i != event.changes.length; i++) { 413 for (var i = 0; i != event.changes.length; i++) {
407 var change = event.changes[i]; 414 var change = event.changes[i];
408 var tile = this.tiles_[change.index]; 415 var tile = this.tiles_[change.index];
409 if (tile) tile.select(change.selected); 416 if (tile) tile.select(change.selected);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
441 this.tiles_.splice(index, event.removed.length); 448 this.tiles_.splice(index, event.removed.length);
442 this.scheduleLayout(Mosaic.LAYOUT_DELAY); 449 this.scheduleLayout(Mosaic.LAYOUT_DELAY);
443 } 450 }
444 451
445 if (event.added.length) { 452 if (event.added.length) {
446 var newTiles = []; 453 var newTiles = [];
447 for (var t = 0; t != event.added.length; t++) 454 for (var t = 0; t != event.added.length; t++)
448 newTiles.push(new Mosaic.Tile(this, this.dataModel_.item(index + t))); 455 newTiles.push(new Mosaic.Tile(this, this.dataModel_.item(index + t)));
449 456
450 this.tiles_.splice.apply(this.tiles_, [index, 0].concat(newTiles)); 457 this.tiles_.splice.apply(this.tiles_, [index, 0].concat(newTiles));
451 this.loadTiles_(newTiles); 458 this.initTiles_(newTiles);
452 } 459 }
453 460
454 if (this.tiles_.length != this.dataModel_.length) 461 if (this.tiles_.length != this.dataModel_.length)
455 console.error('Mosaic is out of sync'); 462 console.error('Mosaic is out of sync');
456 }; 463 };
457 464
458 /** 465 /**
459 * Content change handler. 466 * Content change handler.
460 * 467 *
461 * @param {Event} event Event. 468 * @param {Event} event Event.
462 * @private 469 * @private
463 */ 470 */
464 Mosaic.prototype.onContentChange_ = function(event) { 471 Mosaic.prototype.onContentChange_ = function(event) {
465 if (!this.tiles_) 472 if (!this.tiles_)
466 return; 473 return;
467 474
468 if (!event.metadata) 475 if (!event.metadata)
469 return; // Thumbnail unchanged, nothing to do. 476 return; // Thumbnail unchanged, nothing to do.
470 477
471 var index = this.dataModel_.indexOf(event.item); 478 var index = this.dataModel_.indexOf(event.item);
472 if (index != this.selectionModel_.selectedIndex) 479 if (index != this.selectionModel_.selectedIndex)
473 console.error('Content changed for unselected item'); 480 console.error('Content changed for unselected item');
474 481
475 this.layoutModel_.invalidateFromTile_(index); 482 this.layoutModel_.invalidateFromTile_(index);
476 this.tiles_[index].load( 483 this.tiles_[index].init(event.metadata, function() {
477 event.metadata, this.scheduleLayout.bind(this, Mosaic.LAYOUT_DELAY)); 484 this.tiles_[index].load(
485 this.scheduleLayout.bind(this, Mosaic.LAYOUT_DELAY),
486 this.onThumbnailError_);
487 }.bind(this));
478 }; 488 };
479 489
480 /** 490 /**
481 * Keydown event handler. 491 * Keydown event handler.
482 * 492 *
483 * @param {Event} event Event. 493 * @param {Event} event Event.
484 * @return {boolean} True if the event has been consumed. 494 * @return {boolean} True if the event has been consumed.
485 */ 495 */
486 Mosaic.prototype.onKeyDown = function(event) { 496 Mosaic.prototype.onKeyDown = function(event) {
487 this.selectionController_.handleKeyDown(event); 497 this.selectionController_.handleKeyDown(event);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 }; 531 };
522 532
523 /** 533 /**
524 * Hide the mosaic. 534 * Hide the mosaic.
525 */ 535 */
526 Mosaic.prototype.hide = function() { 536 Mosaic.prototype.hide = function() {
527 this.removeAttribute('visible'); 537 this.removeAttribute('visible');
528 }; 538 };
529 539
530 /** 540 /**
541 * Loads visible tiles. Ignores consecutive calls. Does not reload already
542 * loaded images.
543 * @private
544 */
545 Mosaic.prototype.loadVisibleTiles_ = function() {
546 if (this.loadVisibleTilesTimer_) {
547 clearTimeout(this.loadVisibleTilesTimer_);
548 this.loadVisibleTilesTimer_ = null;
549 }
550 this.loadVisibleTilesTimer_ = setTimeout(function() {
551 var viewportRect = new Rect(0, 0, this.clientWidth, this.clientHeight);
552 for (var index = 0; index < this.tiles_.length; index++) {
553 var tile = this.tiles_[index];
554 var imageRect = tile.getImageRect();
555 if (!tile.isLoading() && !tile.isLoaded() && imageRect &&
556 imageRect.intersects(viewportRect)) {
557 tile.load(function() {}, this.onThumbnailError_);
558 }
559 }
560 }.bind(this), 100);
561 };
562
563 /**
531 * Apply or reset the zoom transform. 564 * Apply or reset the zoom transform.
532 * 565 *
533 * @param {Rect} tileRect Tile rectangle. Reset the transform if null. 566 * @param {Rect} tileRect Tile rectangle. Reset the transform if null.
534 * @param {Rect} imageRect Large image rectangle. Reset the transform if null. 567 * @param {Rect} imageRect Large image rectangle. Reset the transform if null.
535 * @param {boolean=} opt_instant True of the transition should be instant. 568 * @param {boolean=} opt_instant True of the transition should be instant.
536 */ 569 */
537 Mosaic.prototype.transform = function(tileRect, imageRect, opt_instant) { 570 Mosaic.prototype.transform = function(tileRect, imageRect, opt_instant) {
538 if (opt_instant) { 571 if (opt_instant) {
539 this.style.webkitTransitionDuration = '0'; 572 this.style.webkitTransitionDuration = '0';
540 } else { 573 } else {
(...skipping 1040 matching lines...) Expand 10 before | Expand all | Expand 10 after
1581 Mosaic.Tile.prototype.getMaxContentHeight = function() { 1614 Mosaic.Tile.prototype.getMaxContentHeight = function() {
1582 return this.maxContentHeight_; 1615 return this.maxContentHeight_;
1583 }; 1616 };
1584 1617
1585 /** 1618 /**
1586 * @return {number} The aspect ratio of the tile image. 1619 * @return {number} The aspect ratio of the tile image.
1587 */ 1620 */
1588 Mosaic.Tile.prototype.getAspectRatio = function() { return this.aspectRatio_ }; 1621 Mosaic.Tile.prototype.getAspectRatio = function() { return this.aspectRatio_ };
1589 1622
1590 /** 1623 /**
1624 * @return {boolean} True if the tile is initialized.
1625 */
1626 Mosaic.Tile.prototype.isInitialized = function() {
1627 return !!this.maxContentHeight_;
1628 };
1629
1630 /**
1591 * @return {boolean} True if the tile is loaded. 1631 * @return {boolean} True if the tile is loaded.
1592 */ 1632 */
1593 Mosaic.Tile.prototype.isLoaded = function() { return !!this.maxContentHeight_ }; 1633 Mosaic.Tile.prototype.isLoaded = function() {
1634 return this.imageLoaded_;
1635 };
1636
1637 /**
1638 * @return {boolean} True if the tile is being loaded.
1639 */
1640 Mosaic.Tile.prototype.isLoading = function() {
1641 return this.imageLoading_;
1642 };
1594 1643
1595 /** 1644 /**
1596 * Mark the tile as not loaded to prevent it from participating in the layout. 1645 * Mark the tile as not loaded to prevent it from participating in the layout.
1597 */ 1646 */
1598 Mosaic.Tile.prototype.markUnloaded = function() { 1647 Mosaic.Tile.prototype.markUnloaded = function() {
1599 this.maxContentHeight_ = 0; 1648 this.maxContentHeight_ = 0;
1649 if (this.thumbnailLoader_) {
1650 this.thumbnailLoader_.cancel();
1651 this.imageLoaded_ = false;
1652 this.imageLoading_ = false;
1653 }
1600 }; 1654 };
1601 1655
1602 /** 1656 /**
1603 * Load the thumbnail image into the tile. 1657 * Initializes the thumbnail in the tile. Does not load an image, but sets
1658 * target dimensions using metadata.
1604 * 1659 *
1605 * @param {Object} metadata Metadata object. 1660 * @param {Object} metadata Metadata object.
1606 * @param {function} callback Completion callback. 1661 * @param {function} onImageMeasured Image measured callback.
1607 */ 1662 */
1608 Mosaic.Tile.prototype.load = function(metadata, callback) { 1663 Mosaic.Tile.prototype.init = function(metadata, onImageMeasured) {
1609 this.markUnloaded(); 1664 this.markUnloaded();
1610 this.left_ = null; // Mark as not laid out. 1665 this.left_ = null; // Mark as not laid out.
1611 1666
1612 this.thumbnailLoader_ = new ThumbnailLoader(this.getItem().getUrl(), 1667 this.thumbnailLoader_ = new ThumbnailLoader(
1613 ThumbnailLoader.LoaderType.CANVAS, 1668 this.getItem().getUrl(),
1614 metadata); 1669 ThumbnailLoader.LoaderType.CANVAS,
1670 metadata,
1671 undefined, // Media type.
1672 ThumbnailLoader.UseEmbedded.NO_EMBEDDED);
1615 1673
1674 var setDimensions = function(width, height) {
1675 if (width > height) {
1676 if (width > Mosaic.Tile.MAX_CONTENT_SIZE) {
1677 height = Math.round(height * Mosaic.Tile.MAX_CONTENT_SIZE / width);
1678 width = Mosaic.Tile.MAX_CONTENT_SIZE;
1679 }
1680 } else {
1681 if (height > Mosaic.Tile.MAX_CONTENT_SIZE) {
1682 width = Math.round(width * Mosaic.Tile.MAX_CONTENT_SIZE / height);
1683 height = Mosaic.Tile.MAX_CONTENT_SIZE;
1684 }
1685 }
1686 this.maxContentHeight_ = Math.max(Mosaic.Tile.MIN_CONTENT_SIZE, height);
1687 this.aspectRatio_ = width / height;
1688 onImageMeasured();
1689 }.bind(this);
1690
1691 // Dimensions are always acquired from the metadata. If it is not available,
1692 // then the image will not be displayed.
1693 if (metadata.media && metadata.media.width) {
1694 setDimensions(metadata.media.width, metadata.media.height);
1695 } else {
1696 // No dimensions in metadata, then display the generic icon instead.
1697 // TODO(mtomasz): Display a gneric icon instead of a black rectangle.
1698 setDimensions(Mosaic.Tile.GENERIC_ICON_SIZE,
1699 Mosaic.Tile.GENERIC_ICON_SIZE);
1700 }
1701 };
1702
1703 /**
1704 * Loads an image into the tile.
1705 *
1706 * @param {function} onImageLoaded Callback when image is loaded.
yoshiki 2013/02/26 08:21:44 Please add a function parameter.
mtomasz 2013/02/26 08:39:20 Done.
1707 * @param {function=} opt_onThumbnailError Callback for image loading error.
1708 */
1709 Mosaic.Tile.prototype.load = function(onImageLoaded, opt_onThumbnailError) {
1710 this.imageLoaded_ = false;
1711 this.imageLoading_ = true;
1616 this.thumbnailLoader_.loadDetachedImage(function(success) { 1712 this.thumbnailLoader_.loadDetachedImage(function(success) {
1617 if (this.thumbnailLoader_.hasValidImage()) { 1713 if (!success) {
1618 var width = this.thumbnailLoader_.getWidth(); 1714 if (opt_onThumbnailError)
1619 var height = this.thumbnailLoader_.getHeight(); 1715 opt_onThumbnailError();
1620 if (width > height) {
1621 if (width > Mosaic.Tile.MAX_CONTENT_SIZE) {
1622 height = Math.round(height * Mosaic.Tile.MAX_CONTENT_SIZE / width);
1623 width = Mosaic.Tile.MAX_CONTENT_SIZE;
1624 }
1625 } else {
1626 if (height > Mosaic.Tile.MAX_CONTENT_SIZE) {
1627 width = Math.round(width * Mosaic.Tile.MAX_CONTENT_SIZE / height);
1628 height = Mosaic.Tile.MAX_CONTENT_SIZE;
1629 }
1630 }
1631 this.maxContentHeight_ = Math.max(Mosaic.Tile.MIN_CONTENT_SIZE, height);
1632 this.aspectRatio_ = width / height;
1633 } else {
1634 this.maxContentHeight_ = Mosaic.Tile.GENERIC_ICON_SIZE;
1635 this.aspectRatio_ = 1;
1636 } 1716 }
1637 1717 if (this.wrapper_) {
1638 callback(success); 1718 this.thumbnailLoader_.attachImage(this.wrapper_,
1719 ThumbnailLoader.FillMode.FILL);
1720 }
1721 onImageLoaded(success);
1722 this.imageLoaded_ = true;
1723 this.imageLoading_ = false;
1639 }.bind(this)); 1724 }.bind(this));
1640 }; 1725 };
1641 1726
1642 /** 1727 /**
1643 * Select/unselect the tile. 1728 * Select/unselect the tile.
1644 * 1729 *
1645 * @param {boolean} on True if selected. 1730 * @param {boolean} on True if selected.
1646 */ 1731 */
1647 Mosaic.Tile.prototype.select = function(on) { 1732 Mosaic.Tile.prototype.select = function(on) {
1648 if (on) 1733 if (on)
(...skipping 22 matching lines...) Expand all
1671 this.style.height = height + 'px'; 1756 this.style.height = height + 'px';
1672 1757
1673 if (!this.wrapper_) { // First time, create DOM. 1758 if (!this.wrapper_) { // First time, create DOM.
1674 this.container_.appendChild(this); 1759 this.container_.appendChild(this);
1675 var border = util.createChild(this, 'img-border'); 1760 var border = util.createChild(this, 'img-border');
1676 this.wrapper_ = util.createChild(border, 'img-wrapper'); 1761 this.wrapper_ = util.createChild(border, 'img-wrapper');
1677 } 1762 }
1678 if (this.hasAttribute('selected')) 1763 if (this.hasAttribute('selected'))
1679 this.scrollIntoView(false); 1764 this.scrollIntoView(false);
1680 1765
1681 this.thumbnailLoader_.attachImage(this.wrapper_, 1766 if (this.imageLoaded_) {
1682 ThumbnailLoader.FillMode.FILL); 1767 this.thumbnailLoader_.attachImage(this.wrapper_,
1768 ThumbnailLoader.FillMode.FILL);
1769 }
1683 }; 1770 };
1684 1771
1685 /** 1772 /**
1686 * If the tile is not fully visible scroll the parent to make it fully visible. 1773 * If the tile is not fully visible scroll the parent to make it fully visible.
1687 * @param {boolean=} opt_animated True, if scroll should be animated, 1774 * @param {boolean=} opt_animated True, if scroll should be animated,
1688 * default: true. 1775 * default: true.
1689 */ 1776 */
1690 Mosaic.Tile.prototype.scrollIntoView = function(opt_animated) { 1777 Mosaic.Tile.prototype.scrollIntoView = function(opt_animated) {
1691 if (this.left_ == null) // Not laid out. 1778 if (this.left_ == null) // Not laid out.
1692 return; 1779 return;
(...skipping 29 matching lines...) Expand all
1722 return new Rect(this.left_ - this.container_.scrollLeft, this.top_, 1809 return new Rect(this.left_ - this.container_.scrollLeft, this.top_,
1723 this.width_, this.height_).inflate(-margin, -margin); 1810 this.width_, this.height_).inflate(-margin, -margin);
1724 }; 1811 };
1725 1812
1726 /** 1813 /**
1727 * @return {number} X coordinate of the tile center. 1814 * @return {number} X coordinate of the tile center.
1728 */ 1815 */
1729 Mosaic.Tile.prototype.getCenterX = function() { 1816 Mosaic.Tile.prototype.getCenterX = function() {
1730 return this.left_ + Math.round(this.width_ / 2); 1817 return this.left_ + Math.round(this.width_ / 2);
1731 }; 1818 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698