Home | History | Annotate | Download | only in resources
      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  */
     36 WebInspector.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 
     61 WebInspector.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  */
    116 WebInspector.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 
    124 WebInspector.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