Home | History | Annotate | Download | only in js
      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
      3 // found in the LICENSE file.
      4 
      5 'use strict';
      6 
      7 /**
      8  * FileGrid constructor.
      9  *
     10  * Represents grid for the Grid Vew in the File Manager.
     11  * @constructor
     12  * @extends {cr.ui.Grid}
     13  */
     14 
     15 function FileGrid() {
     16   throw new Error('Use FileGrid.decorate');
     17 }
     18 
     19 /**
     20  * Thumbnail quality.
     21  * @enum {number}
     22  */
     23 FileGrid.ThumbnailQuality = {
     24   LOW: 0,
     25   HIGH: 1
     26 };
     27 
     28 /**
     29  * Inherits from cr.ui.Grid.
     30  */
     31 FileGrid.prototype.__proto__ = cr.ui.Grid.prototype;
     32 
     33 /**
     34  * Decorates an HTML element to be a FileGrid.
     35  * @param {HTMLElement} self The grid to decorate.
     36  * @param {MetadataCache} metadataCache Metadata cache to find entries
     37  *                                      metadata.
     38  */
     39 FileGrid.decorate = function(self, metadataCache) {
     40   cr.ui.Grid.decorate(self);
     41   self.__proto__ = FileGrid.prototype;
     42   self.metadataCache_ = metadataCache;
     43 
     44   self.scrollBar_ = new MainPanelScrollBar();
     45   self.scrollBar_.initialize(self.parentNode, self);
     46 
     47   self.itemConstructor = function(entry) {
     48     var item = self.ownerDocument.createElement('LI');
     49     FileGrid.Item.decorate(item, entry, self);
     50     return item;
     51   };
     52 
     53   self.relayoutAggregation_ =
     54       new AsyncUtil.Aggregation(self.relayoutImmediately_.bind(self));
     55 };
     56 
     57 /**
     58  * Updates items to reflect metadata changes.
     59  * @param {string} type Type of metadata changed.
     60  * @param {Object.<string, Object>} props Map from entry URLs to metadata props.
     61  */
     62 FileGrid.prototype.updateListItemsMetadata = function(type, props) {
     63   var boxes = this.querySelectorAll('.img-container');
     64   for (var i = 0; i < boxes.length; i++) {
     65     var box = boxes[i];
     66     var entry = this.dataModel.item(this.getListItemAncestor(box));
     67     if (!entry || !(entry.toURL() in props))
     68       continue;
     69 
     70     FileGrid.decorateThumbnailBox(box,
     71                                   entry,
     72                                   this.metadataCache_,
     73                                   ThumbnailLoader.FillMode.FIT,
     74                                   FileGrid.ThumbnailQuality.HIGH);
     75   }
     76 };
     77 
     78 /**
     79  * Redraws the UI. Skips multiple consecutive calls.
     80  */
     81 FileGrid.prototype.relayout = function() {
     82   this.relayoutAggregation_.run();
     83 };
     84 
     85 /**
     86  * Redraws the UI immediately.
     87  * @private
     88  */
     89 FileGrid.prototype.relayoutImmediately_ = function() {
     90   this.startBatchUpdates();
     91   this.columns = 0;
     92   this.redraw();
     93   this.endBatchUpdates();
     94   cr.dispatchSimpleEvent(this, 'relayout');
     95 };
     96 
     97 /**
     98  * Decorates thumbnail.
     99  * @param {HTMLElement} li List item.
    100  * @param {Entry} entry Entry to render a thumbnail for.
    101  * @param {MetadataCache} metadataCache To retrieve metadata.
    102  */
    103 FileGrid.decorateThumbnail = function(li, entry, metadataCache) {
    104   li.className = 'thumbnail-item';
    105   filelist.decorateListItem(li, entry, metadataCache);
    106 
    107   var frame = li.ownerDocument.createElement('div');
    108   frame.className = 'thumbnail-frame';
    109   li.appendChild(frame);
    110 
    111   var box = li.ownerDocument.createElement('div');
    112   FileGrid.decorateThumbnailBox(box,
    113                                 entry,
    114                                 metadataCache,
    115                                 ThumbnailLoader.FillMode.AUTO,
    116                                 FileGrid.ThumbnailQuality.HIGH);
    117   frame.appendChild(box);
    118 
    119   var bottom = li.ownerDocument.createElement('div');
    120   bottom.className = 'thumbnail-bottom';
    121   frame.appendChild(bottom);
    122 
    123   bottom.appendChild(filelist.renderFileNameLabel(li.ownerDocument, entry));
    124 };
    125 
    126 /**
    127  * Decorates the box containing a centered thumbnail image.
    128  *
    129  * @param {HTMLDivElement} box Box to decorate.
    130  * @param {Entry} entry Entry which thumbnail is generating for.
    131  * @param {MetadataCache} metadataCache To retrieve metadata.
    132  * @param {ThumbnailLoader.FillMode} fillMode Fill mode.
    133  * @param {FileGrid.ThumbnailQuality} quality Thumbnail quality.
    134  * @param {function(HTMLElement)=} opt_imageLoadCallback Callback called when
    135  *     the image has been loaded before inserting it into the DOM.
    136  */
    137 FileGrid.decorateThumbnailBox = function(
    138     box, entry, metadataCache, fillMode, quality, opt_imageLoadCallback) {
    139   box.className = 'img-container';
    140   if (entry.isDirectory) {
    141     box.setAttribute('generic-thumbnail', 'folder');
    142     if (opt_imageLoadCallback)
    143       setTimeout(opt_imageLoadCallback, 0, null /* callback parameter */);
    144     return;
    145   }
    146 
    147   var imageUrl = entry.toURL();
    148   var metadataTypes = 'thumbnail|filesystem';
    149 
    150   if (FileType.isOnDrive(imageUrl)) {
    151     metadataTypes += '|drive';
    152   } else {
    153     // TODO(dgozman): If we ask for 'media' for a Drive file we fall into an
    154     // infinite loop.
    155     metadataTypes += '|media';
    156   }
    157 
    158   // Drive provides high quality thumbnails via USE_EMBEDDED, however local
    159   // images usually provide very tiny thumbnails, therefore USE_EMBEDDE can't
    160   // be used to obtain high quality output.
    161   var useEmbedded;
    162   switch (quality) {
    163     case FileGrid.ThumbnailQuality.LOW:
    164       useEmbedded = ThumbnailLoader.UseEmbedded.USE_EMBEDDED;
    165       break;
    166     case FileGrid.ThumbnailQuality.HIGH:
    167       useEmbedded = FileType.isOnDrive(imageUrl) ?
    168           ThumbnailLoader.UseEmbedded.USE_EMBEDDED :
    169           ThumbnailLoader.UseEmbedded.NO_EMBEDDED;
    170       break;
    171   }
    172 
    173   metadataCache.get(imageUrl, metadataTypes,
    174       function(metadata) {
    175         new ThumbnailLoader(imageUrl,
    176                             ThumbnailLoader.LoaderType.IMAGE,
    177                             metadata,
    178                             undefined,  // opt_mediaType
    179                             useEmbedded).
    180             load(box,
    181                 fillMode,
    182                 ThumbnailLoader.OptimizationMode.DISCARD_DETACHED,
    183                 opt_imageLoadCallback);
    184       });
    185 };
    186 
    187 /**
    188  * Item for the Grid View.
    189  * @constructor
    190  */
    191 FileGrid.Item = function() {
    192   throw new Error();
    193 };
    194 
    195 /**
    196  * Inherits from cr.ui.ListItem.
    197  */
    198 FileGrid.Item.prototype.__proto__ = cr.ui.ListItem.prototype;
    199 
    200 Object.defineProperty(FileGrid.Item.prototype, 'label', {
    201   /**
    202    * @this {FileGrid.Item}
    203    * @return {string} Label of the item.
    204    */
    205   get: function() {
    206     return this.querySelector('filename-label').textContent;
    207   }
    208 });
    209 
    210 /**
    211  * @param {Element} li List item element.
    212  * @param {Entry} entry File entry.
    213  * @param {FileGrid} grid Owner.
    214  */
    215 FileGrid.Item.decorate = function(li, entry, grid) {
    216   li.__proto__ = FileGrid.Item.prototype;
    217   FileGrid.decorateThumbnail(li, entry, grid.metadataCache_, true);
    218 
    219   // Override the default role 'listitem' to 'option' to match the parent's
    220   // role (listbox).
    221   li.setAttribute('role', 'option');
    222 };
    223 
    224 /**
    225  * Sets the margin height for the transparent preview panel at the bottom.
    226  * @param {number} margin Margin to be set in px.
    227  */
    228 FileGrid.prototype.setBottomMarginForPanel = function(margin) {
    229   this.style.paddingBottom = margin + 'px';
    230   this.scrollBar_.setBottomMarginForPanel(margin);
    231 };
    232