Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / resources / FileSystemView.js
blobb34f34d1b9b606db2dd9f7cfb7fa128c00c6c77e
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  */
31 /**
32  * @constructor
33  * @extends {WebInspector.SplitWidget}
34  * @param {!WebInspector.FileSystemModel.FileSystem} fileSystem
35  */
36 WebInspector.FileSystemView = function(fileSystem)
38     WebInspector.SplitWidget.call(this, true, false, "fileSystemViewSplitViewState");
39     this.element.classList.add("file-system-view", "storage-view");
41     var vbox = new WebInspector.VBox();
42     vbox.element.classList.add("sidebar");
43     this._directoryTree = new TreeOutline();
44     this._directoryTree.element.classList.add("outline-disclosure", "filesystem-directory-tree");
45     vbox.element.appendChild(this._directoryTree.element);
46     this.setSidebarWidget(vbox);
48     var rootItem = new WebInspector.FileSystemView.EntryTreeElement(this, fileSystem.root);
49     rootItem.expanded = true;
50     this._directoryTree.appendChild(rootItem);
51     this._visibleView = null;
53     this._refreshButton = new WebInspector.ToolbarButton(WebInspector.UIString("Refresh"), "refresh-toolbar-item");
54     this._refreshButton.setVisible(true);
55     this._refreshButton.addEventListener("click", this._refresh, this);
57     this._deleteButton = new WebInspector.ToolbarButton(WebInspector.UIString("Delete"), "delete-toolbar-item");
58     this._deleteButton.setVisible(true);
59     this._deleteButton.addEventListener("click", this._confirmDelete, this);
62 WebInspector.FileSystemView.prototype = {
63     /**
64      * @return {!Array.<!WebInspector.ToolbarItem>}
65      */
66     toolbarItems: function()
67     {
68         return [this._refreshButton, this._deleteButton];
69     },
71     /**
72      * @type {!WebInspector.Widget}
73      */
74     get visibleView()
75     {
76         return this._visibleView;
77     },
79     /**
80      * @param {!WebInspector.Widget} view
81      */
82     showView: function(view)
83     {
84         if (this._visibleView === view)
85             return;
86         if (this._visibleView)
87             this._visibleView.detach();
88         this._visibleView = view;
89         this.setMainWidget(view);
90     },
92     _refresh: function()
93     {
94         this._directoryTree.firstChild().refresh();
95     },
97     _confirmDelete: function()
98     {
99         if (confirm(WebInspector.UIString("Are you sure you want to delete the selected entry?")))
100             this._delete();
101     },
103     _delete: function()
104     {
105         this._directoryTree.selectedTreeElement.deleteEntry();
106     },
108     __proto__: WebInspector.SplitWidget.prototype
112  * @constructor
113  * @extends {TreeElement}
114  * @param {!WebInspector.FileSystemView} fileSystemView
115  * @param {!WebInspector.FileSystemModel.Entry} entry
116  */
117 WebInspector.FileSystemView.EntryTreeElement = function(fileSystemView, entry)
119     TreeElement.call(this, entry.name, entry.isDirectory);
121     this._entry = entry;
122     this._fileSystemView = fileSystemView;
125 WebInspector.FileSystemView.EntryTreeElement.prototype = {
126     /**
127      * @override
128      */
129     onattach: function()
130     {
131         var selection = this.listItemElement.createChild("div", "selection");
132         this.listItemElement.insertBefore(selection, this.listItemElement.firstChild);
133     },
135     /**
136      * @override
137      * @return {boolean}
138      */
139     onselect: function()
140     {
141         if (!this._view) {
142             if (this._entry.isDirectory)
143                 this._view = new WebInspector.DirectoryContentView();
144             else {
145                 var file = /** @type {!WebInspector.FileSystemModel.File} */ (this._entry);
146                 this._view = new WebInspector.FileContentView(file);
147             }
148         }
149         this._fileSystemView.showView(this._view);
150         this.refresh();
151         return false;
152     },
154     /**
155      * @override
156      */
157     onpopulate: function()
158     {
159         this.refresh();
160     },
162     /**
163      * @param {number} errorCode
164      * @param {!Array.<!WebInspector.FileSystemModel.Entry>=} entries
165      */
166     _directoryContentReceived: function(errorCode, entries)
167     {
168         WebInspector.userMetrics.FileSystemDirectoryContentReceived.record();
169         if (errorCode === FileError.NOT_FOUND_ERR) {
170             if (this.parent)
171                 this.parent.refresh();
172             return;
173         }
175         if (errorCode !== 0 || !entries) {
176             console.error("Failed to read directory: " + errorCode);
177             return;
178         }
180         entries.sort(WebInspector.FileSystemModel.Entry.compare);
181         if (this._view)
182             this._view.showEntries(entries);
184         var oldChildren = this.children().slice(0);
186         var newEntryIndex = 0;
187         var oldChildIndex = 0;
188         var currentTreeItem = 0;
189         while (newEntryIndex < entries.length && oldChildIndex < oldChildren.length) {
190             var newEntry = entries[newEntryIndex];
191             var oldChild = oldChildren[oldChildIndex];
192             var order = newEntry.name.compareTo(oldChild._entry.name);
194             if (order === 0) {
195                 if (oldChild._entry.isDirectory)
196                     oldChild.invalidateChildren();
197                 else
198                     oldChild.refresh();
200                 ++newEntryIndex;
201                 ++oldChildIndex;
202                 ++currentTreeItem;
203                 continue;
204             }
205             if (order < 0) {
206                 this.insertChild(new WebInspector.FileSystemView.EntryTreeElement(this._fileSystemView, newEntry), currentTreeItem);
207                 ++newEntryIndex;
208                 ++currentTreeItem;
209                 continue;
210             }
212             this.removeChildAtIndex(currentTreeItem);
213             ++oldChildIndex;
214         }
215         for (; newEntryIndex < entries.length; ++newEntryIndex)
216             this.appendChild(new WebInspector.FileSystemView.EntryTreeElement(this._fileSystemView, entries[newEntryIndex]));
218         for (; oldChildIndex < oldChildren.length; ++oldChildIndex)
219             this.removeChild(oldChildren[oldChildIndex]);
220     },
222     refresh: function()
223     {
224         if (!this._entry.isDirectory) {
225             if (this._view && this._view === this._fileSystemView.visibleView) {
226                 var fileContentView = /** @type {!WebInspector.FileContentView} */ (this._view);
227                 fileContentView.refresh();
228             }
229         } else
230             this._entry.requestDirectoryContent(this._directoryContentReceived.bind(this));
231     },
233     deleteEntry: function()
234     {
235         this._entry.deleteEntry(this._deletionCompleted.bind(this));
236     },
238     _deletionCompleted: function()
239     {
240         if (this._entry != this._entry.fileSystem.root)
241             this.parent.refresh();
242     },
244     __proto__: TreeElement.prototype