| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013 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 // DirectoryTreeBase | |
| 9 | |
| 10 /** | |
| 11 * Implementation of methods for DirectoryTree and DirectoryItem. These classes | |
| 12 * inherits cr.ui.Tree/TreeItem so we can't make them inherit this class. | |
| 13 * Instead, we separate their implementations to this separate object and call | |
| 14 * it with setting 'this' from DirectoryTree/Item. | |
| 15 */ | |
| 16 var DirectoryItemTreeBaseMethods = {}; | |
| 17 | |
| 18 /** | |
| 19 * Updates sub-elements of {@code this} reading {@code DirectoryEntry}. | |
| 20 * The list of {@code DirectoryEntry} are not updated by this method. | |
| 21 * | |
| 22 * @param {boolean} recursive True if the all visible sub-directories are | |
| 23 * updated recursively including left arrows. If false, the update walks | |
| 24 * only immediate child directories without arrows. | |
| 25 */ | |
| 26 DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) { | |
| 27 var index = 0; | |
| 28 var tree = this.parentTree_ || this; // If no parent, 'this' itself is tree. | |
| 29 while (this.entries_[index]) { | |
| 30 var currentEntry = this.entries_[index]; | |
| 31 var currentElement = this.items[index]; | |
| 32 var label = util.getEntryLabel(tree.volumeManager_, currentEntry); | |
| 33 | |
| 34 if (index >= this.items.length) { | |
| 35 var item = new DirectoryItem(label, currentEntry, this, tree); | |
| 36 this.add(item); | |
| 37 index++; | |
| 38 } else if (util.isSameEntry(currentEntry, currentElement.entry)) { | |
| 39 if (recursive && this.expanded) | |
| 40 currentElement.updateSubDirectories(true /* recursive */); | |
| 41 | |
| 42 index++; | |
| 43 } else if (currentEntry.toURL() < currentElement.entry.toURL()) { | |
| 44 var item = new DirectoryItem(label, currentEntry, this, tree); | |
| 45 this.addAt(item, index); | |
| 46 index++; | |
| 47 } else if (currentEntry.toURL() > currentElement.entry.toURL()) { | |
| 48 this.remove(currentElement); | |
| 49 } | |
| 50 } | |
| 51 | |
| 52 var removedChild; | |
| 53 while (removedChild = this.items[index]) { | |
| 54 this.remove(removedChild); | |
| 55 } | |
| 56 | |
| 57 if (index === 0) { | |
| 58 this.hasChildren = false; | |
| 59 this.expanded = false; | |
| 60 } else { | |
| 61 this.hasChildren = true; | |
| 62 } | |
| 63 }; | |
| 64 | |
| 65 /** | |
| 66 * Finds a parent directory of the {@code entry} in {@code this}, and | |
| 67 * invokes the DirectoryItem.selectByEntry() of the found directory. | |
| 68 * | |
| 69 * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be | |
| 70 * a fake. | |
| 71 * @return {boolean} True if the parent item is found. | |
| 72 */ | |
| 73 DirectoryItemTreeBaseMethods.searchAndSelectByEntry = function(entry) { | |
| 74 for (var i = 0; i < this.items.length; i++) { | |
| 75 var item = this.items[i]; | |
| 76 if (util.isDescendantEntry(item.entry, entry) || | |
| 77 util.isSameEntry(item.entry, entry)) { | |
| 78 item.selectByEntry(entry); | |
| 79 return true; | |
| 80 } | |
| 81 } | |
| 82 return false; | |
| 83 }; | |
| 84 | |
| 85 Object.freeze(DirectoryItemTreeBaseMethods); | |
| 86 | |
| 87 //////////////////////////////////////////////////////////////////////////////// | |
| 88 // DirectoryItem | |
| 89 | |
| 90 /** | |
| 91 * A directory in the tree. Each element represents one directory. | |
| 92 * | |
| 93 * @param {string} label Label for this item. | |
| 94 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. | |
| 95 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. | |
| 96 * @param {DirectoryTree} tree Current tree, which contains this item. | |
| 97 * @extends {cr.ui.TreeItem} | |
| 98 * @constructor | |
| 99 */ | |
| 100 function DirectoryItem(label, dirEntry, parentDirItem, tree) { | |
| 101 var item = new cr.ui.TreeItem(); | |
| 102 DirectoryItem.decorate(item, label, dirEntry, parentDirItem, tree); | |
| 103 return item; | |
| 104 } | |
| 105 | |
| 106 /** | |
| 107 * @param {HTMLElement} el Element to be DirectoryItem. | |
| 108 * @param {string} label Label for this item. | |
| 109 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. | |
| 110 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. | |
| 111 * @param {DirectoryTree} tree Current tree, which contains this item. | |
| 112 */ | |
| 113 DirectoryItem.decorate = | |
| 114 function(el, label, dirEntry, parentDirItem, tree) { | |
| 115 el.__proto__ = DirectoryItem.prototype; | |
| 116 (/** @type {DirectoryItem} */ el).decorate( | |
| 117 label, dirEntry, parentDirItem, tree); | |
| 118 }; | |
| 119 | |
| 120 DirectoryItem.prototype = { | |
| 121 __proto__: cr.ui.TreeItem.prototype, | |
| 122 | |
| 123 /** | |
| 124 * The DirectoryEntry corresponding to this DirectoryItem. This may be | |
| 125 * a dummy DirectoryEntry. | |
| 126 * @type {DirectoryEntry|Object} | |
| 127 */ | |
| 128 get entry() { | |
| 129 return this.dirEntry_; | |
| 130 }, | |
| 131 | |
| 132 /** | |
| 133 * The element containing the label text and the icon. | |
| 134 * @type {!HTMLElement} | |
| 135 * @override | |
| 136 */ | |
| 137 get labelElement() { | |
| 138 return this.firstElementChild.querySelector('.label'); | |
| 139 } | |
| 140 }; | |
| 141 | |
| 142 /** | |
| 143 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). | |
| 144 * | |
| 145 * @param {boolean} recursive True if the all visible sub-directories are | |
| 146 * updated recursively including left arrows. If false, the update walks | |
| 147 * only immediate child directories without arrows. | |
| 148 */ | |
| 149 DirectoryItem.prototype.updateSubElementsFromList = function(recursive) { | |
| 150 DirectoryItemTreeBaseMethods.updateSubElementsFromList.call(this, recursive); | |
| 151 }; | |
| 152 | |
| 153 /** | |
| 154 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). | |
| 155 * | |
| 156 * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be | |
| 157 * a fake. | |
| 158 * @return {boolean} True if the parent item is found. | |
| 159 */ | |
| 160 DirectoryItem.prototype.searchAndSelectByEntry = function(entry) { | |
| 161 return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry); | |
| 162 }; | |
| 163 | |
| 164 /** | |
| 165 * @param {string} label Localized label for this item. | |
| 166 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. | |
| 167 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. | |
| 168 * @param {DirectoryTree} tree Current tree, which contains this item. | |
| 169 */ | |
| 170 DirectoryItem.prototype.decorate = function( | |
| 171 label, dirEntry, parentDirItem, tree) { | |
| 172 this.innerHTML = | |
| 173 '<div class="tree-row">' + | |
| 174 ' <span class="expand-icon"></span>' + | |
| 175 ' <span class="icon"></span>' + | |
| 176 ' <span class="label"></span>' + | |
| 177 '</div>' + | |
| 178 '<div class="tree-children"></div>'; | |
| 179 | |
| 180 this.parentTree_ = tree; | |
| 181 this.directoryModel_ = tree.directoryModel; | |
| 182 this.parent_ = parentDirItem; | |
| 183 this.label = label; | |
| 184 this.dirEntry_ = dirEntry; | |
| 185 this.fileFilter_ = this.directoryModel_.getFileFilter(); | |
| 186 | |
| 187 // Sets hasChildren=false tentatively. This will be overridden after | |
| 188 // scanning sub-directories in updateSubElementsFromList(). | |
| 189 this.hasChildren = false; | |
| 190 | |
| 191 this.addEventListener('expand', this.onExpand_.bind(this), false); | |
| 192 var icon = this.querySelector('.icon'); | |
| 193 icon.classList.add('volume-icon'); | |
| 194 var location = tree.volumeManager.getLocationInfo(dirEntry); | |
| 195 if (location && location.rootType && location.isRootEntry) | |
| 196 icon.setAttribute('volume-type-icon', location.rootType); | |
| 197 else | |
| 198 icon.setAttribute('file-type-icon', 'folder'); | |
| 199 | |
| 200 if (this.parentTree_.contextMenuForSubitems) | |
| 201 this.setContextMenu(this.parentTree_.contextMenuForSubitems); | |
| 202 // Adds handler for future change. | |
| 203 this.parentTree_.addEventListener( | |
| 204 'contextMenuForSubitemsChange', | |
| 205 function(e) { this.setContextMenu(e.newValue); }.bind(this)); | |
| 206 | |
| 207 if (parentDirItem.expanded) | |
| 208 this.updateSubDirectories(false /* recursive */); | |
| 209 }; | |
| 210 | |
| 211 /** | |
| 212 * Overrides WebKit's scrollIntoViewIfNeeded, which doesn't work well with | |
| 213 * a complex layout. This call is not necessary, so we are ignoring it. | |
| 214 * | |
| 215 * @param {boolean} unused Unused. | |
| 216 * @override | |
| 217 */ | |
| 218 DirectoryItem.prototype.scrollIntoViewIfNeeded = function(unused) { | |
| 219 }; | |
| 220 | |
| 221 /** | |
| 222 * Removes the child node, but without selecting the parent item, to avoid | |
| 223 * unintended changing of directories. Removing is done externally, and other | |
| 224 * code will navigate to another directory. | |
| 225 * | |
| 226 * @param {!cr.ui.TreeItem} child The tree item child to remove. | |
| 227 * @override | |
| 228 */ | |
| 229 DirectoryItem.prototype.remove = function(child) { | |
| 230 this.lastElementChild.removeChild(child); | |
| 231 if (this.items.length == 0) | |
| 232 this.hasChildren = false; | |
| 233 }; | |
| 234 | |
| 235 /** | |
| 236 * Invoked when the item is being expanded. | |
| 237 * @param {!UIEvent} e Event. | |
| 238 * @private | |
| 239 **/ | |
| 240 DirectoryItem.prototype.onExpand_ = function(e) { | |
| 241 this.updateSubDirectories( | |
| 242 true /* recursive */, | |
| 243 function() {}, | |
| 244 function() { | |
| 245 this.expanded = false; | |
| 246 }.bind(this)); | |
| 247 | |
| 248 e.stopPropagation(); | |
| 249 }; | |
| 250 | |
| 251 /** | |
| 252 * Invoked when the tree item is clicked. | |
| 253 * | |
| 254 * @param {Event} e Click event. | |
| 255 * @override | |
| 256 */ | |
| 257 DirectoryItem.prototype.handleClick = function(e) { | |
| 258 cr.ui.TreeItem.prototype.handleClick.call(this, e); | |
| 259 | |
| 260 if (e.target.classList.contains('expand-icon')) | |
| 261 return; | |
| 262 | |
| 263 var currentDirectoryEntry = this.directoryModel_.getCurrentDirEntry(); | |
| 264 if (currentDirectoryEntry && | |
| 265 util.isSameEntry(this.entry, currentDirectoryEntry)) { | |
| 266 // On clicking the current directory, clears the selection on the file list. | |
| 267 this.directoryModel_.clearSelection(); | |
| 268 } else { | |
| 269 // Otherwise, changes the current directory. | |
| 270 this.directoryModel_.changeDirectoryEntry(this.entry); | |
| 271 } | |
| 272 }; | |
| 273 | |
| 274 /** | |
| 275 * Retrieves the latest subdirectories and update them on the tree. | |
| 276 * @param {boolean} recursive True if the update is recursively. | |
| 277 * @param {function()=} opt_successCallback Callback called on success. | |
| 278 * @param {function()=} opt_errorCallback Callback called on error. | |
| 279 */ | |
| 280 DirectoryItem.prototype.updateSubDirectories = function( | |
| 281 recursive, opt_successCallback, opt_errorCallback) { | |
| 282 if (util.isFakeEntry(this.entry)) { | |
| 283 if (opt_errorCallback) | |
| 284 opt_errorCallback(); | |
| 285 return; | |
| 286 } | |
| 287 | |
| 288 var sortEntries = function(fileFilter, entries) { | |
| 289 entries.sort(function(a, b) { | |
| 290 return (a.name.toLowerCase() > b.name.toLowerCase()) ? 1 : -1; | |
| 291 }); | |
| 292 return entries.filter(fileFilter.filter.bind(fileFilter)); | |
| 293 }; | |
| 294 | |
| 295 var onSuccess = function(entries) { | |
| 296 this.entries_ = entries; | |
| 297 this.redrawSubDirectoryList_(recursive); | |
| 298 opt_successCallback && opt_successCallback(); | |
| 299 }.bind(this); | |
| 300 | |
| 301 var reader = this.entry.createReader(); | |
| 302 var entries = []; | |
| 303 var readEntry = function() { | |
| 304 reader.readEntries(function(results) { | |
| 305 if (!results.length) { | |
| 306 onSuccess(sortEntries(this.fileFilter_, entries)); | |
| 307 return; | |
| 308 } | |
| 309 | |
| 310 for (var i = 0; i < results.length; i++) { | |
| 311 var entry = results[i]; | |
| 312 if (entry.isDirectory) | |
| 313 entries.push(entry); | |
| 314 } | |
| 315 readEntry(); | |
| 316 }.bind(this)); | |
| 317 }.bind(this); | |
| 318 readEntry(); | |
| 319 }; | |
| 320 | |
| 321 /** | |
| 322 * Searches for the changed directory in the current subtree, and if it is found | |
| 323 * then updates it. | |
| 324 * | |
| 325 * @param {DirectoryEntry} changedDirectoryEntry The entry ot the changed | |
| 326 * directory. | |
| 327 */ | |
| 328 DirectoryItem.prototype.updateItemByEntry = function(changedDirectoryEntry) { | |
| 329 if (util.isSameEntry(changedDirectoryEntry, this.entry)) { | |
| 330 this.updateSubDirectories(false /* recursive */); | |
| 331 return; | |
| 332 } | |
| 333 | |
| 334 // Traverse the entire subtree to find the changed element. | |
| 335 for (var i = 0; i < this.items.length; i++) { | |
| 336 var item = this.items[i]; | |
| 337 if (util.isDescendantEntry(item.entry, changedDirectoryEntry)) { | |
| 338 item.updateItemByEntry(changedDirectoryEntry); | |
| 339 break; | |
| 340 } | |
| 341 } | |
| 342 }; | |
| 343 | |
| 344 /** | |
| 345 * Redraw subitems with the latest information. The items are sorted in | |
| 346 * alphabetical order, case insensitive. | |
| 347 * @param {boolean} recursive True if the update is recursively. | |
| 348 * @private | |
| 349 */ | |
| 350 DirectoryItem.prototype.redrawSubDirectoryList_ = function(recursive) { | |
| 351 this.updateSubElementsFromList(recursive); | |
| 352 }; | |
| 353 | |
| 354 /** | |
| 355 * Select the item corresponding to the given {@code entry}. | |
| 356 * @param {DirectoryEntry|Object} entry The entry to be selected. Can be a fake. | |
| 357 */ | |
| 358 DirectoryItem.prototype.selectByEntry = function(entry) { | |
| 359 if (util.isSameEntry(entry, this.entry)) { | |
| 360 this.selected = true; | |
| 361 return; | |
| 362 } | |
| 363 | |
| 364 if (this.searchAndSelectByEntry(entry)) | |
| 365 return; | |
| 366 | |
| 367 // If the entry doesn't exist, updates sub directories and tries again. | |
| 368 this.updateSubDirectories( | |
| 369 false /* recursive */, | |
| 370 this.searchAndSelectByEntry.bind(this, entry)); | |
| 371 }; | |
| 372 | |
| 373 /** | |
| 374 * Executes the assigned action as a drop target. | |
| 375 */ | |
| 376 DirectoryItem.prototype.doDropTargetAction = function() { | |
| 377 this.expanded = true; | |
| 378 }; | |
| 379 | |
| 380 /** | |
| 381 * Sets the context menu for directory tree. | |
| 382 * @param {cr.ui.Menu} menu Menu to be set. | |
| 383 */ | |
| 384 DirectoryItem.prototype.setContextMenu = function(menu) { | |
| 385 var tree = this.parentTree_ || this; // If no parent, 'this' itself is tree. | |
| 386 var locationInfo = tree.volumeManager_.getLocationInfo(this.entry); | |
| 387 if (locationInfo && locationInfo.isEligibleForFolderShortcut) | |
| 388 cr.ui.contextMenuHandler.setContextMenu(this, menu); | |
| 389 }; | |
| 390 | |
| 391 //////////////////////////////////////////////////////////////////////////////// | |
| 392 // DirectoryTree | |
| 393 | |
| 394 /** | |
| 395 * Tree of directories on the middle bar. This element is also the root of | |
| 396 * items, in other words, this is the parent of the top-level items. | |
| 397 * | |
| 398 * @constructor | |
| 399 * @extends {cr.ui.Tree} | |
| 400 */ | |
| 401 function DirectoryTree() {} | |
| 402 | |
| 403 /** | |
| 404 * Decorates an element. | |
| 405 * @param {HTMLElement} el Element to be DirectoryTree. | |
| 406 * @param {DirectoryModel} directoryModel Current DirectoryModel. | |
| 407 * @param {VolumeManagerWrapper} volumeManager VolumeManager of the system. | |
| 408 */ | |
| 409 DirectoryTree.decorate = function(el, directoryModel, volumeManager) { | |
| 410 el.__proto__ = DirectoryTree.prototype; | |
| 411 (/** @type {DirectoryTree} */ el).decorate(directoryModel, volumeManager); | |
| 412 }; | |
| 413 | |
| 414 DirectoryTree.prototype = { | |
| 415 __proto__: cr.ui.Tree.prototype, | |
| 416 | |
| 417 // DirectoryTree is always expanded. | |
| 418 get expanded() { return true; }, | |
| 419 /** | |
| 420 * @param {boolean} value Not used. | |
| 421 */ | |
| 422 set expanded(value) {}, | |
| 423 | |
| 424 /** | |
| 425 * The DirectoryEntry corresponding to this DirectoryItem. This may be | |
| 426 * a dummy DirectoryEntry. | |
| 427 * @type {DirectoryEntry|Object} | |
| 428 * @override | |
| 429 **/ | |
| 430 get entry() { | |
| 431 return this.dirEntry_; | |
| 432 }, | |
| 433 | |
| 434 /** | |
| 435 * The DirectoryModel this tree corresponds to. | |
| 436 * @type {DirectoryModel} | |
| 437 */ | |
| 438 get directoryModel() { | |
| 439 return this.directoryModel_; | |
| 440 }, | |
| 441 | |
| 442 /** | |
| 443 * The VolumeManager instance of the system. | |
| 444 * @type {VolumeManager} | |
| 445 */ | |
| 446 get volumeManager() { | |
| 447 return this.volumeManager_; | |
| 448 }, | |
| 449 }; | |
| 450 | |
| 451 cr.defineProperty(DirectoryTree, 'contextMenuForSubitems', cr.PropertyKind.JS); | |
| 452 | |
| 453 /** | |
| 454 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). | |
| 455 * | |
| 456 * @param {boolean} recursive True if the all visible sub-directories are | |
| 457 * updated recursively including left arrows. If false, the update walks | |
| 458 * only immediate child directories without arrows. | |
| 459 */ | |
| 460 DirectoryTree.prototype.updateSubElementsFromList = function(recursive) { | |
| 461 DirectoryItemTreeBaseMethods.updateSubElementsFromList.call(this, recursive); | |
| 462 }; | |
| 463 | |
| 464 /** | |
| 465 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). | |
| 466 * | |
| 467 * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be | |
| 468 * a fake. | |
| 469 * @return {boolean} True if the parent item is found. | |
| 470 */ | |
| 471 DirectoryTree.prototype.searchAndSelectByEntry = function(entry) { | |
| 472 return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry); | |
| 473 }; | |
| 474 | |
| 475 /** | |
| 476 * Decorates an element. | |
| 477 * @param {DirectoryModel} directoryModel Current DirectoryModel. | |
| 478 * @param {VolumeManagerWrapper} volumeManager VolumeManager of the system. | |
| 479 */ | |
| 480 DirectoryTree.prototype.decorate = function(directoryModel, volumeManager) { | |
| 481 cr.ui.Tree.prototype.decorate.call(this); | |
| 482 | |
| 483 this.sequence_ = 0; | |
| 484 this.directoryModel_ = directoryModel; | |
| 485 this.volumeManager_ = volumeManager; | |
| 486 this.entries_ = []; | |
| 487 this.currentVolumeInfo_ = null; | |
| 488 | |
| 489 this.fileFilter_ = this.directoryModel_.getFileFilter(); | |
| 490 this.fileFilter_.addEventListener('changed', | |
| 491 this.onFilterChanged_.bind(this)); | |
| 492 | |
| 493 this.directoryModel_.addEventListener('directory-changed', | |
| 494 this.onCurrentDirectoryChanged_.bind(this)); | |
| 495 | |
| 496 this.privateOnDirectoryChangedBound_ = | |
| 497 this.onDirectoryContentChanged_.bind(this); | |
| 498 chrome.fileBrowserPrivate.onDirectoryChanged.addListener( | |
| 499 this.privateOnDirectoryChangedBound_); | |
| 500 | |
| 501 this.scrollBar_ = MainPanelScrollBar(); | |
| 502 this.scrollBar_.initialize(this.parentNode, this); | |
| 503 }; | |
| 504 | |
| 505 /** | |
| 506 * Select the item corresponding to the given entry. | |
| 507 * @param {DirectoryEntry|Object} entry The directory entry to be selected. Can | |
| 508 * be a fake. | |
| 509 */ | |
| 510 DirectoryTree.prototype.selectByEntry = function(entry) { | |
| 511 // If the target directory is not in the tree, do nothing. | |
| 512 var locationInfo = this.volumeManager_.getLocationInfo(entry); | |
| 513 if (!locationInfo || !locationInfo.isDriveBased) | |
| 514 return; | |
| 515 | |
| 516 var volumeInfo = this.volumeManager_.getVolumeInfo(entry); | |
| 517 if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry)) | |
| 518 return; | |
| 519 | |
| 520 if (this.searchAndSelectByEntry(entry)) | |
| 521 return; | |
| 522 | |
| 523 this.updateSubDirectories(false /* recursive */); | |
| 524 var currentSequence = ++this.sequence_; | |
| 525 volumeInfo.resolveDisplayRoot(function() { | |
| 526 if (this.sequence_ !== currentSequence) | |
| 527 return; | |
| 528 if (!this.searchAndSelectByEntry(entry)) | |
| 529 this.selectedItem = null; | |
| 530 }.bind(this)); | |
| 531 }; | |
| 532 | |
| 533 /** | |
| 534 * Retrieves the latest subdirectories and update them on the tree. | |
| 535 * | |
| 536 * @param {boolean} recursive True if the update is recursively. | |
| 537 * @param {function()=} opt_callback Called when subdirectories are fully | |
| 538 * updated. | |
| 539 */ | |
| 540 DirectoryTree.prototype.updateSubDirectories = function( | |
| 541 recursive, opt_callback) { | |
| 542 var callback = opt_callback || function() {}; | |
| 543 this.entries_ = []; | |
| 544 | |
| 545 var compareEntries = function(a, b) { | |
| 546 return a.toURL() < b.toURL(); | |
| 547 }; | |
| 548 | |
| 549 // Add fakes (if any). | |
| 550 for (var key in this.currentVolumeInfo_.fakeEntries) { | |
| 551 this.entries_.push(this.currentVolumeInfo_.fakeEntries[key]); | |
| 552 } | |
| 553 | |
| 554 // If the display root is not available yet, then redraw anyway with what | |
| 555 // we have. However, concurrently try to resolve the display root and then | |
| 556 // redraw. | |
| 557 if (!this.currentVolumeInfo_.displayRoot) { | |
| 558 this.entries_.sort(compareEntries); | |
| 559 this.redraw(recursive); | |
| 560 } | |
| 561 | |
| 562 this.currentVolumeInfo_.resolveDisplayRoot(function(displayRoot) { | |
| 563 this.entries_.push(this.currentVolumeInfo_.displayRoot); | |
| 564 this.entries_.sort(compareEntries); | |
| 565 this.redraw(recursive); // Redraw. | |
| 566 callback(); | |
| 567 }.bind(this), callback /* Ignore errors. */); | |
| 568 }; | |
| 569 | |
| 570 /** | |
| 571 * Redraw the list. | |
| 572 * @param {boolean} recursive True if the update is recursively. False if the | |
| 573 * only root items are updated. | |
| 574 */ | |
| 575 DirectoryTree.prototype.redraw = function(recursive) { | |
| 576 this.updateSubElementsFromList(recursive); | |
| 577 }; | |
| 578 | |
| 579 /** | |
| 580 * Invoked when the filter is changed. | |
| 581 * @private | |
| 582 */ | |
| 583 DirectoryTree.prototype.onFilterChanged_ = function() { | |
| 584 // Returns immediately, if the tree is hidden. | |
| 585 if (this.hidden) | |
| 586 return; | |
| 587 | |
| 588 this.redraw(true /* recursive */); | |
| 589 }; | |
| 590 | |
| 591 /** | |
| 592 * Invoked when a directory is changed. | |
| 593 * @param {!UIEvent} event Event. | |
| 594 * @private | |
| 595 */ | |
| 596 DirectoryTree.prototype.onDirectoryContentChanged_ = function(event) { | |
| 597 if (event.eventType !== 'changed') | |
| 598 return; | |
| 599 | |
| 600 var locationInfo = this.volumeManager_.getLocationInfo(event.entry); | |
| 601 if (!locationInfo || !locationInfo.isDriveBased) | |
| 602 return; | |
| 603 | |
| 604 var myDriveItem = this.items[0]; | |
| 605 if (myDriveItem) | |
| 606 myDriveItem.updateItemByEntry(event.entry); | |
| 607 }; | |
| 608 | |
| 609 /** | |
| 610 * Invoked when the current directory is changed. | |
| 611 * @param {!UIEvent} event Event. | |
| 612 * @private | |
| 613 */ | |
| 614 DirectoryTree.prototype.onCurrentDirectoryChanged_ = function(event) { | |
| 615 this.currentVolumeInfo_ = | |
| 616 this.volumeManager_.getVolumeInfo(event.newDirEntry); | |
| 617 this.selectByEntry(event.newDirEntry); | |
| 618 }; | |
| 619 | |
| 620 /** | |
| 621 * Sets the margin height for the transparent preview panel at the bottom. | |
| 622 * @param {number} margin Margin to be set in px. | |
| 623 */ | |
| 624 DirectoryTree.prototype.setBottomMarginForPanel = function(margin) { | |
| 625 this.style.paddingBottom = margin + 'px'; | |
| 626 this.scrollBar_.setBottomMarginForPanel(margin); | |
| 627 }; | |
| 628 | |
| 629 /** | |
| 630 * Updates the UI after the layout has changed. | |
| 631 */ | |
| 632 DirectoryTree.prototype.relayout = function() { | |
| 633 cr.dispatchSimpleEvent(this, 'relayout'); | |
| 634 }; | |
| OLD | NEW |