Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / devtools / front_end / sources / UISourceCodeFrame.js
bloba6cdd620ad306077d3b56b422677a36ddb58f370
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  */
29 /**
30  * @constructor
31  * @extends {WebInspector.SourceFrame}
32  * @param {!WebInspector.UISourceCode} uiSourceCode
33  */
34 WebInspector.UISourceCodeFrame = function(uiSourceCode)
36     this._uiSourceCode = uiSourceCode;
37     WebInspector.SourceFrame.call(this, this._uiSourceCode);
38     this.textEditor.setAutocompleteDelegate(new WebInspector.SimpleAutocompleteDelegate());
40     this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._onWorkingCopyChanged, this);
41     this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._onWorkingCopyCommitted, this);
42     this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.SavedStateUpdated, this._onSavedStateUpdated, this);
43     this._updateStyle();
46 WebInspector.UISourceCodeFrame.prototype = {
47     /**
48      * @return {!WebInspector.UISourceCode}
49      */
50     uiSourceCode: function()
51     {
52         return this._uiSourceCode;
53     },
55     wasShown: function()
56     {
57         WebInspector.SourceFrame.prototype.wasShown.call(this);
58         this._boundWindowFocused = this._windowFocused.bind(this);
59         this.element.ownerDocument.defaultView.addEventListener("focus", this._boundWindowFocused, false);
60         this._checkContentUpdated();
61     },
63     willHide: function()
64     {
65         WebInspector.SourceFrame.prototype.willHide.call(this);
66         this.element.ownerDocument.defaultView.removeEventListener("focus", this._boundWindowFocused, false);
67         delete this._boundWindowFocused;
68         this._uiSourceCode.removeWorkingCopyGetter();
69     },
71     /**
72      * @override
73      * @return {boolean}
74      */
75     canEditSource: function()
76     {
77         var projectType = this._uiSourceCode.project().type();
78         if (projectType === WebInspector.projectTypes.Service || projectType === WebInspector.projectTypes.Debugger || projectType === WebInspector.projectTypes.Formatter)
79             return false;
80         if (projectType === WebInspector.projectTypes.Network && this._uiSourceCode.contentType() === WebInspector.resourceTypes.Document)
81             return false;
82         return true;
83     },
85     _windowFocused: function(event)
86     {
87         this._checkContentUpdated();
88     },
90     _checkContentUpdated: function()
91     {
92         if (!this.loaded || !this.isShowing())
93             return;
94         this._uiSourceCode.checkContentUpdated();
95     },
97     commitEditing: function()
98     {
99         if (!this._uiSourceCode.isDirty())
100             return;
102         this._muteSourceCodeEvents = true;
103         this._uiSourceCode.commitWorkingCopy();
104         delete this._muteSourceCodeEvents;
105     },
107     onTextChanged: function(oldRange, newRange)
108     {
109         WebInspector.SourceFrame.prototype.onTextChanged.call(this, oldRange, newRange);
110         if (this._isSettingContent)
111             return;
112         this._muteSourceCodeEvents = true;
113         if (this._textEditor.isClean())
114             this._uiSourceCode.resetWorkingCopy();
115         else
116             this._uiSourceCode.setWorkingCopyGetter(this._textEditor.text.bind(this._textEditor));
117         delete this._muteSourceCodeEvents;
118     },
120     /**
121      * @param {!WebInspector.Event} event
122      */
123     _onWorkingCopyChanged: function(event)
124     {
125         if (this._muteSourceCodeEvents)
126             return;
127         this._innerSetContent(this._uiSourceCode.workingCopy());
128         this.onUISourceCodeContentChanged();
129     },
131     /**
132      * @param {!WebInspector.Event} event
133      */
134     _onWorkingCopyCommitted: function(event)
135     {
136         if (!this._muteSourceCodeEvents) {
137             this._innerSetContent(this._uiSourceCode.workingCopy());
138             this.onUISourceCodeContentChanged();
139         }
140         this._textEditor.markClean();
141         this._updateStyle();
142     },
144     /**
145      * @param {!WebInspector.Event} event
146      */
147     _onSavedStateUpdated: function(event)
148     {
149         this._updateStyle();
150     },
152     _updateStyle: function()
153     {
154         this.element.classList.toggle("source-frame-unsaved-committed-changes", this._uiSourceCode.hasUnsavedCommittedChanges());
155     },
157     onUISourceCodeContentChanged: function()
158     {
159     },
161     /**
162      * @param {string} content
163      */
164     _innerSetContent: function(content)
165     {
166         this._isSettingContent = true;
167         this.setContent(content);
168         delete this._isSettingContent;
169     },
171     populateTextAreaContextMenu: function(contextMenu, lineNumber, columnNumber)
172     {
173         WebInspector.SourceFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber, columnNumber);
174         contextMenu.appendApplicableItems(this._uiSourceCode);
175         contextMenu.appendApplicableItems(new WebInspector.UILocation(this._uiSourceCode, lineNumber, columnNumber));
176         contextMenu.appendSeparator();
177     },
179     /**
180      * @param {!Array.<!WebInspector.UISourceCodeFrame.Infobar|undefined>} infobars
181      */
182     attachInfobars: function(infobars)
183     {
184         for (var i = infobars.length - 1; i >= 0; --i) {
185             var infobar = infobars[i];
186             if (!infobar)
187                 continue;
188             this.element.insertBefore(infobar.element, this.element.children[0]);
189             infobar._attached(this);
190         }
191         this.doResize();
192     },
194     dispose: function()
195     {
196         this._textEditor.dispose();
197         this.detach();
198     },
200     __proto__: WebInspector.SourceFrame.prototype
204  * @constructor
205  * @extends {WebInspector.Infobar}
206  * @param {!WebInspector.Infobar.Type} type
207  * @param {string} message
208  * @param {!WebInspector.Setting=} disableSetting
209  */
210 WebInspector.UISourceCodeFrame.Infobar = function(type, message, disableSetting)
212     WebInspector.Infobar.call(this, type, disableSetting);
213     this.setCloseCallback(this.dispose.bind(this));
214     this.element.classList.add("source-frame-infobar");
215     this._rows = this.element.createChild("div", "source-frame-infobar-rows");
217     this._mainRow = this._rows.createChild("div", "source-frame-infobar-main-row");
218     this._mainRow.createChild("span", "source-frame-infobar-row-message").textContent = message;
220     this._toggleElement = this._mainRow.createChild("div", "source-frame-infobar-toggle link");
221     this._toggleElement.addEventListener("click", this._onToggleDetails.bind(this), false);
222     this._detailsContainer = this._rows.createChild("div", "source-frame-infobar-details-container");
223     this._updateToggleElement();
226 WebInspector.UISourceCodeFrame.Infobar.prototype = {
227     _onResize: function()
228     {
229         if (this._uiSourceCodeFrame)
230             this._uiSourceCodeFrame.doResize();
231     },
233     _onToggleDetails: function()
234     {
235         this._toggled = !this._toggled;
236         this._updateToggleElement();
237         this._onResize();
238     },
240     _updateToggleElement: function()
241     {
242         this._toggleElement.textContent = this._toggled ? WebInspector.UIString("less") : WebInspector.UIString("more");
243         this._detailsContainer.classList.toggle("hidden", !this._toggled);
244     },
246     /**
247      * @param {!WebInspector.UISourceCodeFrame} uiSourceCodeFrame
248      */
249     _attached: function(uiSourceCodeFrame)
250     {
251         this._uiSourceCodeFrame = uiSourceCodeFrame;
252         this.setVisible(true);
253     },
255     /**
256      * @param {string=} message
257      * @return {!Element}
258      */
259     createDetailsRowMessage: function(message)
260     {
261         var infobarDetailsRow = this._detailsContainer.createChild("div", "source-frame-infobar-details-row");
262         var detailsRowMessage = infobarDetailsRow.createChild("span", "source-frame-infobar-row-message");
263         detailsRowMessage.textContent = message || "";
264         return detailsRowMessage;
265     },
267     dispose: function()
268     {
269         this.element.remove();
270         this._onResize();
271         delete this._uiSourceCodeFrame;
272     },
274     __proto__: WebInspector.Infobar.prototype