• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31/**
32 * @constructor
33 * @extends {WebInspector.SplitView}
34 * @param {!WebInspector.FileSystemModel.FileSystem} fileSystem
35 */
36WebInspector.FileSystemView = function(fileSystem)
37{
38    WebInspector.SplitView.call(this, true, false, "fileSystemViewSplitViewState");
39    this.element.classList.add("file-system-view");
40    this.element.classList.add("storage-view");
41
42    var directoryTreeElement = this.element.createChild("ol", "filesystem-directory-tree");
43    this._directoryTree = new TreeOutline(directoryTreeElement);
44    this.sidebarElement().appendChild(directoryTreeElement);
45    this.sidebarElement().classList.add("outline-disclosure", "sidebar");
46
47    var rootItem = new WebInspector.FileSystemView.EntryTreeElement(this, fileSystem.root);
48    rootItem.expanded = true;
49    this._directoryTree.appendChild(rootItem);
50    this._visibleView = null;
51
52    this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
53    this._refreshButton.visible = true;
54    this._refreshButton.addEventListener("click", this._refresh, this);
55
56    this._deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
57    this._deleteButton.visible = true;
58    this._deleteButton.addEventListener("click", this._confirmDelete, this);
59}
60
61WebInspector.FileSystemView.prototype = {
62    /**
63     * @type {!Array.<!Element>}
64     */
65    get statusBarItems()
66    {
67        return [this._refreshButton.element, this._deleteButton.element];
68    },
69
70    /**
71     * @type {!WebInspector.View}
72     */
73    get visibleView()
74    {
75        return this._visibleView;
76    },
77
78    /**
79     * @param {!WebInspector.View} view
80     */
81    showView: function(view)
82    {
83        if (this._visibleView === view)
84            return;
85        if (this._visibleView)
86            this._visibleView.detach();
87        this._visibleView = view;
88        view.show(this.mainElement());
89    },
90
91    _refresh: function()
92    {
93        this._directoryTree.children[0].refresh();
94    },
95
96    _confirmDelete: function()
97    {
98        if (confirm(WebInspector.UIString("Are you sure you want to delete the selected entry?")))
99            this._delete();
100    },
101
102    _delete: function()
103    {
104        this._directoryTree.selectedTreeElement.deleteEntry();
105    },
106
107    __proto__: WebInspector.SplitView.prototype
108}
109
110/**
111 * @constructor
112 * @extends {TreeElement}
113 * @param {!WebInspector.FileSystemView} fileSystemView
114 * @param {!WebInspector.FileSystemModel.Entry} entry
115 */
116WebInspector.FileSystemView.EntryTreeElement = function(fileSystemView, entry)
117{
118    TreeElement.call(this, entry.name, null, entry.isDirectory);
119
120    this._entry = entry;
121    this._fileSystemView = fileSystemView;
122}
123
124WebInspector.FileSystemView.EntryTreeElement.prototype = {
125    /**
126     * @override
127     */
128    onattach: function()
129    {
130        var selection = this.listItemElement.createChild("div", "selection");
131        this.listItemElement.insertBefore(selection, this.listItemElement.firstChild);
132    },
133
134    /**
135     * @override
136     * @return {boolean}
137     */
138    onselect: function()
139    {
140        if (!this._view) {
141            if (this._entry.isDirectory)
142                this._view = new WebInspector.DirectoryContentView();
143            else {
144                var file = /** @type {!WebInspector.FileSystemModel.File} */ (this._entry);
145                this._view = new WebInspector.FileContentView(file);
146            }
147        }
148        this._fileSystemView.showView(this._view);
149        this.refresh();
150        return false;
151    },
152
153    /**
154     * @override
155     */
156    onpopulate: function()
157    {
158        this.refresh();
159    },
160
161    /**
162     * @param {number} errorCode
163     * @param {!Array.<!WebInspector.FileSystemModel.Entry>=} entries
164     */
165    _directoryContentReceived: function(errorCode, entries)
166    {
167        if (errorCode === FileError.NOT_FOUND_ERR) {
168            if (this.parent !== this.treeOutline)
169                this.parent.refresh();
170            return;
171        }
172
173        if (errorCode !== 0 || !entries) {
174            console.error("Failed to read directory: " + errorCode);
175            return;
176        }
177
178        entries.sort(WebInspector.FileSystemModel.Entry.compare);
179        if (this._view)
180            this._view.showEntries(entries);
181
182        var oldChildren = this.children.slice(0);
183
184        var newEntryIndex = 0;
185        var oldChildIndex = 0;
186        var currentTreeItem = 0;
187        while (newEntryIndex < entries.length && oldChildIndex < oldChildren.length) {
188            var newEntry = entries[newEntryIndex];
189            var oldChild = oldChildren[oldChildIndex];
190            var order = newEntry.name.compareTo(oldChild._entry.name);
191
192            if (order === 0) {
193                if (oldChild._entry.isDirectory)
194                    oldChild.shouldRefreshChildren = true;
195                else
196                    oldChild.refresh();
197
198                ++newEntryIndex;
199                ++oldChildIndex;
200                ++currentTreeItem;
201                continue;
202            }
203            if (order < 0) {
204                this.insertChild(new WebInspector.FileSystemView.EntryTreeElement(this._fileSystemView, newEntry), currentTreeItem);
205                ++newEntryIndex;
206                ++currentTreeItem;
207                continue;
208            }
209
210            this.removeChildAtIndex(currentTreeItem);
211            ++oldChildIndex;
212        }
213        for (; newEntryIndex < entries.length; ++newEntryIndex)
214            this.appendChild(new WebInspector.FileSystemView.EntryTreeElement(this._fileSystemView, entries[newEntryIndex]));
215
216        for (; oldChildIndex < oldChildren.length; ++oldChildIndex)
217            this.removeChild(oldChildren[oldChildIndex]);
218    },
219
220    refresh: function()
221    {
222        if (!this._entry.isDirectory) {
223            if (this._view && this._view === this._fileSystemView.visibleView) {
224                var fileContentView = /** @type {!WebInspector.FileContentView} */ (this._view);
225                fileContentView.refresh();
226            }
227        } else
228            this._entry.requestDirectoryContent(this._directoryContentReceived.bind(this));
229    },
230
231    deleteEntry: function()
232    {
233        this._entry.deleteEntry(this._deletionCompleted.bind(this));
234    },
235
236    _deletionCompleted: function()
237    {
238        if (this._entry != this._entry.fileSystem.root)
239            this.parent.refresh();
240    },
241
242    __proto__: TreeElement.prototype
243}
244