Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / sources / UISourceCodeFrame.js
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  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC.
20  * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 /**
30  * @constructor
31  * @extends {WebInspector.SourceFrame}
32  * @param {!WebInspector.UISourceCode} uiSourceCode
33  */
34 WebInspector.UISourceCodeFrame = function(uiSourceCode)
35 {
36     this._uiSourceCode = uiSourceCode;
37     WebInspector.SourceFrame.call(this, this._uiSourceCode);
38     WebInspector.settings.textEditorAutocompletion.addChangeListener(this._enableAutocompletionIfNeeded, this);
39     this._enableAutocompletionIfNeeded();
40
41     this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyChanged, this);
42     this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this);
43     this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.SavedStateUpdated, this._onSavedStateUpdated, this);
44     this._updateStyle();
45 }
46
47 WebInspector.UISourceCodeFrame.prototype = {
48     /**
49      * @return {!WebInspector.UISourceCode}
50      */
51     uiSourceCode: function()
52     {
53         return this._uiSourceCode;
54     },
55
56     _enableAutocompletionIfNeeded: function()
57     {
58         this.textEditor.setCompletionDictionary(WebInspector.settings.textEditorAutocompletion.get() ? new WebInspector.SampleCompletionDictionary() : null);
59     },
60
61     wasShown: function()
62     {
63         WebInspector.SourceFrame.prototype.wasShown.call(this);
64         this._boundWindowFocused = this._windowFocused.bind(this);
65         this.element.ownerDocument.defaultView.addEventListener("focus", this._boundWindowFocused, false);
66         this._checkContentUpdated();
67     },
68
69     willHide: function()
70     {
71         WebInspector.SourceFrame.prototype.willHide.call(this);
72         this.element.ownerDocument.defaultView.removeEventListener("focus", this._boundWindowFocused, false);
73         delete this._boundWindowFocused;
74         this._uiSourceCode.removeWorkingCopyGetter();
75     },
76
77     /**
78      * @return {boolean}
79      */
80     canEditSource: function()
81     {
82         var projectType = this._uiSourceCode.project().type();
83         if (projectType === WebInspector.projectTypes.Service || projectType === WebInspector.projectTypes.Debugger || projectType === WebInspector.projectTypes.Formatter)
84             return false;
85         if (projectType === WebInspector.projectTypes.Network && this._uiSourceCode.contentType() === WebInspector.resourceTypes.Document)
86             return false;
87         return true;
88     },
89
90     _windowFocused: function(event)
91     {
92         this._checkContentUpdated();
93     },
94
95     _checkContentUpdated: function()
96     {
97         if (!this.loaded || !this.isShowing())
98             return;
99         this._uiSourceCode.checkContentUpdated();
100     },
101
102     commitEditing: function()
103     {
104         if (!this._uiSourceCode.isDirty())
105             return;
106
107         this._muteSourceCodeEvents = true;
108         this._uiSourceCode.commitWorkingCopy();
109         delete this._muteSourceCodeEvents;
110     },
111
112     onTextChanged: function(oldRange, newRange)
113     {
114         WebInspector.SourceFrame.prototype.onTextChanged.call(this, oldRange, newRange);
115         if (this._isSettingContent)
116             return;
117         this._muteSourceCodeEvents = true;
118         if (this._textEditor.isClean())
119             this._uiSourceCode.resetWorkingCopy();
120         else
121             this._uiSourceCode.setWorkingCopyGetter(this._textEditor.text.bind(this._textEditor));
122         delete this._muteSourceCodeEvents;
123     },
124
125     /**
126      * @param {!WebInspector.Event} event
127      */
128     _onWorkingCopyChanged: function(event)
129     {
130         if (this._muteSourceCodeEvents)
131             return;
132         this._innerSetContent(this._uiSourceCode.workingCopy());
133         this.onUISourceCodeContentChanged();
134     },
135
136     /**
137      * @param {!WebInspector.Event} event
138      */
139     _onWorkingCopyCommitted: function(event)
140     {
141         if (!this._muteSourceCodeEvents) {
142             this._innerSetContent(this._uiSourceCode.workingCopy());
143             this.onUISourceCodeContentChanged();
144         }
145         this._textEditor.markClean();
146         this._updateStyle();
147         WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
148             action: WebInspector.UserMetrics.UserActionNames.FileSaved,
149             url: this._uiSourceCode.url
150         });
151     },
152
153     /**
154      * @param {!WebInspector.Event} event
155      */
156     _onSavedStateUpdated: function(event)
157     {
158         this._updateStyle();
159     },
160
161     _updateStyle: function()
162     {
163         this.element.classList.toggle("source-frame-unsaved-committed-changes", this._uiSourceCode.hasUnsavedCommittedChanges());
164     },
165
166     onUISourceCodeContentChanged: function()
167     {
168     },
169
170     /**
171      * @param {string} content
172      */
173     _innerSetContent: function(content)
174     {
175         this._isSettingContent = true;
176         this.setContent(content);
177         delete this._isSettingContent;
178     },
179
180     populateTextAreaContextMenu: function(contextMenu, lineNumber)
181     {
182         WebInspector.SourceFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber);
183         contextMenu.appendApplicableItems(this._uiSourceCode);
184         contextMenu.appendSeparator();
185     },
186
187     /**
188      * @param {!Array.<!WebInspector.UISourceCodeFrame.Infobar|undefined>} infobars
189      */
190     attachInfobars: function(infobars)
191     {
192         for (var i = infobars.length - 1; i >= 0; --i) {
193             var infobar = infobars[i];
194             if (!infobar)
195                 continue;
196             this.element.insertBefore(infobar.element, this.element.children[0]);
197             infobar._attached(this);
198         }
199         this.doResize();
200     },
201
202     dispose: function()
203     {
204         WebInspector.settings.textEditorAutocompletion.removeChangeListener(this._enableAutocompletionIfNeeded, this);
205         this._textEditor.dispose();
206         this.detach();
207     },
208
209     __proto__: WebInspector.SourceFrame.prototype
210 }
211
212 /**
213  * @constructor
214  * @param {!WebInspector.UISourceCodeFrame.Infobar.Level} level
215  * @param {string} message
216  * @param {function()=} onDispose
217  */
218 WebInspector.UISourceCodeFrame.Infobar = function(level, message, onDispose)
219 {
220     this.element = createElementWithClass("div", "source-frame-infobar source-frame-infobar-" + level);
221     this._mainRow = this.element.createChild("div", "source-frame-infobar-main-row");
222     this._detailsContainer = this.element.createChild("span", "source-frame-infobar-details-container");
223
224     this._mainRow.createChild("span", "source-frame-infobar-icon");
225     this._mainRow.createChild("span", "source-frame-infobar-row-message").textContent = message;
226
227     this._toggleElement = this._mainRow.createChild("div", "source-frame-infobar-toggle link");
228     this._toggleElement.addEventListener("click", this._onToggleDetails.bind(this), false);
229
230     this._closeElement = this._mainRow.createChild("div", "close-button");
231     this._closeElement.addEventListener("click", this._onClose.bind(this), false);
232     this._onDispose = onDispose;
233
234     this._updateToggleElement();
235 }
236
237 /**
238  * @enum {string}
239  */
240 WebInspector.UISourceCodeFrame.Infobar.Level = {
241     Info: "info",
242     Warning: "warning",
243     Error: "error",
244 };
245
246 WebInspector.UISourceCodeFrame.Infobar.prototype = {
247     _onResize: function()
248     {
249         if (this._uiSourceCodeFrame)
250             this._uiSourceCodeFrame.doResize();
251     },
252
253     _onToggleDetails: function()
254     {
255         this._toggled = !this._toggled;
256         this._updateToggleElement();
257         this._onResize();
258     },
259
260     _onClose: function()
261     {
262         this.dispose();
263     },
264
265     _updateToggleElement: function()
266     {
267         this._toggleElement.textContent = this._toggled ? WebInspector.UIString("less") : WebInspector.UIString("more");
268         this._detailsContainer.classList.toggle("hidden", !this._toggled);
269     },
270
271     /**
272      * @param {!WebInspector.UISourceCodeFrame} uiSourceCodeFrame
273      */
274     _attached: function(uiSourceCodeFrame)
275     {
276         this._uiSourceCodeFrame = uiSourceCodeFrame;
277     },
278
279     /**
280      * @param {string=} message
281      * @return {!Element}
282      */
283     createDetailsRowMessage: function(message)
284     {
285         var infobarDetailsRow = this._detailsContainer.createChild("div", "source-frame-infobar-details-row");
286         var detailsRowMessage = infobarDetailsRow.createChild("span", "source-frame-infobar-row-message");
287         detailsRowMessage.textContent = message || "";
288         return detailsRowMessage;
289     },
290
291     dispose: function()
292     {
293         this.element.remove();
294         this._onResize();
295         delete this._uiSourceCodeFrame;
296         if (this._onDispose)
297             this._onDispose();
298     }
299 }