text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  'use strict';
  
  /**
   * FileGrid constructor.
   *
   * Represents grid for the Grid Vew in the File Manager.
   * @constructor
   * @extends {cr.ui.Grid}
   */
  
  function FileGrid() {
    throw new Error('Use FileGrid.decorate');
  }
  
  /**
   * Thumbnail quality.
   * @enum {number}
   */
  FileGrid.ThumbnailQuality = {
    LOW: 0,
    HIGH: 1
  };
  
  /**
   * Inherits from cr.ui.Grid.
   */
  FileGrid.prototype.__proto__ = cr.ui.Grid.prototype;
  
  /**
   * Decorates an HTML element to be a FileGrid.
   * @param {HTMLElement} self The grid to decorate.
   * @param {MetadataCache} metadataCache Metadata cache to find entries
   *                                      metadata.
   */
  FileGrid.decorate = function(self, metadataCache) {
    cr.ui.Grid.decorate(self);
    self.__proto__ = FileGrid.prototype;
    self.metadataCache_ = metadataCache;
  
    self.scrollBar_ = new MainPanelScrollBar();
    self.scrollBar_.initialize(self.parentNode, self);
  
    self.itemConstructor = function(entry) {
      var item = self.ownerDocument.createElement('LI');
      FileGrid.Item.decorate(item, entry, self);
      return item;
    };
  
    self.relayoutAggregation_ =
        new AsyncUtil.Aggregation(self.relayoutImmediately_.bind(self));
  };
  
  /**
   * Updates items to reflect metadata changes.
   * @param {string} type Type of metadata changed.
   * @param {Object.<string, Object>} props Map from entry URLs to metadata props.
   */
  FileGrid.prototype.updateListItemsMetadata = function(type, props) {
    var boxes = this.querySelectorAll('.img-container');
    for (var i = 0; i < boxes.length; i++) {
      var box = boxes[i];
      var entry = this.dataModel.item(this.getListItemAncestor(box));
      if (!entry || !(entry.toURL() in props))
        continue;
  
      FileGrid.decorateThumbnailBox(box,
                                    entry,
                                    this.metadataCache_,
                                    ThumbnailLoader.FillMode.FIT,
                                    FileGrid.ThumbnailQuality.HIGH);
    }
  };
  
  /**
   * Redraws the UI. Skips multiple consecutive calls.
   */
  FileGrid.prototype.relayout = function() {
    this.relayoutAggregation_.run();
  };
  
  /**
   * Redraws the UI immediately.
   * @private
   */
  FileGrid.prototype.relayoutImmediately_ = function() {
    this.startBatchUpdates();
    this.columns = 0;
    this.redraw();
    this.endBatchUpdates();
    cr.dispatchSimpleEvent(this, 'relayout');
  };
  
  /**
   * Decorates thumbnail.
   * @param {HTMLElement} li List item.
   * @param {Entry} entry Entry to render a thumbnail for.
   * @param {MetadataCache} metadataCache To retrieve metadata.
   */
  FileGrid.decorateThumbnail = function(li, entry, metadataCache) {
    li.className = 'thumbnail-item';
    filelist.decorateListItem(li, entry, metadataCache);
  
    var frame = li.ownerDocument.createElement('div');
    frame.className = 'thumbnail-frame';
    li.appendChild(frame);
  
    var box = li.ownerDocument.createElement('div');
    FileGrid.decorateThumbnailBox(box,
                                  entry,
                                  metadataCache,
                                  ThumbnailLoader.FillMode.AUTO,
                                  FileGrid.ThumbnailQuality.HIGH);
    frame.appendChild(box);
  
    var bottom = li.ownerDocument.createElement('div');
    bottom.className = 'thumbnail-bottom';
    frame.appendChild(bottom);
  
    bottom.appendChild(filelist.renderFileNameLabel(li.ownerDocument, entry));
  };
  
  /**
   * Decorates the box containing a centered thumbnail image.
   *
   * @param {HTMLDivElement} box Box to decorate.
   * @param {Entry} entry Entry which thumbnail is generating for.
   * @param {MetadataCache} metadataCache To retrieve metadata.
   * @param {ThumbnailLoader.FillMode} fillMode Fill mode.
   * @param {FileGrid.ThumbnailQuality} quality Thumbnail quality.
   * @param {function(HTMLElement)=} opt_imageLoadCallback Callback called when
   *     the image has been loaded before inserting it into the DOM.
   */
  FileGrid.decorateThumbnailBox = function(
      box, entry, metadataCache, fillMode, quality, opt_imageLoadCallback) {
    box.className = 'img-container';
    if (entry.isDirectory) {
      box.setAttribute('generic-thumbnail', 'folder');
      if (opt_imageLoadCallback)
        setTimeout(opt_imageLoadCallback, 0, null /* callback parameter */);
      return;
    }
  
    var imageUrl = entry.toURL();
    var metadataTypes = 'thumbnail|filesystem';
  
    if (FileType.isOnDrive(imageUrl)) {
      metadataTypes += '|drive';
    } else {
      // TODO(dgozman): If we ask for 'media' for a Drive file we fall into an
      // infinite loop.
      metadataTypes += '|media';
    }
  
    // Drive provides high quality thumbnails via USE_EMBEDDED, however local
    // images usually provide very tiny thumbnails, therefore USE_EMBEDDE can't
    // be used to obtain high quality output.
    var useEmbedded;
    switch (quality) {
      case FileGrid.ThumbnailQuality.LOW:
        useEmbedded = ThumbnailLoader.UseEmbedded.USE_EMBEDDED;
        break;
      case FileGrid.ThumbnailQuality.HIGH:
        useEmbedded = FileType.isOnDrive(imageUrl) ?
            ThumbnailLoader.UseEmbedded.USE_EMBEDDED :
            ThumbnailLoader.UseEmbedded.NO_EMBEDDED;
        break;
    }
  
    metadataCache.get(imageUrl, metadataTypes,
        function(metadata) {
          new ThumbnailLoader(imageUrl,
                              ThumbnailLoader.LoaderType.IMAGE,
                              metadata,
                              undefined,  // opt_mediaType
                              useEmbedded).
              load(box,
                  fillMode,
                  ThumbnailLoader.OptimizationMode.DISCARD_DETACHED,
                  opt_imageLoadCallback);
        });
  };
  
  /**
   * Item for the Grid View.
   * @constructor
   */
  FileGrid.Item = function() {
    throw new Error();
  };
  
  /**
   * Inherits from cr.ui.ListItem.
   */
  FileGrid.Item.prototype.__proto__ = cr.ui.ListItem.prototype;
  
  Object.defineProperty(FileGrid.Item.prototype, 'label', {
    /**
     * @this {FileGrid.Item}
     * @return {string} Label of the item.
     */
    get: function() {
      return this.querySelector('filename-label').textContent;
    }
  });
  
  /**
   * @param {Element} li List item element.
   * @param {Entry} entry File entry.
   * @param {FileGrid} grid Owner.
   */
  FileGrid.Item.decorate = function(li, entry, grid) {
    li.__proto__ = FileGrid.Item.prototype;
    FileGrid.decorateThumbnail(li, entry, grid.metadataCache_, true);
  
    // Override the default role 'listitem' to 'option' to match the parent's
    // role (listbox).
    li.setAttribute('role', 'option');
  };
  
  /**
   * Sets the margin height for the transparent preview panel at the bottom.
   * @param {number} margin Margin to be set in px.
   */
  FileGrid.prototype.setBottomMarginForPanel = function(margin) {
    this.style.paddingBottom = margin + 'px';
    this.scrollBar_.setBottomMarginForPanel(margin);
  };
  