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