• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
29WebInspector.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
40WebInspector.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
238WebInspector.SourceView.prototype.__proto__ = WebInspector.ResourceView.prototype;
239