2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
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
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.
31 * @extends {WebInspector.SourceFrame}
32 * @param {!WebInspector.UISourceCode} uiSourceCode
34 WebInspector.UISourceCodeFrame = function(uiSourceCode)
36 this._uiSourceCode = uiSourceCode;
37 WebInspector.SourceFrame.call(this, this._uiSourceCode);
38 WebInspector.settings.textEditorAutocompletion.addChangeListener(this._enableAutocompletionIfNeeded, this);
39 this._enableAutocompletionIfNeeded();
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);
47 WebInspector.UISourceCodeFrame.prototype = {
49 * @return {!WebInspector.UISourceCode}
51 uiSourceCode: function()
53 return this._uiSourceCode;
56 _enableAutocompletionIfNeeded: function()
58 this.textEditor.setCompletionDictionary(WebInspector.settings.textEditorAutocompletion.get() ? new WebInspector.SampleCompletionDictionary() : null);
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();
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();
80 canEditSource: function()
82 var projectType = this._uiSourceCode.project().type();
83 if (projectType === WebInspector.projectTypes.Service || projectType === WebInspector.projectTypes.Debugger || projectType === WebInspector.projectTypes.Formatter)
85 if (projectType === WebInspector.projectTypes.Network && this._uiSourceCode.contentType() === WebInspector.resourceTypes.Document)
90 _windowFocused: function(event)
92 this._checkContentUpdated();
95 _checkContentUpdated: function()
97 if (!this.loaded || !this.isShowing())
99 this._uiSourceCode.checkContentUpdated();
102 commitEditing: function()
104 if (!this._uiSourceCode.isDirty())
107 this._muteSourceCodeEvents = true;
108 this._uiSourceCode.commitWorkingCopy();
109 delete this._muteSourceCodeEvents;
112 onTextChanged: function(oldRange, newRange)
114 WebInspector.SourceFrame.prototype.onTextChanged.call(this, oldRange, newRange);
115 if (this._isSettingContent)
117 this._muteSourceCodeEvents = true;
118 if (this._textEditor.isClean())
119 this._uiSourceCode.resetWorkingCopy();
121 this._uiSourceCode.setWorkingCopyGetter(this._textEditor.text.bind(this._textEditor));
122 delete this._muteSourceCodeEvents;
126 * @param {!WebInspector.Event} event
128 _onWorkingCopyChanged: function(event)
130 if (this._muteSourceCodeEvents)
132 this._innerSetContent(this._uiSourceCode.workingCopy());
133 this.onUISourceCodeContentChanged();
137 * @param {!WebInspector.Event} event
139 _onWorkingCopyCommitted: function(event)
141 if (!this._muteSourceCodeEvents) {
142 this._innerSetContent(this._uiSourceCode.workingCopy());
143 this.onUISourceCodeContentChanged();
145 this._textEditor.markClean();
147 WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
148 action: WebInspector.UserMetrics.UserActionNames.FileSaved,
149 url: this._uiSourceCode.url
154 * @param {!WebInspector.Event} event
156 _onSavedStateUpdated: function(event)
161 _updateStyle: function()
163 this.element.classList.toggle("source-frame-unsaved-committed-changes", this._uiSourceCode.hasUnsavedCommittedChanges());
166 onUISourceCodeContentChanged: function()
171 * @param {string} content
173 _innerSetContent: function(content)
175 this._isSettingContent = true;
176 this.setContent(content);
177 delete this._isSettingContent;
180 populateTextAreaContextMenu: function(contextMenu, lineNumber)
182 WebInspector.SourceFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber);
183 contextMenu.appendApplicableItems(this._uiSourceCode);
184 contextMenu.appendSeparator();
188 * @param {!Array.<!WebInspector.UISourceCodeFrame.Infobar|undefined>} infobars
190 attachInfobars: function(infobars)
192 for (var i = infobars.length - 1; i >= 0; --i) {
193 var infobar = infobars[i];
196 this.element.insertBefore(infobar.element, this.element.children[0]);
197 infobar._attached(this);
204 WebInspector.settings.textEditorAutocompletion.removeChangeListener(this._enableAutocompletionIfNeeded, this);
205 this._textEditor.dispose();
209 __proto__: WebInspector.SourceFrame.prototype
214 * @param {!WebInspector.UISourceCodeFrame.Infobar.Level} level
215 * @param {string} message
216 * @param {function()=} onDispose
218 WebInspector.UISourceCodeFrame.Infobar = function(level, message, onDispose)
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");
224 this._mainRow.createChild("span", "source-frame-infobar-icon");
225 this._mainRow.createChild("span", "source-frame-infobar-row-message").textContent = message;
227 this._toggleElement = this._mainRow.createChild("div", "source-frame-infobar-toggle link");
228 this._toggleElement.addEventListener("click", this._onToggleDetails.bind(this), false);
230 this._closeElement = this._mainRow.createChild("div", "close-button");
231 this._closeElement.addEventListener("click", this._onClose.bind(this), false);
232 this._onDispose = onDispose;
234 this._updateToggleElement();
240 WebInspector.UISourceCodeFrame.Infobar.Level = {
246 WebInspector.UISourceCodeFrame.Infobar.prototype = {
247 _onResize: function()
249 if (this._uiSourceCodeFrame)
250 this._uiSourceCodeFrame.doResize();
253 _onToggleDetails: function()
255 this._toggled = !this._toggled;
256 this._updateToggleElement();
265 _updateToggleElement: function()
267 this._toggleElement.textContent = this._toggled ? WebInspector.UIString("less") : WebInspector.UIString("more");
268 this._detailsContainer.classList.toggle("hidden", !this._toggled);
272 * @param {!WebInspector.UISourceCodeFrame} uiSourceCodeFrame
274 _attached: function(uiSourceCodeFrame)
276 this._uiSourceCodeFrame = uiSourceCodeFrame;
280 * @param {string=} message
283 createDetailsRowMessage: function(message)
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;
293 this.element.remove();
295 delete this._uiSourceCodeFrame;