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 |