Home | History | Annotate | Download | only in front-end
      1 /*
      2  * Copyright (C) 2007, 2008 Apple 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
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     14  *     its contributors may be used to endorse or promote products derived
     15  *     from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 WebInspector.SourceView = function(resource)
     30 {
     31     WebInspector.ResourceView.call(this, resource);
     32 
     33     this.element.addStyleClass("source");
     34 
     35     this.sourceFrame = new WebInspector.SourceFrame(this.contentElement, this._addBreakpoint.bind(this), this._removeBreakpoint.bind(this));
     36     resource.addEventListener("finished", this._resourceLoadingFinished, this);
     37     this._frameNeedsSetup = true;
     38 }
     39 
     40 WebInspector.SourceView.prototype = {
     41     show: function(parentElement)
     42     {
     43         WebInspector.ResourceView.prototype.show.call(this, parentElement);
     44         this.sourceFrame.visible = true;
     45         this.resize();
     46     },
     47 
     48     hide: function()
     49     {
     50         WebInspector.View.prototype.hide.call(this);
     51         this.sourceFrame.visible = false;
     52         this._currentSearchResultIndex = -1;
     53     },
     54 
     55     resize: function()
     56     {
     57         if (this.sourceFrame)
     58             this.sourceFrame.resize();
     59     },
     60 
     61     setupSourceFrameIfNeeded: function()
     62     {
     63         if (!this._frameNeedsSetup)
     64             return;
     65 
     66         this.attach();
     67 
     68         delete this._frameNeedsSetup;
     69         WebInspector.getResourceContent(this.resource.identifier, this._contentLoaded.bind(this));
     70     },
     71 
     72     contentTabSelected: function()
     73     {
     74         this.setupSourceFrameIfNeeded();
     75     },
     76 
     77     _contentLoaded: function(content)
     78     {
     79         this.sourceFrame.setContent(this.resource.mimeType, content, this.resource.url);
     80         this._sourceFrameSetupFinished();
     81     },
     82 
     83     _resourceLoadingFinished: function(event)
     84     {
     85         this._frameNeedsSetup = true;
     86         this._sourceFrameSetup = false;
     87         if (this.visible)
     88             this.setupSourceFrameIfNeeded();
     89         this.resource.removeEventListener("finished", this._resourceLoadingFinished, this);
     90     },
     91 
     92     _addBreakpoint: function(line)
     93     {
     94         var sourceID = null;
     95         var closestStartingLine = 0;
     96         var scripts = this.resource.scripts;
     97         for (var i = 0; i < scripts.length; ++i) {
     98             var script = scripts[i];
     99             if (script.startingLine <= line && script.startingLine >= closestStartingLine) {
    100                 closestStartingLine = script.startingLine;
    101                 sourceID = script.sourceID;
    102             }
    103         }
    104 
    105         if (WebInspector.panels.scripts) {
    106             var breakpoint = new WebInspector.Breakpoint(this.resource.url, line, sourceID);
    107             WebInspector.panels.scripts.addBreakpoint(breakpoint);
    108         }
    109     },
    110 
    111     _removeBreakpoint: function(breakpoint)
    112     {
    113         if (WebInspector.panels.scripts)
    114             WebInspector.panels.scripts.removeBreakpoint(breakpoint);
    115     },
    116 
    117     // The rest of the methods in this prototype need to be generic enough to work with a ScriptView.
    118     // The ScriptView prototype pulls these methods into it's prototype to avoid duplicate code.
    119 
    120     searchCanceled: function()
    121     {
    122         this._currentSearchResultIndex = -1;
    123         this._searchResults = [];
    124         this.sourceFrame.clearMarkedRange();
    125         delete this._delayedFindSearchMatches;
    126     },
    127 
    128     performSearch: function(query, finishedCallback)
    129     {
    130         // Call searchCanceled since it will reset everything we need before doing a new search.
    131         this.searchCanceled();
    132 
    133         this._searchFinishedCallback = finishedCallback;
    134 
    135         function findSearchMatches(query, finishedCallback)
    136         {
    137             this._searchResults = this.sourceFrame.findSearchMatches(query);
    138             if (this._searchResults)
    139                 finishedCallback(this, this._searchResults.length);
    140         }
    141 
    142         if (!this._sourceFrameSetup) {
    143             // The search is performed in _sourceFrameSetupFinished by calling _delayedFindSearchMatches.
    144             this._delayedFindSearchMatches = findSearchMatches.bind(this, query, finishedCallback);
    145             this.setupSourceFrameIfNeeded();
    146             return;
    147         }
    148 
    149         findSearchMatches.call(this, query, finishedCallback);
    150     },
    151 
    152     jumpToFirstSearchResult: function()
    153     {
    154         if (!this._searchResults || !this._searchResults.length)
    155             return;
    156         this._currentSearchResultIndex = 0;
    157         this._jumpToSearchResult(this._currentSearchResultIndex);
    158     },
    159 
    160     jumpToLastSearchResult: function()
    161     {
    162         if (!this._searchResults || !this._searchResults.length)
    163             return;
    164         this._currentSearchResultIndex = (this._searchResults.length - 1);
    165         this._jumpToSearchResult(this._currentSearchResultIndex);
    166     },
    167 
    168     jumpToNextSearchResult: function()
    169     {
    170         if (!this._searchResults || !this._searchResults.length)
    171             return;
    172         if (++this._currentSearchResultIndex >= this._searchResults.length)
    173             this._currentSearchResultIndex = 0;
    174         this._jumpToSearchResult(this._currentSearchResultIndex);
    175     },
    176 
    177     jumpToPreviousSearchResult: function()
    178     {
    179         if (!this._searchResults || !this._searchResults.length)
    180             return;
    181         if (--this._currentSearchResultIndex < 0)
    182             this._currentSearchResultIndex = (this._searchResults.length - 1);
    183         this._jumpToSearchResult(this._currentSearchResultIndex);
    184     },
    185 
    186     showingFirstSearchResult: function()
    187     {
    188         return (this._currentSearchResultIndex === 0);
    189     },
    190 
    191     showingLastSearchResult: function()
    192     {
    193         return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
    194     },
    195 
    196     revealLine: function(lineNumber)
    197     {
    198         this.setupSourceFrameIfNeeded();
    199         this.sourceFrame.revealLine(lineNumber);
    200     },
    201 
    202     highlightLine: function(lineNumber)
    203     {
    204         this.setupSourceFrameIfNeeded();
    205         this.sourceFrame.highlightLine(lineNumber);
    206     },
    207 
    208     addMessage: function(msg)
    209     {
    210         this.sourceFrame.addMessage(msg);
    211     },
    212 
    213     clearMessages: function()
    214     {
    215         this.sourceFrame.clearMessages();
    216     },
    217 
    218     _jumpToSearchResult: function(index)
    219     {
    220         var foundRange = this._searchResults[index];
    221         if (!foundRange)
    222             return;
    223 
    224         this.sourceFrame.markAndRevealRange(foundRange);
    225     },
    226 
    227     _sourceFrameSetupFinished: function()
    228     {
    229         this._sourceFrameSetup = true;
    230         this.resize();
    231         if (this._delayedFindSearchMatches) {
    232             this._delayedFindSearchMatches();
    233             delete this._delayedFindSearchMatches;
    234         }
    235     }
    236 }
    237 
    238 WebInspector.SourceView.prototype.__proto__ = WebInspector.ResourceView.prototype;
    239