Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 //////////////////////////////////////////////////////////////////////////////// | 7 //////////////////////////////////////////////////////////////////////////////// |
| 8 // DirectoryTreeUtil | 8 // DirectoryTreeUtil |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 43 * @param {boolean} recursive True if the all visible sub-directories are | 43 * @param {boolean} recursive True if the all visible sub-directories are |
| 44 * updated recursively including left arrows. If false, the update walks | 44 * updated recursively including left arrows. If false, the update walks |
| 45 * only immediate child directories without arrows. | 45 * only immediate child directories without arrows. |
| 46 */ | 46 */ |
| 47 DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) { | 47 DirectoryItemTreeBaseMethods.updateSubElementsFromList = function(recursive) { |
| 48 var index = 0; | 48 var index = 0; |
| 49 var tree = this.parentTree_ || this; // If no parent, 'this' itself is tree. | 49 var tree = this.parentTree_ || this; // If no parent, 'this' itself is tree. |
| 50 while (this.entries_[index]) { | 50 while (this.entries_[index]) { |
| 51 var currentEntry = this.entries_[index]; | 51 var currentEntry = this.entries_[index]; |
| 52 var currentElement = this.items[index]; | 52 var currentElement = this.items[index]; |
| 53 // TODO(mtomasz): Stop using full paths, and use getLocationInfo() instead. | |
| 54 var label = PathUtil.getFolderLabel(currentEntry.fullPath); | |
| 53 | 55 |
| 54 if (index >= this.items.length) { | 56 if (index >= this.items.length) { |
| 55 var item = new DirectoryItem(currentEntry, this, tree); | 57 var item = new DirectoryItem(label, currentEntry, this, tree); |
| 56 this.add(item); | 58 this.add(item); |
| 57 index++; | 59 index++; |
| 58 } else if (currentEntry.fullPath == currentElement.fullPath) { | 60 } else if (currentEntry.fullPath == currentElement.fullPath) { |
| 59 if (recursive && this.expanded) | 61 if (recursive && this.expanded) |
| 60 currentElement.updateSubDirectories(true /* recursive */); | 62 currentElement.updateSubDirectories(true /* recursive */); |
| 61 | 63 |
| 62 index++; | 64 index++; |
| 63 } else if (currentEntry.fullPath < currentElement.fullPath) { | 65 } else if (currentEntry.fullPath < currentElement.fullPath) { |
| 64 var item = new DirectoryItem(currentEntry, this, tree); | 66 var item = new DirectoryItem(label, currentEntry, this, tree); |
| 65 this.addAt(item, index); | 67 this.addAt(item, index); |
| 66 index++; | 68 index++; |
| 67 } else if (currentEntry.fullPath > currentElement.fullPath) { | 69 } else if (currentEntry.fullPath > currentElement.fullPath) { |
| 68 this.remove(currentElement); | 70 this.remove(currentElement); |
| 69 } | 71 } |
| 70 } | 72 } |
| 71 | 73 |
| 72 var removedChild; | 74 var removedChild; |
| 73 while (removedChild = this.items[index]) { | 75 while (removedChild = this.items[index]) { |
| 74 this.remove(removedChild); | 76 this.remove(removedChild); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 102 }; | 104 }; |
| 103 | 105 |
| 104 Object.freeze(DirectoryItemTreeBaseMethods); | 106 Object.freeze(DirectoryItemTreeBaseMethods); |
| 105 | 107 |
| 106 //////////////////////////////////////////////////////////////////////////////// | 108 //////////////////////////////////////////////////////////////////////////////// |
| 107 // DirectoryItem | 109 // DirectoryItem |
| 108 | 110 |
| 109 /** | 111 /** |
| 110 * A directory in the tree. Each element represents one directory. | 112 * A directory in the tree. Each element represents one directory. |
| 111 * | 113 * |
| 114 * @param {string} label Label for this item. | |
| 112 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. | 115 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. |
| 113 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. | 116 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. |
| 114 * @param {DirectoryTree} tree Current tree, which contains this item. | 117 * @param {DirectoryTree} tree Current tree, which contains this item. |
| 115 * @extends {cr.ui.TreeItem} | 118 * @extends {cr.ui.TreeItem} |
| 116 * @constructor | 119 * @constructor |
| 117 */ | 120 */ |
| 118 function DirectoryItem(dirEntry, parentDirItem, tree) { | 121 function DirectoryItem(label, dirEntry, parentDirItem, tree) { |
| 119 var item = cr.doc.createElement('div'); | 122 var item = cr.doc.createElement('div'); |
| 120 DirectoryItem.decorate(item, dirEntry, parentDirItem, tree); | 123 DirectoryItem.decorate(item, label, dirEntry, parentDirItem, tree); |
| 121 return item; | 124 return item; |
| 122 } | 125 } |
| 123 | 126 |
| 124 /** | 127 /** |
| 125 * @param {HTMLElement} el Element to be DirectoryItem. | 128 * @param {HTMLElement} el Element to be DirectoryItem. |
| 129 * @param {string} label Label for this item. | |
| 126 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. | 130 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. |
| 127 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. | 131 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. |
| 128 * @param {DirectoryTree} tree Current tree, which contains this item. | 132 * @param {DirectoryTree} tree Current tree, which contains this item. |
| 129 */ | 133 */ |
| 130 DirectoryItem.decorate = | 134 DirectoryItem.decorate = |
| 131 function(el, dirEntry, parentDirItem, tree) { | 135 function(el, label, dirEntry, parentDirItem, tree) { |
| 132 el.__proto__ = DirectoryItem.prototype; | 136 el.__proto__ = DirectoryItem.prototype; |
| 133 (/** @type {DirectoryItem} */ el).decorate( | 137 (/** @type {DirectoryItem} */ el).decorate( |
| 134 dirEntry, parentDirItem, tree); | 138 label, dirEntry, parentDirItem, tree); |
| 135 }; | 139 }; |
| 136 | 140 |
| 137 DirectoryItem.prototype = { | 141 DirectoryItem.prototype = { |
| 138 __proto__: cr.ui.TreeItem.prototype, | 142 __proto__: cr.ui.TreeItem.prototype, |
| 139 | 143 |
| 140 /** | 144 /** |
| 141 * The DirectoryEntry corresponding to this DirectoryItem. This may be | 145 * The DirectoryEntry corresponding to this DirectoryItem. This may be |
| 142 * a dummy DirectoryEntry. | 146 * a dummy DirectoryEntry. |
| 143 * @type {DirectoryEntry|Object} | 147 * @type {DirectoryEntry|Object} |
| 144 */ | 148 */ |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 171 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). | 175 * Calls DirectoryItemTreeBaseMethods.updateSubElementsFromList(). |
| 172 * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be | 176 * @param {DirectoryEntry|Object} entry The entry to be searched for. Can be |
| 173 * a fake. | 177 * a fake. |
| 174 * @return {boolean} True if the parent item is found. | 178 * @return {boolean} True if the parent item is found. |
| 175 */ | 179 */ |
| 176 DirectoryItem.prototype.searchAndSelectByEntry = function(entry) { | 180 DirectoryItem.prototype.searchAndSelectByEntry = function(entry) { |
| 177 return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry); | 181 return DirectoryItemTreeBaseMethods.searchAndSelectByEntry.call(this, entry); |
| 178 }; | 182 }; |
| 179 | 183 |
| 180 /** | 184 /** |
| 185 * @param {string} label Localized label for this item. | |
| 181 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. | 186 * @param {DirectoryEntry} dirEntry DirectoryEntry of this item. |
| 182 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. | 187 * @param {DirectoryItem|DirectoryTree} parentDirItem Parent of this item. |
| 183 * @param {DirectoryTree} tree Current tree, which contains this item. | 188 * @param {DirectoryTree} tree Current tree, which contains this item. |
| 184 */ | 189 */ |
| 185 DirectoryItem.prototype.decorate = function( | 190 DirectoryItem.prototype.decorate = function( |
| 186 dirEntry, parentDirItem, tree) { | 191 label, dirEntry, parentDirItem, tree) { |
| 187 this.className = 'tree-item'; | 192 this.className = 'tree-item'; |
| 188 this.innerHTML = | 193 this.innerHTML = |
| 189 '<div class="tree-row">' + | 194 '<div class="tree-row">' + |
| 190 ' <span class="expand-icon"></span>' + | 195 ' <span class="expand-icon"></span>' + |
| 191 ' <span class="icon"></span>' + | 196 ' <span class="icon"></span>' + |
| 192 ' <span class="label"></span>' + | 197 ' <span class="label"></span>' + |
| 193 '</div>' + | 198 '</div>' + |
| 194 '<div class="tree-children"></div>'; | 199 '<div class="tree-children"></div>'; |
| 195 this.setAttribute('role', 'treeitem'); | 200 this.setAttribute('role', 'treeitem'); |
| 196 | 201 |
| 197 this.parentTree_ = tree; | 202 this.parentTree_ = tree; |
| 198 this.directoryModel_ = tree.directoryModel; | 203 this.directoryModel_ = tree.directoryModel; |
| 199 this.parent_ = parentDirItem; | 204 this.parent_ = parentDirItem; |
| 200 this.label = dirEntry.label || dirEntry.name; | 205 this.label = label; |
| 201 this.fullPath = dirEntry.fullPath; | 206 this.fullPath = dirEntry.fullPath; |
| 202 this.dirEntry_ = dirEntry; | 207 this.dirEntry_ = dirEntry; |
| 203 this.fileFilter_ = this.directoryModel_.getFileFilter(); | 208 this.fileFilter_ = this.directoryModel_.getFileFilter(); |
| 204 | 209 |
| 205 // Sets hasChildren=false tentatively. This will be overridden after | 210 // Sets hasChildren=false tentatively. This will be overridden after |
| 206 // scanning sub-directories in DirectoryTreeUtil.updateSubElementsFromList. | 211 // scanning sub-directories in DirectoryTreeUtil.updateSubElementsFromList. |
| 207 this.hasChildren = false; | 212 this.hasChildren = false; |
| 208 | 213 |
| 209 this.addEventListener('expand', this.onExpand_.bind(this), false); | 214 this.addEventListener('expand', this.onExpand_.bind(this), false); |
| 210 var icon = this.querySelector('.icon'); | 215 var icon = this.querySelector('.icon'); |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 } | 509 } |
| 505 }.bind(this)); | 510 }.bind(this)); |
| 506 | 511 |
| 507 this.privateOnDirectoryChangedBound_ = | 512 this.privateOnDirectoryChangedBound_ = |
| 508 this.onDirectoryContentChanged_.bind(this); | 513 this.onDirectoryContentChanged_.bind(this); |
| 509 chrome.fileBrowserPrivate.onDirectoryChanged.addListener( | 514 chrome.fileBrowserPrivate.onDirectoryChanged.addListener( |
| 510 this.privateOnDirectoryChangedBound_); | 515 this.privateOnDirectoryChangedBound_); |
| 511 | 516 |
| 512 this.scrollBar_ = MainPanelScrollBar(); | 517 this.scrollBar_ = MainPanelScrollBar(); |
| 513 this.scrollBar_.initialize(this.parentNode, this); | 518 this.scrollBar_.initialize(this.parentNode, this); |
| 514 | |
| 515 // Once, draws the list with the fake '/drive/' entry. | |
| 516 this.redraw(false /* recursive */); | |
| 517 // Resolves 'My Drive' entry and replaces the fake with the true one. | |
| 518 this.maybeResolveMyDriveRoot_(function() { | |
| 519 // After the true entry is resolved, draws the list again. | |
| 520 this.redraw(true /* recursive */); | |
| 521 }.bind(this)); | |
| 522 }; | 519 }; |
| 523 | 520 |
| 524 /** | 521 /** |
| 525 * Select the item corresponding to the given entry. | 522 * Select the item corresponding to the given entry. |
| 526 * @param {DirectoryEntry|Object} entry The directory entry to be selected. Can | 523 * @param {DirectoryEntry|Object} entry The directory entry to be selected. Can |
| 527 * be a fake. | 524 * be a fake. |
| 528 */ | 525 */ |
| 529 DirectoryTree.prototype.selectByEntry = function(entry) { | 526 DirectoryTree.prototype.selectByEntry = function(entry) { |
| 530 // If the target directory is not in the tree, do nothing. | 527 // If the target directory is not in the tree, do nothing. |
| 531 if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(entry.fullPath)) | 528 if (!DirectoryTreeUtil.isEligiblePathForDirectoryTree(entry.fullPath)) |
| 532 return; | 529 return; |
| 533 | 530 |
| 534 this.maybeResolveMyDriveRoot_(function() { | 531 var volumeInfo = this.volumeManager_.getVolumeInfo(entry); |
| 535 if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry)) | 532 if (this.selectedItem && util.isSameEntry(entry, this.selectedItem.entry)) |
| 536 return; | 533 return; |
| 537 | 534 |
| 538 if (this.searchAndSelectByEntry(entry)) | 535 if (this.searchAndSelectByEntry(entry)) |
| 539 return; | 536 return; |
| 540 | 537 |
| 541 this.selectedItem = null; | 538 this.updateSubDirectories(false /* recursive */); |
| 542 this.updateSubDirectories( | 539 // TODO(yoshiki, mtomasz): There may be a race in here. |
| 543 false /* recursive */, | 540 volumeInfo.resolveDisplayRoot(function() { |
| 544 // Success callback, failure is not handled. | 541 if (!this.searchAndSelectByEntry(entry)) |
| 545 function() { | 542 this.selectedItem = null; |
| 546 if (!this.searchAndSelectByEntry(entry)) | |
| 547 this.selectedItem = null; | |
| 548 }.bind(this)); | |
| 549 }.bind(this)); | 543 }.bind(this)); |
| 550 }; | 544 }; |
| 551 | 545 |
| 552 /** | 546 /** |
| 553 * Resolves the My Drive root's entry, if it is a fake. If the entry is already | 547 * Retrieves the latest subdirectories and update them on the tree. |
| 554 * resolved to a DirectoryEntry, completionCallback() will be called | 548 * |
| 555 * immediately. | 549 * @param {boolean} recursive True if the update is recursively. |
| 556 * @param {function()} completionCallback Called when the resolving is | 550 * @param {function()=} opt_callback Called when subdirectories are fully |
| 557 * done (or the entry is already resolved), regardless if it is | 551 * updated. |
| 558 * successfully done or not. | |
| 559 * @private | |
| 560 */ | 552 */ |
| 561 DirectoryTree.prototype.maybeResolveMyDriveRoot_ = function( | 553 DirectoryTree.prototype.updateSubDirectories = function( |
|
yoshiki
2014/01/15 07:33:13
Could you change the method name? Or change the na
mtomasz
2014/01/16 01:31:58
There is no defined interface @interface, not this
yoshiki
2014/01/17 01:57:52
OK. I agree with you.
| |
| 562 completionCallback) { | 554 recursive, opt_callback) { |
| 563 var myDriveItem = this.items[0]; | 555 var callback = opt_callback || function() {}; |
| 564 if (!myDriveItem || !util.isFakeEntry(myDriveItem.entry)) { | 556 this.entries_ = []; |
| 565 // The entry is already resolved. Don't need to try again. | 557 |
| 566 completionCallback(); | 558 var compareEntries = function(a, b) { |
| 567 return; | 559 return a.toURL() < b.toURL(); |
| 560 }; | |
| 561 | |
| 562 // Add fakes (if any). | |
| 563 for (var key in this.currentVolumeInfo_.fakeEntries) { | |
| 564 this.entries_.push(this.currentVolumeInfo_.fakeEntries[key]); | |
| 568 } | 565 } |
| 569 | 566 |
| 570 // The entry is a fake. | 567 // If the display root is not available yet, then redraw anyway with what |
| 571 this.directoryModel_.resolveDirectory( | 568 // we have. However, concurrently try to resolve the display root and then |
| 572 myDriveItem.fullPath, | 569 // redraw. |
| 573 function(entry) { | 570 if (!this.currentVolumeInfo_.displayRoot) { |
| 574 if (!util.isFakeEntry(entry)) | 571 this.entries_.sort(compareEntries); |
| 575 myDriveItem.dirEntry_ = entry; | 572 this.redraw(recursive); |
| 573 } | |
| 576 | 574 |
| 577 completionCallback(); | 575 this.currentVolumeInfo_.resolveDisplayRoot(function(displayRoot) { |
| 578 }, | 576 this.entries_.push(this.currentVolumeInfo_.displayRoot); |
| 579 completionCallback); | 577 this.entries_.sort(compareEntries); |
| 578 this.redraw(recursive); // Redraw. | |
| 579 callback(); | |
| 580 }.bind(this), callback /* Ignore errors. */); | |
| 580 }; | 581 }; |
| 581 | 582 |
| 582 /** | 583 /** |
| 583 * Retrieves the latest subdirectories and update them on the tree. | |
| 584 * @param {boolean} recursive True if the update is recursively. | |
| 585 * @param {function()=} opt_successCallback Callback called on success. | |
| 586 * @param {function()=} opt_errorCallback Callback called on error. | |
| 587 */ | |
| 588 DirectoryTree.prototype.updateSubDirectories = function( | |
| 589 recursive, opt_successCallback, opt_errorCallback) { | |
| 590 var hasFakeEntries = this.currentVolumeInfo_ && | |
| 591 this.currentVolumeInfo_.volumeType === util.VolumeType.DRIVE; | |
| 592 this.entries_ = hasFakeEntries ? [ | |
| 593 this.currentVolumeInfo_.fakeEntries[RootType.DRIVE], | |
| 594 this.currentVolumeInfo_.fakeEntries[RootType.DRIVE_OFFLINE], | |
| 595 this.currentVolumeInfo_.fakeEntries[RootType.DRIVE_SHARED_WITH_ME], | |
| 596 this.currentVolumeInfo_.fakeEntries[RootType.DRIVE_RECENT] | |
| 597 ] : []; | |
| 598 | |
| 599 this.redraw(recursive); | |
| 600 if (opt_successCallback) | |
| 601 opt_successCallback(); | |
| 602 }; | |
| 603 | |
| 604 /** | |
| 605 * Redraw the list. | 584 * Redraw the list. |
| 606 * @param {boolean} recursive True if the update is recursively. False if the | 585 * @param {boolean} recursive True if the update is recursively. False if the |
| 607 * only root items are updated. | 586 * only root items are updated. |
| 608 */ | 587 */ |
| 609 DirectoryTree.prototype.redraw = function(recursive) { | 588 DirectoryTree.prototype.redraw = function(recursive) { |
| 610 this.updateSubElementsFromList(recursive); | 589 this.updateSubElementsFromList(recursive); |
| 611 }; | 590 }; |
| 612 | 591 |
| 613 /** | 592 /** |
| 614 * Invoked when the filter is changed. | 593 * Invoked when the filter is changed. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 660 this.style.paddingBottom = margin + 'px'; | 639 this.style.paddingBottom = margin + 'px'; |
| 661 this.scrollBar_.setBottomMarginForPanel(margin); | 640 this.scrollBar_.setBottomMarginForPanel(margin); |
| 662 }; | 641 }; |
| 663 | 642 |
| 664 /** | 643 /** |
| 665 * Updates the UI after the layout has changed. | 644 * Updates the UI after the layout has changed. |
| 666 */ | 645 */ |
| 667 DirectoryTree.prototype.relayout = function() { | 646 DirectoryTree.prototype.relayout = function() { |
| 668 cr.dispatchSimpleEvent(this, 'relayout'); | 647 cr.dispatchSimpleEvent(this, 'relayout'); |
| 669 }; | 648 }; |
| OLD | NEW |