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