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.
8 * Base item of NavigationListModel. Should not be created directly.
9 * @param {string} label Label.
12 function NavigationModelItem(label) {
16 NavigationModelItem.prototype = {
17 get label() { return this.label_; },
21 * Item of NavigationListModel for shortcuts.
23 * @param {string} label Label.
24 * @param {!DirectoryEntry} entry Entry. Cannot be null.
26 * @extends {NavigationModelItem}
28 function NavigationModelShortcutItem(label, entry) {
29 NavigationModelItem.call(this, label);
34 NavigationModelShortcutItem.prototype = {
35 __proto__: NavigationModelItem.prototype,
36 get entry() { return this.entry_; },
37 get isVolume() { return false; },
38 get isShortcut() { return true; }
42 * Item of NavigationListModel for volumes.
44 * @param {string} label Label.
45 * @param {!VolumeInfo} volumeInfo Volume info for the volume. Cannot be null.
47 * @extends {NavigationModelItem}
49 function NavigationModelVolumeItem(label, volumeInfo) {
50 NavigationModelItem.call(this, label);
51 this.volumeInfo_ = volumeInfo;
52 // Start resovling the display root because it is used
53 // for determining executability of commands.
54 this.volumeInfo_.resolveDisplayRoot(
55 function() {}, function() {});
59 NavigationModelVolumeItem.prototype = {
60 __proto__: NavigationModelItem.prototype,
61 get volumeInfo() { return this.volumeInfo_; },
62 get isVolume() { return true; },
63 get isShortcut() { return false; }
67 * A navigation list model. This model combines the 2 lists.
68 * @param {VolumeManagerWrapper} volumeManager VolumeManagerWrapper instance.
69 * @param {cr.ui.ArrayDataModel} shortcutListModel The list of folder shortcut.
71 * @extends {cr.EventTarget}
73 function NavigationListModel(volumeManager, shortcutListModel) {
74 cr.EventTarget.call(this);
76 this.volumeManager_ = volumeManager;
77 this.shortcutListModel_ = shortcutListModel;
79 var volumeInfoToModelItem = function(volumeInfo) {
80 return new NavigationModelVolumeItem(
85 var entryToModelItem = function(entry) {
86 var item = new NavigationModelShortcutItem(
93 * Type of updated list.
101 Object.freeze(ListType);
103 // Generates this.volumeList_ and this.shortcutList_ from the models.
105 this.volumeManager_.volumeInfoList.slice().map(volumeInfoToModelItem);
107 this.shortcutList_ = [];
108 for (var i = 0; i < this.shortcutListModel_.length; i++) {
109 var shortcutEntry = this.shortcutListModel_.item(i);
110 var volumeInfo = this.volumeManager_.getVolumeInfo(shortcutEntry);
111 this.shortcutList_.push(entryToModelItem(shortcutEntry));
114 // Generates a combined 'permuted' event from an event of either list.
115 var permutedHandler = function(listType, event) {
118 // Build the volumeList.
119 if (listType == ListType.VOLUME_LIST) {
120 // The volume is mounted or unmounted.
123 // Use the old instances if they just move.
124 for (var i = 0; i < event.permutation.length; i++) {
125 if (event.permutation[i] >= 0)
126 newList[event.permutation[i]] = this.volumeList_[i];
129 // Create missing instances.
130 for (var i = 0; i < event.newLength; i++) {
132 newList[i] = volumeInfoToModelItem(
133 this.volumeManager_.volumeInfoList.item(i));
136 this.volumeList_ = newList;
138 permutation = event.permutation.slice();
140 // shortcutList part has not been changed, so the permutation should be
141 // just identity mapping with a shift.
142 for (var i = 0; i < this.shortcutList_.length; i++) {
143 permutation.push(i + this.volumeList_.length);
146 // Build the shortcutList.
148 // volumeList part has not been changed, so the permutation should be
152 for (var i = 0; i < this.volumeList_.length; i++) {
157 var oldListIndex = 0;
159 while (modelIndex < this.shortcutListModel_.length &&
160 oldListIndex < this.shortcutList_.length) {
161 var shortcutEntry = this.shortcutListModel_.item(modelIndex);
162 var cmp = this.shortcutListModel_.compare(
163 shortcutEntry, this.shortcutList_[oldListIndex].entry);
165 // The shortcut at shortcutList_[oldListIndex] is removed.
166 permutation.push(-1);
172 // Reuse the old instance.
173 permutation.push(newList.length + this.volumeList_.length);
174 newList.push(this.shortcutList_[oldListIndex]);
177 // We needs to create a new instance for the shortcut entry.
178 newList.push(entryToModelItem(shortcutEntry));
183 // Add remaining (new) shortcuts if necessary.
184 for (; modelIndex < this.shortcutListModel_.length; modelIndex++) {
185 var shortcutEntry = this.shortcutListModel_.item(modelIndex);
186 newList.push(entryToModelItem(shortcutEntry));
189 // Fill remaining permutation if necessary.
190 for (; oldListIndex < this.shortcutList_.length; oldListIndex++)
191 permutation.push(-1);
193 this.shortcutList_ = newList;
196 // Dispatch permuted event.
197 var permutedEvent = new Event('permuted');
198 permutedEvent.newLength =
199 this.volumeList_.length + this.shortcutList_.length;
200 permutedEvent.permutation = permutation;
201 this.dispatchEvent(permutedEvent);
204 this.volumeManager_.volumeInfoList.addEventListener(
205 'permuted', permutedHandler.bind(this, ListType.VOLUME_LIST));
206 this.shortcutListModel_.addEventListener(
207 'permuted', permutedHandler.bind(this, ListType.SHORTCUT_LIST));
209 // 'change' event is just ignored, because it is not fired neither in
210 // the folder shortcut list nor in the volume info list.
211 // 'splice' and 'sorted' events are not implemented, since they are not used
216 * NavigationList inherits cr.EventTarget.
218 NavigationListModel.prototype = {
219 __proto__: cr.EventTarget.prototype,
220 get length() { return this.length_(); },
221 get folderShortcutList() { return this.shortcutList_; }
225 * Returns the item at the given index.
226 * @param {number} index The index of the entry to get.
227 * @return {NavigationModelItem} The item at the given index.
229 NavigationListModel.prototype.item = function(index) {
230 var offset = this.volumeList_.length;
232 return this.volumeList_[index];
233 return this.shortcutList_[index - offset];
237 * Returns the number of items in the model.
238 * @return {number} The length of the model.
241 NavigationListModel.prototype.length_ = function() {
242 return this.volumeList_.length + this.shortcutList_.length;
246 * Returns the first matching item.
247 * @param {NavigationModelItem} modelItem The entry to find.
248 * @param {number=} opt_fromIndex If provided, then the searching start at
249 * the {@code opt_fromIndex}.
250 * @return {number} The index of the first found element or -1 if not found.
252 NavigationListModel.prototype.indexOf = function(modelItem, opt_fromIndex) {
253 for (var i = opt_fromIndex || 0; i < this.length; i++) {
254 if (modelItem === this.item(i))
261 * Called externally when one od the items is not found on the filesystem.
262 * @param {NavigationModelItem} modelItem The entry which is not found.
264 NavigationListModel.prototype.onItemNotFoundError = function(modelItem) {
265 if (modelItem.isVolume) {
266 // TODO(mtomasz, yoshiki): Implement when needed.
269 if (modelItem.isShortcut) {
270 // For shortcuts, lets the shortcut model handle this situation.
271 this.shortcutListModel_.onItemNotFoundError(modelItem.entry);