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._updateStyle(); 44 } 45 46 WebInspector.UISourceCodeFrame.prototype = { 47 /** 48 * @return {!WebInspector.UISourceCode} 49 */ 50 uiSourceCode: function() 51 { 52 return this._uiSourceCode; 53 }, 54 55 _enableAutocompletionIfNeeded: function() 56 { 57 this.textEditor.setCompletionDictionary(WebInspector.settings.textEditorAutocompletion.get() ? new WebInspector.SampleCompletionDictionary() : null); 58 }, 59 60 wasShown: function() 61 { 62 WebInspector.SourceFrame.prototype.wasShown.call(this); 63 this._boundWindowFocused = this._windowFocused.bind(this); 64 window.addEventListener("focus", this._boundWindowFocused, false); 65 this._checkContentUpdated(); 66 }, 67 68 willHide: function() 69 { 70 WebInspector.SourceFrame.prototype.willHide.call(this); 71 window.removeEventListener("focus", this._boundWindowFocused, false); 72 delete this._boundWindowFocused; 73 this._uiSourceCode.removeWorkingCopyGetter(); 74 }, 75 76 /** 77 * @return {boolean} 78 */ 79 canEditSource: function() 80 { 81 var projectType = this._uiSourceCode.project().type(); 82 if (projectType === WebInspector.projectTypes.Debugger || projectType === WebInspector.projectTypes.Formatter) 83 return false; 84 if (projectType === WebInspector.projectTypes.Network && this._uiSourceCode.contentType() === WebInspector.resourceTypes.Document) 85 return false; 86 return true; 87 }, 88 89 _windowFocused: function(event) 90 { 91 this._checkContentUpdated(); 92 }, 93 94 _checkContentUpdated: function() 95 { 96 if (!this.loaded || !this.isShowing()) 97 return; 98 this._uiSourceCode.checkContentUpdated(); 99 }, 100 101 commitEditing: function() 102 { 103 if (!this._uiSourceCode.isDirty()) 104 return; 105 106 this._muteSourceCodeEvents = true; 107 this._uiSourceCode.commitWorkingCopy(this._didEditContent.bind(this)); 108 delete this._muteSourceCodeEvents; 109 }, 110 111 onTextChanged: function(oldRange, newRange) 112 { 113 WebInspector.SourceFrame.prototype.onTextChanged.call(this, oldRange, newRange); 114 if (this._isSettingContent) 115 return; 116 this._muteSourceCodeEvents = true; 117 if (this._textEditor.isClean()) 118 this._uiSourceCode.resetWorkingCopy(); 119 else 120 this._uiSourceCode.setWorkingCopyGetter(this._textEditor.text.bind(this._textEditor)); 121 delete this._muteSourceCodeEvents; 122 }, 123 124 _didEditContent: function(error) 125 { 126 if (error) { 127 WebInspector.messageSink.addErrorMessage(error, true); 128 return; 129 } 130 }, 131 132 /** 133 * @param {!WebInspector.Event} event 134 */ 135 _onWorkingCopyChanged: function(event) 136 { 137 if (this._muteSourceCodeEvents) 138 return; 139 this._innerSetContent(this._uiSourceCode.workingCopy()); 140 this.onUISourceCodeContentChanged(); 141 }, 142 143 /** 144 * @param {!WebInspector.Event} event 145 */ 146 _onWorkingCopyCommitted: function(event) 147 { 148 if (!this._muteSourceCodeEvents) { 149 this._innerSetContent(this._uiSourceCode.workingCopy()); 150 this.onUISourceCodeContentChanged(); 151 } 152 this._textEditor.markClean(); 153 this._updateStyle(); 154 }, 155 156 _updateStyle: function() 157 { 158 this.element.classList.toggle("source-frame-unsaved-committed-changes", this._uiSourceCode.hasUnsavedCommittedChanges()); 159 }, 160 161 onUISourceCodeContentChanged: function() 162 { 163 }, 164 165 /** 166 * @param {string} content 167 */ 168 _innerSetContent: function(content) 169 { 170 this._isSettingContent = true; 171 this.setContent(content); 172 delete this._isSettingContent; 173 }, 174 175 populateTextAreaContextMenu: function(contextMenu, lineNumber) 176 { 177 WebInspector.SourceFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber); 178 contextMenu.appendApplicableItems(this._uiSourceCode); 179 contextMenu.appendSeparator(); 180 }, 181 182 dispose: function() 183 { 184 WebInspector.settings.textEditorAutocompletion.removeChangeListener(this._enableAutocompletionIfNeeded, this); 185 this._textEditor.dispose(); 186 this.detach(); 187 }, 188 189 __proto__: WebInspector.SourceFrame.prototype 190 } 191