Commit fcdfa398 authored by yawano's avatar yawano Committed by Commit bot

Add type annotations to gallery/js/mosaic_mode.js.

BUG=433728
TEST=GYP_GENERATORS=ninja tools/gyp/gyp --depth . ui/file_manager/gallery/js/compiled_resources.gyp && ninja -C out/Default | grep "gallery/js/mosaic_mode.js"

Review URL: https://codereview.chromium.org/805723003

Cr-Commit-Position: refs/heads/master@{#308320}
parent 69273a46
...@@ -3,18 +3,19 @@ ...@@ -3,18 +3,19 @@
// found in the LICENSE file. // found in the LICENSE file.
/** /**
* @param {Element} container Content container. * @param {!Element} container Content container.
* @param {ErrorBanner} errorBanner Error banner. * @param {!ErrorBanner} errorBanner Error banner.
* @param {cr.ui.ArrayDataModel} dataModel Data model. * @param {!cr.ui.ArrayDataModel} dataModel Data model.
* @param {cr.ui.ListSelectionModel} selectionModel Selection model. * @param {!cr.ui.ListSelectionModel} selectionModel Selection model.
* @param {!VolumeManager} volumeManager Volume manager. * @param {!VolumeManager} volumeManager Volume manager.
* @param {function()} toggleMode Function to switch to the Slide mode. * @param {function()} toggleMode Function to switch to the Slide mode.
* @constructor * @constructor
* @struct
*/ */
function MosaicMode( function MosaicMode(
container, errorBanner, dataModel, selectionModel, volumeManager, container, errorBanner, dataModel, selectionModel, volumeManager,
toggleMode) { toggleMode) {
this.mosaic_ = new Mosaic(container.ownerDocument, errorBanner, this.mosaic_ = new Mosaic(assert(container.ownerDocument), errorBanner,
dataModel, selectionModel, volumeManager); dataModel, selectionModel, volumeManager);
container.appendChild(this.mosaic_); container.appendChild(this.mosaic_);
...@@ -24,7 +25,7 @@ function MosaicMode( ...@@ -24,7 +25,7 @@ function MosaicMode(
} }
/** /**
* @return {Mosaic} The mosaic control. * @return {!Mosaic} The mosaic control.
*/ */
MosaicMode.prototype.getMosaic = function() { return this.mosaic_; }; MosaicMode.prototype.getMosaic = function() { return this.mosaic_; };
...@@ -52,7 +53,7 @@ MosaicMode.prototype.hasActiveTool = function() { return true; }; ...@@ -52,7 +53,7 @@ MosaicMode.prototype.hasActiveTool = function() { return true; };
/** /**
* Keydown handler. * Keydown handler.
* *
* @param {Event} event Event. * @param {!Event} event Event.
*/ */
MosaicMode.prototype.onKeyDown = function(event) { MosaicMode.prototype.onKeyDown = function(event) {
switch (util.getKeyModifiers(event) + event.keyIdentifier) { switch (util.getKeyModifiers(event) + event.keyIdentifier) {
...@@ -72,17 +73,20 @@ MosaicMode.prototype.onKeyDown = function(event) { ...@@ -72,17 +73,20 @@ MosaicMode.prototype.onKeyDown = function(event) {
/** /**
* Mosaic control. * Mosaic control.
* *
* @param {Document} document Document. * @param {!Document} document Document.
* @param {ErrorBanner} errorBanner Error banner. * @param {!ErrorBanner} errorBanner Error banner.
* @param {cr.ui.ArrayDataModel} dataModel Data model. * @param {!cr.ui.ArrayDataModel} dataModel Data model.
* @param {cr.ui.ListSelectionModel} selectionModel Selection model. * @param {!cr.ui.ListSelectionModel} selectionModel Selection model.
* @param {VolumeManagerWrapper} volumeManager Volume manager. * @param {!VolumeManager} volumeManager Volume manager.
* @return {Element} Mosaic element. * @return {!Element} Mosaic element.
* @constructor * @constructor
* @struct
* @extends {HTMLDivElement}
* @suppress {checkStructDictInheritance}
*/ */
function Mosaic(document, errorBanner, dataModel, selectionModel, function Mosaic(document, errorBanner, dataModel, selectionModel,
volumeManager) { volumeManager) {
var self = document.createElement('div'); var self = assertInstanceof(document.createElement('div'), HTMLDivElement);
Mosaic.decorate(self, errorBanner, dataModel, selectionModel, volumeManager); Mosaic.decorate(self, errorBanner, dataModel, selectionModel, volumeManager);
return self; return self;
} }
...@@ -110,15 +114,16 @@ Mosaic.ANIMATED_SCROLL_DURATION = 500; ...@@ -110,15 +114,16 @@ Mosaic.ANIMATED_SCROLL_DURATION = 500;
/** /**
* Decorates a Mosaic instance. * Decorates a Mosaic instance.
* *
* @param {Mosaic} self Self pointer. * @param {!HTMLDivElement} self Self pointer.
* @param {ErrorBanner} errorBanner Error banner. * @param {!ErrorBanner} errorBanner Error banner.
* @param {cr.ui.ArrayDataModel} dataModel Data model. * @param {!cr.ui.ArrayDataModel} dataModel Data model.
* @param {cr.ui.ListSelectionModel} selectionModel Selection model. * @param {!cr.ui.ListSelectionModel} selectionModel Selection model.
* @param {VolumeManagerWrapper} volumeManager Volume manager. * @param {!VolumeManager} volumeManager Volume manager.
*/ */
Mosaic.decorate = function( Mosaic.decorate = function(
self, errorBanner, dataModel, selectionModel, volumeManager) { self, errorBanner, dataModel, selectionModel, volumeManager) {
self.__proto__ = Mosaic.prototype; self.__proto__ = Mosaic.prototype;
self = /** @type {!Mosaic} */ (self);
self.className = 'mosaic'; self.className = 'mosaic';
self.dataModel_ = dataModel; self.dataModel_ = dataModel;
...@@ -126,6 +131,60 @@ Mosaic.decorate = function( ...@@ -126,6 +131,60 @@ Mosaic.decorate = function(
self.volumeManager_ = volumeManager; self.volumeManager_ = volumeManager;
self.errorBanner_ = errorBanner; self.errorBanner_ = errorBanner;
/**
* @type {Array.<!Mosaic.Tile>}
* @private
*/
self.tiles_ = null;
/**
* @type {boolean}
* @private
*/
self.loadVisibleTilesSuppressed_ = false;
/**
* @type {boolean}
* @private
*/
self.loadVisibleTilesScheduled_ = false;
/**
* @type {number}
* @private
*/
self.showingTimeoutID_ = 0;
/**
* @type {Mosaic.SelectionController}
* @private
*/
self.selectionController_ = null;
/**
* @type {Mosaic.Layout}
* @private
*/
self.layoutModel_ = null;
/**
* @type {boolean}
* @private
*/
self.suppressHovering_ = false;
/**
* @type {number}
* @private
*/
self.layoutTimer_ = 0;
/**
* @type {number}
* @private
*/
self.scrollAnimation_ = 0;
// Initialization is completed lazily on the first call to |init|. // Initialization is completed lazily on the first call to |init|.
}; };
...@@ -201,7 +260,7 @@ Mosaic.prototype.initListeners_ = function() { ...@@ -201,7 +260,7 @@ Mosaic.prototype.initListeners_ = function() {
Mosaic.prototype.animatedScrollTo = function(targetPosition) { Mosaic.prototype.animatedScrollTo = function(targetPosition) {
if (this.scrollAnimation_) { if (this.scrollAnimation_) {
webkitCancelAnimationFrame(this.scrollAnimation_); webkitCancelAnimationFrame(this.scrollAnimation_);
this.scrollAnimation_ = null; this.scrollAnimation_ = 0;
} }
// Mouse move events are fired without touching the mouse because of scrolling // Mouse move events are fired without touching the mouse because of scrolling
...@@ -270,10 +329,10 @@ Mosaic.prototype.getTileRect = function(index) { ...@@ -270,10 +329,10 @@ Mosaic.prototype.getTileRect = function(index) {
}; };
/** /**
* @param {number} index Tile index.
* Scroll the given tile into the viewport. * Scroll the given tile into the viewport.
* @param {number} index Tile index.
*/ */
Mosaic.prototype.scrollIntoView = function(index) { Mosaic.prototype.scrollIntoViewByIndex = function(index) {
var tile = this.tiles_[index]; var tile = this.tiles_[index];
if (tile) tile.scrollIntoView(); if (tile) tile.scrollIntoView();
}; };
...@@ -281,7 +340,7 @@ Mosaic.prototype.scrollIntoView = function(index) { ...@@ -281,7 +340,7 @@ Mosaic.prototype.scrollIntoView = function(index) {
/** /**
* Initializes multiple tiles. * Initializes multiple tiles.
* *
* @param {Array.<Mosaic.Tile>} tiles Array of tiles. * @param {!Array.<!Mosaic.Tile>} tiles Array of tiles.
* @private * @private
*/ */
Mosaic.prototype.initTiles_ = function(tiles) { Mosaic.prototype.initTiles_ = function(tiles) {
...@@ -308,7 +367,7 @@ Mosaic.prototype.reload = function() { ...@@ -308,7 +367,7 @@ Mosaic.prototype.reload = function() {
Mosaic.prototype.layout = function() { Mosaic.prototype.layout = function() {
if (this.layoutTimer_) { if (this.layoutTimer_) {
clearTimeout(this.layoutTimer_); clearTimeout(this.layoutTimer_);
this.layoutTimer_ = null; this.layoutTimer_ = 0;
} }
while (true) { while (true) {
var index = this.layoutModel_.getTileCount(); var index = this.layoutModel_.getTileCount();
...@@ -330,7 +389,7 @@ Mosaic.prototype.layout = function() { ...@@ -330,7 +389,7 @@ Mosaic.prototype.layout = function() {
Mosaic.prototype.scheduleLayout = function(opt_delay) { Mosaic.prototype.scheduleLayout = function(opt_delay) {
if (!this.layoutTimer_) { if (!this.layoutTimer_) {
this.layoutTimer_ = setTimeout(function() { this.layoutTimer_ = setTimeout(function() {
this.layoutTimer_ = null; this.layoutTimer_ = 0;
this.layout(); this.layout();
}.bind(this), opt_delay || 0); }.bind(this), opt_delay || 0);
} }
...@@ -350,7 +409,7 @@ Mosaic.prototype.onResize_ = function() { ...@@ -350,7 +409,7 @@ Mosaic.prototype.onResize_ = function() {
/** /**
* Mouse event handler. * Mouse event handler.
* *
* @param {Event} event Event. * @param {!Event} event Event.
* @private * @private
*/ */
Mosaic.prototype.onMouseEvent_ = function(event) { Mosaic.prototype.onMouseEvent_ = function(event) {
...@@ -386,7 +445,7 @@ Mosaic.prototype.onScroll_ = function() { ...@@ -386,7 +445,7 @@ Mosaic.prototype.onScroll_ = function() {
/** /**
* Selection change handler. * Selection change handler.
* *
* @param {Event} event Event. * @param {!Event} event Event.
* @private * @private
*/ */
Mosaic.prototype.onSelection_ = function(event) { Mosaic.prototype.onSelection_ = function(event) {
...@@ -400,7 +459,7 @@ Mosaic.prototype.onSelection_ = function(event) { ...@@ -400,7 +459,7 @@ Mosaic.prototype.onSelection_ = function(event) {
/** /**
* Leads item change handler. * Leads item change handler.
* *
* @param {Event} event Event. * @param {!Event} event Event.
* @private * @private
*/ */
Mosaic.prototype.onLeadChange_ = function(event) { Mosaic.prototype.onLeadChange_ = function(event) {
...@@ -414,7 +473,7 @@ Mosaic.prototype.onLeadChange_ = function(event) { ...@@ -414,7 +473,7 @@ Mosaic.prototype.onLeadChange_ = function(event) {
/** /**
* Splice event handler. * Splice event handler.
* *
* @param {Event} event Event. * @param {!Event} event Event.
* @private * @private
*/ */
Mosaic.prototype.onSplice_ = function(event) { Mosaic.prototype.onSplice_ = function(event) {
...@@ -456,7 +515,7 @@ Mosaic.prototype.onSplice_ = function(event) { ...@@ -456,7 +515,7 @@ Mosaic.prototype.onSplice_ = function(event) {
/** /**
* Content change handler. * Content change handler.
* *
* @param {Event} event Event. * @param {!Event} event Event.
* @private * @private
*/ */
Mosaic.prototype.onContentChange_ = function(event) { Mosaic.prototype.onContentChange_ = function(event) {
...@@ -481,7 +540,7 @@ Mosaic.prototype.onContentChange_ = function(event) { ...@@ -481,7 +540,7 @@ Mosaic.prototype.onContentChange_ = function(event) {
/** /**
* Keydown event handler. * Keydown event handler.
* *
* @param {Event} event Event. * @param {!Event} event Event.
* @return {boolean} True if the event has been consumed. * @return {boolean} True if the event has been consumed.
*/ */
Mosaic.prototype.onKeyDown = function(event) { Mosaic.prototype.onKeyDown = function(event) {
...@@ -518,7 +577,7 @@ Mosaic.prototype.show = function() { ...@@ -518,7 +577,7 @@ Mosaic.prototype.show = function() {
duration -= 100; duration -= 100;
} }
this.showingTimeoutID_ = setTimeout(function() { this.showingTimeoutID_ = setTimeout(function() {
this.showingTimeoutID_ = null; this.showingTimeoutID_ = 0;
// Make the selection visible. // Make the selection visible.
// If the mosaic is not animated it will start fading in now. // If the mosaic is not animated it will start fading in now.
this.setAttribute('visible', 'normal'); this.setAttribute('visible', 'normal');
...@@ -532,9 +591,9 @@ Mosaic.prototype.show = function() { ...@@ -532,9 +591,9 @@ Mosaic.prototype.show = function() {
Mosaic.prototype.hide = function() { Mosaic.prototype.hide = function() {
this.errorBanner_.clear(); this.errorBanner_.clear();
if (this.showingTimeoutID_ !== null) { if (this.showingTimeoutID_ !== 0) {
clearTimeout(this.showingTimeoutID_); clearTimeout(this.showingTimeoutID_);
this.showingTimeoutID_ = null; this.showingTimeoutID_ = 0;
} }
this.removeAttribute('visible'); this.removeAttribute('visible');
}; };
...@@ -660,11 +719,13 @@ Mosaic.prototype.getItemCount_ = function() { ...@@ -660,11 +719,13 @@ Mosaic.prototype.getItemCount_ = function() {
/** /**
* Creates a selection controller that is to be used with grid. * Creates a selection controller that is to be used with grid.
* @param {cr.ui.ListSelectionModel} selectionModel The selection model to * @param {!cr.ui.ListSelectionModel} selectionModel The selection model to
* interact with. * interact with.
* @param {Mosaic.Layout} layoutModel The layout model to use. * @param {!Mosaic.Layout} layoutModel The layout model to use.
* @constructor * @constructor
* @extends {!cr.ui.ListSelectionController} * @struct
* @extends {cr.ui.ListSelectionController}
* @suppress {checkStructDictInheritance}
*/ */
Mosaic.SelectionController = function(selectionModel, layoutModel) { Mosaic.SelectionController = function(selectionModel, layoutModel) {
cr.ui.ListSelectionController.call(this, selectionModel); cr.ui.ListSelectionController.call(this, selectionModel);
...@@ -710,51 +771,89 @@ Mosaic.SelectionController.prototype.getIndexBelow = function(index) { ...@@ -710,51 +771,89 @@ Mosaic.SelectionController.prototype.getIndexBelow = function(index) {
* @param {string=} opt_mode Layout mode. * @param {string=} opt_mode Layout mode.
* @param {Mosaic.Density=} opt_maxDensity Layout density. * @param {Mosaic.Density=} opt_maxDensity Layout density.
* @constructor * @constructor
* @struct
*/ */
Mosaic.Layout = function(opt_mode, opt_maxDensity) { Mosaic.Layout = function(opt_mode, opt_maxDensity) {
this.mode_ = opt_mode || Mosaic.Layout.MODE_TENTATIVE; this.mode_ = opt_mode || Mosaic.Layout.Mode.TENTATIVE;
this.maxDensity_ = opt_maxDensity || Mosaic.Density.createHighest(); this.maxDensity_ = opt_maxDensity || Mosaic.Density.createHighest();
/**
* @type {!Array.<!Mosaic.Column>}
* @private
*/
this.columns_ = [];
/**
* @type {Mosaic.Column}
* @private
*/
this.newColumn_ = null;
/**
* @type {number}
* @private
*/
this.viewportWidth_ = 0;
/**
* @type {number}
* @private
*/
this.viewportHeight_ = 0;
/**
* @type {Mosaic.Density}
* @private
*/
this.density_ = null;
this.reset_(); this.reset_();
}; };
/** /**
* Blank space at the top of the mosaic element. We do not do that in CSS * Blank space at the top of the mosaic element. We do not do that in CSS
* to make transition effects easier. * to make transition effects easier.
* @type {number}
* @const
*/ */
Mosaic.Layout.PADDING_TOP = 50; Mosaic.Layout.PADDING_TOP = 50;
/** /**
* Blank space at the bottom of the mosaic element. * Blank space at the bottom of the mosaic element.
* @type {number}
* @const
*/ */
Mosaic.Layout.PADDING_BOTTOM = 50; Mosaic.Layout.PADDING_BOTTOM = 50;
/** /**
* Horizontal and vertical spacing between images. Should be kept in sync * Horizontal and vertical spacing between images. Should be kept in sync
* with the style of .mosaic-item in gallery.css (= 2 * ( 4 + 1)) * with the style of .mosaic-item in gallery.css (= 2 * ( 4 + 1))
* @type {number}
* @const
*/ */
Mosaic.Layout.SPACING = 10; Mosaic.Layout.SPACING = 10;
/** /**
* Margin for scrolling using keyboard. Distance between a selected tile * Margin for scrolling using keyboard. Distance between a selected tile
* and window border. * and window border.
* @type {number}
* @const
*/ */
Mosaic.Layout.SCROLL_MARGIN = 30; Mosaic.Layout.SCROLL_MARGIN = 30;
/** /**
* Layout mode: commit to DOM immediately. * Layout mode.
* @enum {string}
*/ */
Mosaic.Layout.MODE_FINAL = 'final'; Mosaic.Layout.Mode = {
// Commit to DOM immediately.
/** FINAL: 'final',
* Layout mode: do not commit layout to DOM until it is complete or the viewport // Do not commit layout to DOM until it is complete or the viewport
* overflows. // overflows.
*/ TENTATIVE: 'tentative',
Mosaic.Layout.MODE_TENTATIVE = 'tentative'; // Never commit layout to DOM.
DRY_RUN: 'dry_run',
/** };
* Layout mode: never commit layout to DOM.
*/
Mosaic.Layout.MODE_DRY_RUN = 'dry_run';
/** /**
* Resets the layout. * Resets the layout.
...@@ -765,8 +864,8 @@ Mosaic.Layout.prototype.reset_ = function() { ...@@ -765,8 +864,8 @@ Mosaic.Layout.prototype.reset_ = function() {
this.columns_ = []; this.columns_ = [];
this.newColumn_ = null; this.newColumn_ = null;
this.density_ = Mosaic.Density.createLowest(); this.density_ = Mosaic.Density.createLowest();
if (this.mode_ !== Mosaic.Layout.MODE_DRY_RUN) // DRY_RUN is sticky. if (this.mode_ !== Mosaic.Layout.Mode.DRY_RUN) // DRY_RUN is sticky.
this.mode_ = Mosaic.Layout.MODE_TENTATIVE; this.mode_ = Mosaic.Layout.Mode.TENTATIVE;
}; };
/** /**
...@@ -796,7 +895,7 @@ Mosaic.Layout.prototype.getHeight = function() { ...@@ -796,7 +895,7 @@ Mosaic.Layout.prototype.getHeight = function() {
}; };
/** /**
* @return {Array.<Mosaic.Tile>} All tiles in the layout. * @return {!Array.<!Mosaic.Tile>} All tiles in the layout.
*/ */
Mosaic.Layout.prototype.getTiles = function() { Mosaic.Layout.prototype.getTiles = function() {
return Array.prototype.concat.apply([], return Array.prototype.concat.apply([],
...@@ -830,7 +929,7 @@ Mosaic.Layout.prototype.getLaidOutTileCount = function() { ...@@ -830,7 +929,7 @@ Mosaic.Layout.prototype.getLaidOutTileCount = function() {
/** /**
* Adds a tile to the layout. * Adds a tile to the layout.
* *
* @param {Mosaic.Tile} tile The tile to be added. * @param {!Mosaic.Tile} tile The tile to be added.
* @param {boolean} isLast True if this tile is the last. * @param {boolean} isLast True if this tile is the last.
*/ */
Mosaic.Layout.prototype.add = function(tile, isLast) { Mosaic.Layout.prototype.add = function(tile, isLast) {
...@@ -876,7 +975,7 @@ Mosaic.Layout.prototype.add = function(tile, isLast) { ...@@ -876,7 +975,7 @@ Mosaic.Layout.prototype.add = function(tile, isLast) {
this.columns_.push(this.newColumn_); this.columns_.push(this.newColumn_);
this.newColumn_ = null; this.newColumn_ = null;
if (this.mode_ === Mosaic.Layout.MODE_FINAL && isFinalColumn) { if (this.mode_ === Mosaic.Layout.Mode.FINAL && isFinalColumn) {
this.commit_(); this.commit_();
continue; continue;
} }
...@@ -885,7 +984,7 @@ Mosaic.Layout.prototype.add = function(tile, isLast) { ...@@ -885,7 +984,7 @@ Mosaic.Layout.prototype.add = function(tile, isLast) {
// Viewport completely filled. // Viewport completely filled.
if (this.density_.equals(this.maxDensity_)) { if (this.density_.equals(this.maxDensity_)) {
// Max density reached, commit if tentative, just continue if dry run. // Max density reached, commit if tentative, just continue if dry run.
if (this.mode_ === Mosaic.Layout.MODE_TENTATIVE) if (this.mode_ === Mosaic.Layout.Mode.TENTATIVE)
this.commit_(); this.commit_();
continue; continue;
} }
...@@ -897,7 +996,7 @@ Mosaic.Layout.prototype.add = function(tile, isLast) { ...@@ -897,7 +996,7 @@ Mosaic.Layout.prototype.add = function(tile, isLast) {
continue; continue;
} }
if (isFinalColumn && this.mode_ === Mosaic.Layout.MODE_TENTATIVE) { if (isFinalColumn && this.mode_ === Mosaic.Layout.Mode.TENTATIVE) {
// The complete tentative layout fits into the viewport. // The complete tentative layout fits into the viewport.
var stretched = this.findHorizontalLayout_(); var stretched = this.findHorizontalLayout_();
if (stretched) if (stretched)
...@@ -920,7 +1019,7 @@ Mosaic.Layout.prototype.commit_ = function(opt_offsetX, opt_offsetY) { ...@@ -920,7 +1019,7 @@ Mosaic.Layout.prototype.commit_ = function(opt_offsetX, opt_offsetY) {
for (var i = 0; i !== this.columns_.length; i++) { for (var i = 0; i !== this.columns_.length; i++) {
this.columns_[i].layout(opt_offsetX, opt_offsetY); this.columns_[i].layout(opt_offsetX, opt_offsetY);
} }
this.mode_ = Mosaic.Layout.MODE_FINAL; this.mode_ = Mosaic.Layout.Mode.FINAL;
}; };
/** /**
...@@ -952,7 +1051,7 @@ Mosaic.Layout.prototype.findHorizontalLayout_ = function() { ...@@ -952,7 +1051,7 @@ Mosaic.Layout.prototype.findHorizontalLayout_ = function() {
for (var h = minTileHeight; h < this.viewportHeight_; h += minTileHeight) { for (var h = minTileHeight; h < this.viewportHeight_; h += minTileHeight) {
var layout = new Mosaic.Layout( var layout = new Mosaic.Layout(
Mosaic.Layout.MODE_DRY_RUN, this.density_.clone()); Mosaic.Layout.Mode.DRY_RUN, this.density_.clone());
layout.setViewportSize(this.viewportWidth_, h); layout.setViewportSize(this.viewportWidth_, h);
for (var t = 0; t !== tiles.length; t++) for (var t = 0; t !== tiles.length; t++)
layout.add(tiles[t], t + 1 === tiles.length); layout.add(tiles[t], t + 1 === tiles.length);
...@@ -980,14 +1079,14 @@ Mosaic.Layout.prototype.invalidateFromTile_ = function(index) { ...@@ -980,14 +1079,14 @@ Mosaic.Layout.prototype.invalidateFromTile_ = function(index) {
// The columns to the right cover the entire viewport width, so there is no // The columns to the right cover the entire viewport width, so there is no
// chance that the modified layout would fit into the viewport. // chance that the modified layout would fit into the viewport.
// No point in restarting the entire layout, keep the columns to the right. // No point in restarting the entire layout, keep the columns to the right.
console.assert(this.mode_ === Mosaic.Layout.MODE_FINAL, console.assert(this.mode_ === Mosaic.Layout.Mode.FINAL,
'Expected FINAL layout mode'); 'Expected FINAL layout mode');
this.columns_ = this.columns_.slice(0, columnIndex); this.columns_ = this.columns_.slice(0, columnIndex);
this.newColumn_ = null; this.newColumn_ = null;
} else { } else {
// There is a chance that the modified layout would fit into the viewport. // There is a chance that the modified layout would fit into the viewport.
this.reset_(); this.reset_();
this.mode_ = Mosaic.Layout.MODE_TENTATIVE; this.mode_ = Mosaic.Layout.Mode.TENTATIVE;
} }
}; };
...@@ -1099,7 +1198,7 @@ Mosaic.Layout.prototype.getColumnIndexByTile_ = function(index) { ...@@ -1099,7 +1198,7 @@ Mosaic.Layout.prototype.getColumnIndexByTile_ = function(index) {
* 3. The relative proportions of the sizes should be as close to the original * 3. The relative proportions of the sizes should be as close to the original
* as possible. * as possible.
* *
* @param {Array.<number>} sizes Array of sizes. * @param {!Array.<number>} sizes Array of sizes.
* @param {number} newTotal New total size. * @param {number} newTotal New total size.
*/ */
Mosaic.Layout.rescaleSizesToNewTotal = function(sizes, newTotal) { Mosaic.Layout.rescaleSizesToNewTotal = function(sizes, newTotal) {
...@@ -1128,6 +1227,7 @@ Mosaic.Layout.rescaleSizesToNewTotal = function(sizes, newTotal) { ...@@ -1128,6 +1227,7 @@ Mosaic.Layout.rescaleSizesToNewTotal = function(sizes, newTotal) {
* @param {number} vertical Vertical density, frequency of rows forced to * @param {number} vertical Vertical density, frequency of rows forced to
* contain a single tile. * contain a single tile.
* @constructor * @constructor
* @struct
*/ */
Mosaic.Density = function(horizontal, vertical) { Mosaic.Density = function(horizontal, vertical) {
this.horizontal = horizontal; this.horizontal = horizontal;
...@@ -1136,26 +1236,34 @@ Mosaic.Density = function(horizontal, vertical) { ...@@ -1136,26 +1236,34 @@ Mosaic.Density = function(horizontal, vertical) {
/** /**
* Minimal horizontal density (tiles per row). * Minimal horizontal density (tiles per row).
* @type {number}
* @const
*/ */
Mosaic.Density.MIN_HORIZONTAL = 1; Mosaic.Density.MIN_HORIZONTAL = 1;
/** /**
* Minimal horizontal density (tiles per row). * Minimal horizontal density (tiles per row).
* @type {number}
* @const
*/ */
Mosaic.Density.MAX_HORIZONTAL = 3; Mosaic.Density.MAX_HORIZONTAL = 3;
/** /**
* Minimal vertical density: force 1 out of 2 rows to containt a single tile. * Minimal vertical density: force 1 out of 2 rows to containt a single tile.
* @type {number}
* @const
*/ */
Mosaic.Density.MIN_VERTICAL = 2; Mosaic.Density.MIN_VERTICAL = 2;
/** /**
* Maximal vertical density: force 1 out of 3 rows to containt a single tile. * Maximal vertical density: force 1 out of 3 rows to containt a single tile.
* @type {number}
* @const
*/ */
Mosaic.Density.MAX_VERTICAL = 3; Mosaic.Density.MAX_VERTICAL = 3;
/** /**
* @return {Mosaic.Density} Lowest density. * @return {!Mosaic.Density} Lowest density.
*/ */
Mosaic.Density.createLowest = function() { Mosaic.Density.createLowest = function() {
return new Mosaic.Density( return new Mosaic.Density(
...@@ -1164,7 +1272,7 @@ Mosaic.Density.createLowest = function() { ...@@ -1164,7 +1272,7 @@ Mosaic.Density.createLowest = function() {
}; };
/** /**
* @return {Mosaic.Density} Highest density. * @return {!Mosaic.Density} Highest density.
*/ */
Mosaic.Density.createHighest = function() { Mosaic.Density.createHighest = function() {
return new Mosaic.Density( return new Mosaic.Density(
...@@ -1173,14 +1281,14 @@ Mosaic.Density.createHighest = function() { ...@@ -1173,14 +1281,14 @@ Mosaic.Density.createHighest = function() {
}; };
/** /**
* @return {Mosaic.Density} A clone of this density object. * @return {!Mosaic.Density} A clone of this density object.
*/ */
Mosaic.Density.prototype.clone = function() { Mosaic.Density.prototype.clone = function() {
return new Mosaic.Density(this.horizontal, this.vertical); return new Mosaic.Density(this.horizontal, this.vertical);
}; };
/** /**
* @param {Mosaic.Density} that The other object. * @param {!Mosaic.Density} that The other object.
* @return {boolean} True if equal. * @return {boolean} True if equal.
*/ */
Mosaic.Density.prototype.equals = function(that) { Mosaic.Density.prototype.equals = function(that) {
...@@ -1229,8 +1337,9 @@ Mosaic.Density.prototype.isRowComplete = function(tileCount, rowIndex) { ...@@ -1229,8 +1337,9 @@ Mosaic.Density.prototype.isRowComplete = function(tileCount, rowIndex) {
* @param {number} firstTileIndex Index of the first tile in the column. * @param {number} firstTileIndex Index of the first tile in the column.
* @param {number} left Left edge coordinate. * @param {number} left Left edge coordinate.
* @param {number} maxHeight Maximum height. * @param {number} maxHeight Maximum height.
* @param {Mosaic.Density} density Layout density. * @param {!Mosaic.Density} density Layout density.
* @constructor * @constructor
* @struct
*/ */
Mosaic.Column = function(index, firstRowIndex, firstTileIndex, left, maxHeight, Mosaic.Column = function(index, firstRowIndex, firstTileIndex, left, maxHeight,
density) { density) {
...@@ -1241,6 +1350,42 @@ Mosaic.Column = function(index, firstRowIndex, firstTileIndex, left, maxHeight, ...@@ -1241,6 +1350,42 @@ Mosaic.Column = function(index, firstRowIndex, firstTileIndex, left, maxHeight,
this.maxHeight_ = maxHeight; this.maxHeight_ = maxHeight;
this.density_ = density; this.density_ = density;
/**
* @type {number}
* @private
*/
this.width_ = 0;
/**
* @type {!Array.<!Mosaic.Tile>}
* @private
*/
this.tiles_ = [];
/**
* @type {!Array.<!Mosaic.Row>}
* @private
*/
this.rows_ = [];
/**
* @type {Mosaic.Row}
* @private
*/
this.newRow_ = null;
/**
* @type {!Array.<number>}
* @private
*/
this.rowHeights_ = [];
/**
* @type {number}
* @private
*/
this.height_ = 0;
this.reset_(); this.reset_();
}; };
...@@ -1274,7 +1419,7 @@ Mosaic.Column.prototype.getNextRowIndex = function() { ...@@ -1274,7 +1419,7 @@ Mosaic.Column.prototype.getNextRowIndex = function() {
}; };
/** /**
* @return {Array.<Mosaic.Tile>} Array of tiles in the column. * @return {!Array.<!Mosaic.Tile>} Array of tiles in the column.
*/ */
Mosaic.Column.prototype.getTiles = function() { return this.tiles_ }; Mosaic.Column.prototype.getTiles = function() { return this.tiles_ };
...@@ -1317,7 +1462,7 @@ Mosaic.Column.prototype.getRowByTileIndex = function(index) { ...@@ -1317,7 +1462,7 @@ Mosaic.Column.prototype.getRowByTileIndex = function(index) {
/** /**
* Adds a tile to the column. * Adds a tile to the column.
* *
* @param {Mosaic.Tile} tile The tile to add. * @param {!Mosaic.Tile} tile The tile to add.
*/ */
Mosaic.Column.prototype.add = function(tile) { Mosaic.Column.prototype.add = function(tile) {
var rowIndex = this.getNextRowIndex(); var rowIndex = this.getNextRowIndex();
...@@ -1461,14 +1606,27 @@ Mosaic.Column.prototype.isSuboptimal = function() { ...@@ -1461,14 +1606,27 @@ Mosaic.Column.prototype.isSuboptimal = function() {
* *
* @param {number} firstTileIndex Index of the first tile in the row. * @param {number} firstTileIndex Index of the first tile in the row.
* @constructor * @constructor
* @struct
*/ */
Mosaic.Row = function(firstTileIndex) { Mosaic.Row = function(firstTileIndex) {
this.firstTileIndex_ = firstTileIndex; this.firstTileIndex_ = firstTileIndex;
this.tiles_ = []; this.tiles_ = [];
/**
* @type {number}
* @private
*/
this.top_ = 0;
/**
* @type {number}
* @private
*/
this.height_ = 0;
}; };
/** /**
* @param {Mosaic.Tile} tile The tile to add. * @param {!Mosaic.Tile} tile The tile to add.
*/ */
Mosaic.Row.prototype.add = function(tile) { Mosaic.Row.prototype.add = function(tile) {
console.assert(this.getTileCount() < Mosaic.Density.MAX_HORIZONTAL); console.assert(this.getTileCount() < Mosaic.Density.MAX_HORIZONTAL);
...@@ -1476,7 +1634,7 @@ Mosaic.Row.prototype.add = function(tile) { ...@@ -1476,7 +1634,7 @@ Mosaic.Row.prototype.add = function(tile) {
}; };
/** /**
* @return {Array.<Mosaic.Tile>} Array of tiles in the row. * @return {!Array.<!Mosaic.Tile>} Array of tiles in the row.
*/ */
Mosaic.Row.prototype.getTiles = function() { return this.tiles_ }; Mosaic.Row.prototype.getTiles = function() { return this.tiles_ };
...@@ -1616,32 +1774,113 @@ Mosaic.Row.prototype.layout = function(left, top, width, height) { ...@@ -1616,32 +1774,113 @@ Mosaic.Row.prototype.layout = function(left, top, width, height) {
/** /**
* A single tile of the image mosaic. * A single tile of the image mosaic.
* *
* @param {Element} container Container element. * @param {!Element} container Container element.
* @param {Gallery.Item} item Gallery item associated with this tile. * @param {!Gallery.Item} item Gallery item associated with this tile.
* @param {EntryLocation} locationInfo Location information for the tile. * @param {EntryLocation=} opt_locationInfo Location information for the tile.
* @return {Element} The new tile element. * @return {!Element} The new tile element.
* @constructor * @constructor
* @extends {HTMLDivElement}
* @struct
* @suppress {checkStructDictInheritance}
*/ */
Mosaic.Tile = function(container, item, locationInfo) { Mosaic.Tile = function(container, item, opt_locationInfo) {
var self = container.ownerDocument.createElement('div'); var self = container.ownerDocument.createElement('div');
Mosaic.Tile.decorate(self, container, item, locationInfo); Mosaic.Tile.decorate(self, container, item, opt_locationInfo);
return self; return self;
}; };
/** /**
* @param {Element} self Self pointer. * @param {!Element} self Self pointer.
* @param {Element} container Container element. * @param {!Element} container Container element.
* @param {Gallery.Item} item Gallery item associated with this tile. * @param {!Gallery.Item} item Gallery item associated with this tile.
* @param {EntryLocation} locationInfo Location info for the tile image. * @param {EntryLocation=} opt_locationInfo Location info for the tile image.
*/ */
Mosaic.Tile.decorate = function(self, container, item, locationInfo) { Mosaic.Tile.decorate = function(self, container, item, opt_locationInfo) {
self.__proto__ = Mosaic.Tile.prototype; self.__proto__ = Mosaic.Tile.prototype;
self = /** @type {!Mosaic.Tile} */ (self);
self.className = 'mosaic-tile'; self.className = 'mosaic-tile';
self.container_ = container; self.container_ = container;
self.item_ = item; self.item_ = item;
self.hidpiEmbedded_ = opt_locationInfo && opt_locationInfo.isDriveBased;
/**
* @type {?number}
* @private
*/
self.left_ = null; // Mark as not laid out. self.left_ = null; // Mark as not laid out.
self.hidpiEmbedded_ = locationInfo && locationInfo.isDriveBased;
/**
* @type {number}
* @private
*/
self.top_ = 0;
/**
* @type {number}
* @private
*/
self.width_ = 0;
/**
* @type {number}
* @private
*/
self.height_ = 0;
/**
* @type {number}
* @private
*/
self.maxContentHeight_ = 0;
/**
* @type {number}
* @private
*/
self.aspectRatio_ = 0;
/**
* @type {ThumbnailLoader}
* @private
*/
self.thumbnailPreloader_ = null;
/**
* @type {ThumbnailLoader}
* @private
*/
self.thumbnailLoader_ = null;
/**
* @type {boolean}
* @private
*/
self.imagePreloaded_ = false;
/**
* @type {boolean}
* @private
*/
self.imageLoaded_ = false;
/**
* @type {boolean}
* @private
*/
self.imagePreloading_ = false;
/**
* @type {boolean}
* @private
*/
self.imageLoading_ = false;
/**
* @type {HTMLDivElement}
* @private
*/
self.wrapper_ = null;
}; };
/** /**
...@@ -1660,27 +1899,35 @@ Mosaic.Tile.prototype.__proto__ = HTMLDivElement.prototype; ...@@ -1660,27 +1899,35 @@ Mosaic.Tile.prototype.__proto__ = HTMLDivElement.prototype;
/** /**
* Minimum tile content size. * Minimum tile content size.
* @type {number}
* @const
*/ */
Mosaic.Tile.MIN_CONTENT_SIZE = 64; Mosaic.Tile.MIN_CONTENT_SIZE = 64;
/** /**
* Maximum tile content size. * Maximum tile content size.
* @type {number}
* @const
*/ */
Mosaic.Tile.MAX_CONTENT_SIZE = 512; Mosaic.Tile.MAX_CONTENT_SIZE = 512;
/** /**
* Default size for a tile with no thumbnail image. * Default size for a tile with no thumbnail image.
* @type {number}
* @const
*/ */
Mosaic.Tile.GENERIC_ICON_SIZE = 128; Mosaic.Tile.GENERIC_ICON_SIZE = 128;
/** /**
* Max size of an image considered to be 'small'. * Max size of an image considered to be 'small'.
* Small images are laid out slightly differently. * Small images are laid out slightly differently.
* @type {number}
* @const
*/ */
Mosaic.Tile.SMALL_IMAGE_SIZE = 160; Mosaic.Tile.SMALL_IMAGE_SIZE = 160;
/** /**
* @return {Gallery.Item} The Gallery item. * @return {!Gallery.Item} The Gallery item.
*/ */
Mosaic.Tile.prototype.getItem = function() { return this.item_; }; Mosaic.Tile.prototype.getItem = function() { return this.item_; };
...@@ -1843,7 +2090,7 @@ Mosaic.Tile.prototype.init = function() { ...@@ -1843,7 +2090,7 @@ Mosaic.Tile.prototype.init = function() {
* For the low-dpi mode, only low-dpi image is loaded. If not available, then * For the low-dpi mode, only low-dpi image is loaded. If not available, then
* the high-dpi image is loaded as a fallback. * the high-dpi image is loaded as a fallback.
* *
* @param {Mosaic.Tile.LoadMode} loadMode Loading mode. * @param {!Mosaic.Tile.LoadMode} loadMode Loading mode.
* @param {function(boolean)} onImageLoaded Callback when image is loaded. * @param {function(boolean)} onImageLoaded Callback when image is loaded.
* The argument is true for success, false for failure. * The argument is true for success, false for failure.
*/ */
...@@ -1951,7 +2198,8 @@ Mosaic.Tile.prototype.layout = function(left, top, width, height) { ...@@ -1951,7 +2198,8 @@ Mosaic.Tile.prototype.layout = function(left, top, width, height) {
if (!this.wrapper_) { // First time, create DOM. if (!this.wrapper_) { // First time, create DOM.
this.container_.appendChild(this); this.container_.appendChild(this);
var border = util.createChild(this, 'img-border'); var border = util.createChild(this, 'img-border');
this.wrapper_ = util.createChild(border, 'img-wrapper'); this.wrapper_ = assertInstanceof(util.createChild(border, 'img-wrapper'),
HTMLDivElement);
} }
if (this.hasAttribute('selected')) if (this.hasAttribute('selected'))
this.scrollIntoView(false); this.scrollIntoView(false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment