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);
46 WebInspector.UISourceCodeFrame.prototype = {
48 * @return {!WebInspector.UISourceCode}
50 uiSourceCode: function()
52 return this._uiSourceCode;
55 _enableAutocompletionIfNeeded: function()
57 this.textEditor.setCompletionDictionary(WebInspector.settings.textEditorAutocompletion.get() ? new WebInspector.SampleCompletionDictionary() : null);
62 WebInspector.SourceFrame.prototype.wasShown.call(this);
63 this._boundWindowFocused = this._windowFocused.bind(this);
64 window.addEventListener("focus", this._boundWindowFocused, false);
65 this._checkContentUpdated();
70 WebInspector.SourceFrame.prototype.willHide.call(this);
71 window.removeEventListener("focus", this._boundWindowFocused, false);
72 delete this._boundWindowFocused;
73 this._uiSourceCode.removeWorkingCopyGetter();
79 canEditSource: function()
81 var projectType = this._uiSourceCode.project().type();
82 if (projectType === WebInspector.projectTypes.Debugger || projectType === WebInspector.projectTypes.Formatter)
84 if (projectType === WebInspector.projectTypes.Network && this._uiSourceCode.contentType() === WebInspector.resourceTypes.Document)
89 _windowFocused: function(event)
91 this._checkContentUpdated();
94 _checkContentUpdated: function()
96 if (!this.loaded || !this.isShowing())
98 this._uiSourceCode.checkContentUpdated();
101 commitEditing: function()
103 if (!this._uiSourceCode.isDirty())
106 this._muteSourceCodeEvents = true;
107 this._uiSourceCode.commitWorkingCopy();
108 delete this._muteSourceCodeEvents;
111 onTextChanged: function(oldRange, newRange)
113 WebInspector.SourceFrame.prototype.onTextChanged.call(this, oldRange, newRange);
114 if (this._isSettingContent)
116 this._muteSourceCodeEvents = true;
117 if (this._textEditor.isClean())
118 this._uiSourceCode.resetWorkingCopy();
120 this._uiSourceCode.setWorkingCopyGetter(this._textEditor.text.bind(this._textEditor));
121 delete this._muteSourceCodeEvents;
125 * @param {!WebInspector.Event} event
127 _onWorkingCopyChanged: function(event)
129 if (this._muteSourceCodeEvents)
131 this._innerSetContent(this._uiSourceCode.workingCopy());
132 this.onUISourceCodeContentChanged();
136 * @param {!WebInspector.Event} event
138 _onWorkingCopyCommitted: function(event)
140 if (!this._muteSourceCodeEvents) {
141 this._innerSetContent(this._uiSourceCode.workingCopy());
142 this.onUISourceCodeContentChanged();
144 this._textEditor.markClean();
146 WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
147 action: WebInspector.UserMetrics.UserActionNames.FileSaved,
148 url: this._uiSourceCode.url
152 _updateStyle: function()
154 this.element.classList.toggle("source-frame-unsaved-committed-changes", this._uiSourceCode.hasUnsavedCommittedChanges());
157 onUISourceCodeContentChanged: function()
162 * @param {string} content
164 _innerSetContent: function(content)
166 this._isSettingContent = true;
167 this.setContent(content);
168 delete this._isSettingContent;
171 populateTextAreaContextMenu: function(contextMenu, lineNumber)
173 WebInspector.SourceFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber);
174 contextMenu.appendApplicableItems(this._uiSourceCode);
175 contextMenu.appendSeparator();
179 * @param {!Array.<!WebInspector.UISourceCodeFrame.Infobar|undefined>} infobars
181 attachInfobars: function(infobars)
183 for (var i = infobars.length - 1; i >= 0; --i) {
184 var infobar = infobars[i];
187 this.element.insertBefore(infobar.element, this.element.children[0]);
188 infobar._attached(this);
195 WebInspector.settings.textEditorAutocompletion.removeChangeListener(this._enableAutocompletionIfNeeded, this);
196 this._textEditor.dispose();
200 __proto__: WebInspector.SourceFrame.prototype
205 * @param {!WebInspector.UISourceCodeFrame.Infobar.Level} level
206 * @param {string} message
208 WebInspector.UISourceCodeFrame.Infobar = function(level, message)
210 this.element = document.createElementWithClass("div", "source-frame-infobar source-frame-infobar-" + level);
211 this._mainRow = this.element.createChild("div", "source-frame-infobar-main-row");
212 this._detailsContainer = this.element.createChild("span", "source-frame-infobar-details-container");
214 this._mainRow.createChild("span", "source-frame-infobar-icon");
215 this._mainRow.createChild("span", "source-frame-infobar-row-message").textContent = message;
217 this._toggleElement = this._mainRow.createChild("div", "source-frame-infobar-toggle source-frame-infobar-link");
218 this._toggleElement.addEventListener("click", this._onToggleDetails.bind(this), false);
220 this._closeElement = this._mainRow.createChild("div", "close-button");
221 this._closeElement.addEventListener("click", this._onClose.bind(this), false);
223 this._updateToggleElement();
229 WebInspector.UISourceCodeFrame.Infobar.Level = {
235 WebInspector.UISourceCodeFrame.Infobar.prototype = {
236 _onResize: function()
238 if (this._uiSourceCodeFrame)
239 this._uiSourceCodeFrame.doResize();
242 _onToggleDetails: function()
244 this._toggled = !this._toggled;
245 this._updateToggleElement();
254 _updateToggleElement: function()
256 this._toggleElement.textContent = this._toggled ? WebInspector.UIString("less") : WebInspector.UIString("more");
257 this._detailsContainer.classList.toggle("hidden", !this._toggled);
261 * @param {!WebInspector.UISourceCodeFrame} uiSourceCodeFrame
263 _attached: function(uiSourceCodeFrame)
265 this._uiSourceCodeFrame = uiSourceCodeFrame;
269 * @param {string=} message
272 createDetailsRowMessage: function(message)
274 var infobarDetailsRow = this._detailsContainer.createChild("div", "source-frame-infobar-details-row");
275 var detailsRowMessage = infobarDetailsRow.createChild("span", "source-frame-infobar-row-message");
276 detailsRowMessage.textContent = message || "";
277 return detailsRowMessage;
282 this.element.remove();
284 delete this._uiSourceCodeFrame;