2008-03-26 Timothy Hatcher <timothy@apple.com>
[WebKit-https.git] / WebCore / page / inspector / SourceView.js
1 /*
2  * Copyright (C) 2007 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.SourcePanel = function(resource, views)
30 {
31     var allViews = [{ title: WebInspector.UIString("Source"), name: "source" }];
32     if (views)
33         allViews = allViews.concat(views);
34
35     WebInspector.ResourcePanel.call(this, resource, allViews);
36
37     this.currentView = this.views.source;
38
39     var sourceView = this.views.source;
40
41     sourceView.messages = [];
42     sourceView.frameNeedsSetup = true;
43
44     sourceView.frameElement = document.createElement("iframe");
45     sourceView.frameElement.setAttribute("viewsource", "true");
46     sourceView.contentElement.appendChild(sourceView.frameElement);
47 }
48
49 WebInspector.SourcePanel.prototype = {
50     show: function()
51     {
52         WebInspector.ResourcePanel.prototype.show.call(this);
53         this.setupSourceFrameIfNeeded();
54     },
55
56     setupSourceFrameIfNeeded: function()
57     {
58         if (this.views.source.frameNeedsSetup) {
59             this.attach();
60
61             InspectorController.addSourceToFrame(this.resource.identifier, this.views.source.frameElement);
62             WebInspector.addMainEventListeners(this.views.source.frameElement.contentDocument);
63
64             var length = this.views.source.messages;
65             for (var i = 0; i < length; ++i)
66                 this._addMessageToSource(this.views.source.messages[i]);
67
68             delete this.views.source.frameNeedsSetup;
69         }
70     },
71
72     sourceRow: function(lineNumber)
73     {
74         this.setupSourceFrameIfNeeded();
75
76         var doc = this.views.source.frameElement.contentDocument;
77         var rows = doc.getElementsByTagName("table")[0].rows;
78
79         // Line numbers are a 1-based index, but the rows collection is 0-based.
80         --lineNumber;
81         if (lineNumber >= rows.length)
82             lineNumber = rows.length - 1;
83
84         return rows[lineNumber];
85     },
86
87     showSourceLine: function(lineNumber)
88     {
89         var row = this.sourceRow(lineNumber);
90         if (!row)
91             return;
92         this.currentView = this.views.source;
93         row.scrollIntoViewIfNeeded(true);
94     },
95
96     addMessageToSource: function(msg)
97     {
98         this.views.source.messages.push(msg);
99         if (!this.views.source.frameNeedsSetup)
100             this._addMessageToSource(msg);
101     },
102
103     _addMessageToSource: function(msg)
104     {
105         var row = this.sourceRow(msg.line);
106         if (!row)
107             return;
108
109         var doc = this.views.source.frameElement.contentDocument;
110         var cell = row.getElementsByTagName("td")[1];
111
112         var errorDiv = cell.lastChild;
113         if (!errorDiv || errorDiv.nodeName.toLowerCase() !== "div" || !errorDiv.hasStyleClass("webkit-html-message-bubble")) {
114             errorDiv = doc.createElement("div");
115             errorDiv.className = "webkit-html-message-bubble";
116             cell.appendChild(errorDiv);
117         }
118
119         var imageURL;
120         switch (msg.level) {
121             case WebInspector.ConsoleMessage.MessageLevel.Error:
122                 errorDiv.addStyleClass("webkit-html-error-message");
123                 imageURL = "Images/errorIcon.png";
124                 break;
125             case WebInspector.ConsoleMessage.MessageLevel.Warning:
126                 errorDiv.addStyleClass("webkit-html-warning-message");
127                 imageURL = "Images/warningIcon.png";
128                 break;
129         }
130
131         var lineDiv = doc.createElement("div");
132         lineDiv.className = "webkit-html-message-line";
133         errorDiv.appendChild(lineDiv);
134
135         var image = doc.createElement("img");
136         image.src = imageURL;
137         image.className = "webkit-html-message-icon";
138         lineDiv.appendChild(image);
139
140         lineDiv.appendChild(doc.createTextNode(msg.message));
141     }
142 }
143
144 WebInspector.SourcePanel.prototype.__proto__ = WebInspector.ResourcePanel.prototype;