Home | History | Annotate | Download | only in front_end
      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.SidebarView}
     34  * @param {WebInspector.FileSystemModel.FileSystem} fileSystem
     35  */
     36 WebInspector.FileSystemView = function(fileSystem)
     37 {
     38     WebInspector.SidebarView.call(this, WebInspector.SidebarView.SidebarPosition.Start, "FileSystemViewSidebarWidth");
     39     this.element.addStyleClass("file-system-view");
     40     this.element.addStyleClass("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.addStyleClass("outline-disclosure");
     46     this.sidebarElement.addStyleClass("sidebar");
     47 
     48     var rootItem = new WebInspector.FileSystemView.EntryTreeElement(this, fileSystem.root);
     49     rootItem.expanded = true;
     50     this._directoryTree.appendChild(rootItem);
     51     this._visibleView = null;
     52 
     53     this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
     54     this._refreshButton.visible = true;
     55     this._refreshButton.addEventListener("click", this._refresh, this);
     56 
     57     this._deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
     58     this._deleteButton.visible = true;
     59     this._deleteButton.addEventListener("click", this._confirmDelete, this);
     60 }
     61 
     62 WebInspector.FileSystemView.prototype = {
     63     /**
     64      * @type {Array.<Element>}
     65      */
     66     get statusBarItems()
     67     {
     68         return [this._refreshButton.element, this._deleteButton.element];
     69     },
     70 
     71     /**
     72      * @type {WebInspector.View}
     73      */
     74     get visibleView()
     75     {
     76         return this._visibleView;
     77     },
     78 
     79     /**
     80      * @param {WebInspector.View} 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         view.show(this.mainElement);
     90     },
     91 
     92     _refresh: function()
     93     {
     94         this._directoryTree.children[0].refresh();
     95     },
     96 
     97     _confirmDelete: function()
     98     {
     99         if (confirm(WebInspector.UIString("Are you sure you want to delete the selected entry?")))
    100             this._delete();
    101     },
    102 
    103     _delete: function()
    104     {
    105         this._directoryTree.selectedTreeElement.deleteEntry();
    106     },
    107 
    108     __proto__: WebInspector.SidebarView.prototype
    109 }
    110 
    111 /**
    112  * @constructor
    113  * @extends {TreeElement}
    114  * @param {WebInspector.FileSystemView} fileSystemView
    115  * @param {WebInspector.FileSystemModel.Entry} entry
    116  */
    117 WebInspector.FileSystemView.EntryTreeElement = function(fileSystemView, entry)
    118 {
    119     TreeElement.call(this, entry.name, null, entry.isDirectory);
    120 
    121     this._entry = entry;
    122     this._fileSystemView = fileSystemView;
    123 }
    124 
    125 WebInspector.FileSystemView.EntryTreeElement.prototype = {
    126     onattach: function()
    127     {
    128         var selection = this.listItemElement.createChild("div", "selection");
    129         this.listItemElement.insertBefore(selection, this.listItemElement.firstChild);
    130     },
    131 
    132     onselect: function()
    133     {
    134         if (!this._view) {
    135             if (this._entry.isDirectory)
    136                 this._view = new WebInspector.DirectoryContentView();
    137             else {
    138                 var file = /** @type {WebInspector.FileSystemModel.File} */ (this._entry);
    139                 this._view = new WebInspector.FileContentView(file);
    140             }
    141         }
    142         this._fileSystemView.showView(this._view);
    143         this.refresh();
    144     },
    145 
    146     onpopulate: function()
    147     {
    148         this.refresh();
    149     },
    150 
    151     /**
    152      * @param {number} errorCode
    153      * @param {Array.<WebInspector.FileSystemModel.Entry>=} entries
    154      */
    155     _directoryContentReceived: function(errorCode, entries)
    156     {
    157         if (errorCode === FileError.NOT_FOUND_ERR) {
    158             if (this.parent !== this.treeOutline)
    159                 this.parent.refresh();
    160             return;
    161         }
    162 
    163         if (errorCode !== 0 || !entries) {
    164             console.error("Failed to read directory: " + errorCode);
    165             return;
    166         }
    167 
    168         entries.sort(WebInspector.FileSystemModel.Entry.compare);
    169         if (this._view)
    170             this._view.showEntries(entries);
    171 
    172         var oldChildren = this.children.slice(0);
    173 
    174         var newEntryIndex = 0;
    175         var oldChildIndex = 0;
    176         var currentTreeItem = 0;
    177         while (newEntryIndex < entries.length && oldChildIndex < oldChildren.length) {
    178             var newEntry = entries[newEntryIndex];
    179             var oldChild = oldChildren[oldChildIndex];
    180             var order = newEntry.name.compareTo(oldChild._entry.name);
    181 
    182             if (order === 0) {
    183                 if (oldChild._entry.isDirectory)
    184                     oldChild.shouldRefreshChildren = true;
    185                 else
    186                     oldChild.refresh();
    187 
    188                 ++newEntryIndex;
    189                 ++oldChildIndex;
    190                 ++currentTreeItem;
    191                 continue;
    192             }
    193             if (order < 0) {
    194                 this.insertChild(new WebInspector.FileSystemView.EntryTreeElement(this._fileSystemView, newEntry), currentTreeItem);
    195                 ++newEntryIndex;
    196                 ++currentTreeItem;
    197                 continue;
    198             }
    199 
    200             this.removeChildAtIndex(currentTreeItem);
    201             ++oldChildIndex;
    202         }
    203         for (; newEntryIndex < entries.length; ++newEntryIndex)
    204             this.appendChild(new WebInspector.FileSystemView.EntryTreeElement(this._fileSystemView, entries[newEntryIndex]));
    205 
    206         for (; oldChildIndex < oldChildren.length; ++oldChildIndex)
    207             this.removeChild(oldChildren[oldChildIndex]);
    208     },
    209 
    210     refresh: function()
    211     {
    212         if (!this._entry.isDirectory) {
    213             if (this._view && this._view === this._fileSystemView.visibleView) {
    214                 var fileContentView = /** @type {WebInspector.FileContentView} */ (this._view);
    215                 fileContentView.refresh();
    216             }
    217         } else
    218             this._entry.requestDirectoryContent(this._directoryContentReceived.bind(this));
    219     },
    220 
    221     deleteEntry: function()
    222     {
    223         this._entry.deleteEntry(this._deletionCompleted.bind(this));
    224     },
    225 
    226     _deletionCompleted: function()
    227     {
    228         if (this._entry != this._entry.fileSystem.root)
    229             this.parent.refresh();
    230     },
    231 
    232     __proto__: TreeElement.prototype
    233 }
    234