| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) IBM Corp. 2009 All rights reserved. | 2 * Copyright (C) IBM Corp. 2009 All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
| 13 * distribution. | 13 * distribution. |
| 14 * * Neither the name of IBM Corp. nor the names of its | 14 * * Neither the name of IBM Corp. nor the names of its |
| 15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
| 16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
| 17 * | 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | |
| 31 /** | 30 /** |
| 32 * @constructor | |
| 33 * @extends {WebInspector.ThrottledWidget} | |
| 34 * @implements {WebInspector.ActionDelegate} | 31 * @implements {WebInspector.ActionDelegate} |
| 35 * @implements {WebInspector.ToolbarItem.ItemsProvider} | 32 * @implements {WebInspector.ToolbarItem.ItemsProvider} |
| 36 * @implements {WebInspector.ContextMenu.Provider} | 33 * @implements {WebInspector.ContextMenu.Provider} |
| 34 * @unrestricted |
| 37 */ | 35 */ |
| 38 WebInspector.WatchExpressionsSidebarPane = function() | 36 WebInspector.WatchExpressionsSidebarPane = class extends WebInspector.ThrottledW
idget { |
| 39 { | 37 constructor() { |
| 40 WebInspector.ThrottledWidget.call(this); | 38 super(); |
| 41 this.registerRequiredCSS("components/objectValue.css"); | 39 this.registerRequiredCSS('components/objectValue.css'); |
| 42 | 40 |
| 43 /** @type {!Array.<!WebInspector.WatchExpression>} */ | 41 /** @type {!Array.<!WebInspector.WatchExpression>} */ |
| 44 this._watchExpressions = []; | 42 this._watchExpressions = []; |
| 45 this._watchExpressionsSetting = WebInspector.settings.createLocalSetting("wa
tchExpressions", []); | 43 this._watchExpressionsSetting = WebInspector.settings.createLocalSetting('wa
tchExpressions', []); |
| 46 | 44 |
| 47 this._addButton = new WebInspector.ToolbarButton(WebInspector.UIString("Add
expression"), "add-toolbar-item"); | 45 this._addButton = new WebInspector.ToolbarButton(WebInspector.UIString('Add
expression'), 'add-toolbar-item'); |
| 48 this._addButton.addEventListener("click", this._addButtonClicked.bind(this))
; | 46 this._addButton.addEventListener('click', this._addButtonClicked.bind(this))
; |
| 49 this._refreshButton = new WebInspector.ToolbarButton(WebInspector.UIString("
Refresh"), "refresh-toolbar-item"); | 47 this._refreshButton = new WebInspector.ToolbarButton(WebInspector.UIString('
Refresh'), 'refresh-toolbar-item'); |
| 50 this._refreshButton.addEventListener("click", this._refreshButtonClicked.bin
d(this)); | 48 this._refreshButton.addEventListener('click', this._refreshButtonClicked.bin
d(this)); |
| 51 | 49 |
| 52 this._bodyElement = this.element.createChild("div", "vbox watch-expressions"
); | 50 this._bodyElement = this.element.createChild('div', 'vbox watch-expressions'
); |
| 53 this._bodyElement.addEventListener("contextmenu", this._contextMenu.bind(thi
s), false); | 51 this._bodyElement.addEventListener('contextmenu', this._contextMenu.bind(thi
s), false); |
| 54 this._expandController = new WebInspector.ObjectPropertiesSectionExpandContr
oller(); | 52 this._expandController = new WebInspector.ObjectPropertiesSectionExpandContr
oller(); |
| 55 | 53 |
| 56 WebInspector.context.addFlavorChangeListener(WebInspector.ExecutionContext,
this.update, this); | 54 WebInspector.context.addFlavorChangeListener(WebInspector.ExecutionContext,
this.update, this); |
| 57 WebInspector.context.addFlavorChangeListener(WebInspector.DebuggerModel.Call
Frame, this.update, this); | 55 WebInspector.context.addFlavorChangeListener(WebInspector.DebuggerModel.Call
Frame, this.update, this); |
| 58 this._linkifier = new WebInspector.Linkifier(); | 56 this._linkifier = new WebInspector.Linkifier(); |
| 59 this.update(); | 57 this.update(); |
| 58 } |
| 59 |
| 60 /** |
| 61 * @override |
| 62 * @return {!Array<!WebInspector.ToolbarItem>} |
| 63 */ |
| 64 toolbarItems() { |
| 65 return [this._addButton, this._refreshButton]; |
| 66 } |
| 67 |
| 68 /** |
| 69 * @return {boolean} |
| 70 */ |
| 71 hasExpressions() { |
| 72 return !!this._watchExpressionsSetting.get().length; |
| 73 } |
| 74 |
| 75 _saveExpressions() { |
| 76 var toSave = []; |
| 77 for (var i = 0; i < this._watchExpressions.length; i++) |
| 78 if (this._watchExpressions[i].expression()) |
| 79 toSave.push(this._watchExpressions[i].expression()); |
| 80 |
| 81 this._watchExpressionsSetting.set(toSave); |
| 82 } |
| 83 |
| 84 /** |
| 85 * @param {!WebInspector.Event=} event |
| 86 */ |
| 87 _addButtonClicked(event) { |
| 88 if (event) |
| 89 event.consume(true); |
| 90 WebInspector.viewManager.showView('sources.watch'); |
| 91 this._createWatchExpression(null).startEditing(); |
| 92 } |
| 93 |
| 94 /** |
| 95 * @param {!WebInspector.Event} event |
| 96 */ |
| 97 _refreshButtonClicked(event) { |
| 98 event.consume(); |
| 99 this.update(); |
| 100 } |
| 101 |
| 102 /** |
| 103 * @override |
| 104 * @return {!Promise.<?>} |
| 105 */ |
| 106 doUpdate() { |
| 107 this._linkifier.reset(); |
| 108 this._bodyElement.removeChildren(); |
| 109 this._watchExpressions = []; |
| 110 this._emptyElement = this._bodyElement.createChild('div', 'gray-info-message
'); |
| 111 this._emptyElement.textContent = WebInspector.UIString('No Watch Expressions
'); |
| 112 var watchExpressionStrings = this._watchExpressionsSetting.get(); |
| 113 for (var i = 0; i < watchExpressionStrings.length; ++i) { |
| 114 var expression = watchExpressionStrings[i]; |
| 115 if (!expression) |
| 116 continue; |
| 117 |
| 118 this._createWatchExpression(expression); |
| 119 } |
| 120 return Promise.resolve(); |
| 121 } |
| 122 |
| 123 /** |
| 124 * @param {?string} expression |
| 125 * @return {!WebInspector.WatchExpression} |
| 126 */ |
| 127 _createWatchExpression(expression) { |
| 128 this._emptyElement.classList.add('hidden'); |
| 129 var watchExpression = new WebInspector.WatchExpression(expression, this._exp
andController, this._linkifier); |
| 130 watchExpression.addEventListener( |
| 131 WebInspector.WatchExpression.Events.ExpressionUpdated, this._watchExpres
sionUpdated.bind(this)); |
| 132 this._bodyElement.appendChild(watchExpression.element()); |
| 133 this._watchExpressions.push(watchExpression); |
| 134 return watchExpression; |
| 135 } |
| 136 |
| 137 /** |
| 138 * @param {!WebInspector.Event} event |
| 139 */ |
| 140 _watchExpressionUpdated(event) { |
| 141 var watchExpression = /** @type {!WebInspector.WatchExpression} */ (event.ta
rget); |
| 142 if (!watchExpression.expression()) { |
| 143 this._watchExpressions.remove(watchExpression); |
| 144 this._bodyElement.removeChild(watchExpression.element()); |
| 145 this._emptyElement.classList.toggle('hidden', !!this._watchExpressions.len
gth); |
| 146 } |
| 147 |
| 148 this._saveExpressions(); |
| 149 } |
| 150 |
| 151 /** |
| 152 * @param {!Event} event |
| 153 */ |
| 154 _contextMenu(event) { |
| 155 var contextMenu = new WebInspector.ContextMenu(event); |
| 156 this._populateContextMenu(contextMenu, event); |
| 157 contextMenu.show(); |
| 158 } |
| 159 |
| 160 /** |
| 161 * @param {!WebInspector.ContextMenu} contextMenu |
| 162 * @param {!Event} event |
| 163 */ |
| 164 _populateContextMenu(contextMenu, event) { |
| 165 var isEditing = false; |
| 166 for (var watchExpression of this._watchExpressions) |
| 167 isEditing |= watchExpression.isEditing(); |
| 168 |
| 169 if (!isEditing) |
| 170 contextMenu.appendItem( |
| 171 WebInspector.UIString.capitalize('Add ^watch ^expression'), this._addB
uttonClicked.bind(this)); |
| 172 |
| 173 if (this._watchExpressions.length > 1) |
| 174 contextMenu.appendItem( |
| 175 WebInspector.UIString.capitalize('Delete ^all ^watch ^expressions'), t
his._deleteAllButtonClicked.bind(this)); |
| 176 |
| 177 var target = event.deepElementFromPoint(); |
| 178 if (!target) |
| 179 return; |
| 180 for (var watchExpression of this._watchExpressions) |
| 181 if (watchExpression.element().isSelfOrAncestor(target)) |
| 182 watchExpression._populateContextMenu(contextMenu, event); |
| 183 } |
| 184 |
| 185 _deleteAllButtonClicked() { |
| 186 this._watchExpressions = []; |
| 187 this._saveExpressions(); |
| 188 this.update(); |
| 189 } |
| 190 |
| 191 /** |
| 192 * @override |
| 193 * @param {!WebInspector.Context} context |
| 194 * @param {string} actionId |
| 195 * @return {boolean} |
| 196 */ |
| 197 handleAction(context, actionId) { |
| 198 var frame = WebInspector.context.flavor(WebInspector.UISourceCodeFrame); |
| 199 if (!frame) |
| 200 return false; |
| 201 var text = frame.textEditor.text(frame.textEditor.selection()); |
| 202 WebInspector.viewManager.showView('sources.watch'); |
| 203 this.doUpdate(); |
| 204 this._createWatchExpression(text); |
| 205 this._saveExpressions(); |
| 206 return true; |
| 207 } |
| 208 |
| 209 /** |
| 210 * @override |
| 211 * @param {!Event} event |
| 212 * @param {!WebInspector.ContextMenu} contextMenu |
| 213 * @param {!Object} target |
| 214 */ |
| 215 appendApplicableItems(event, contextMenu, target) { |
| 216 contextMenu.appendAction('sources.add-to-watch'); |
| 217 } |
| 60 }; | 218 }; |
| 61 | 219 |
| 62 WebInspector.WatchExpressionsSidebarPane.prototype = { | |
| 63 /** | |
| 64 * @override | |
| 65 * @return {!Array<!WebInspector.ToolbarItem>} | |
| 66 */ | |
| 67 toolbarItems: function() | |
| 68 { | |
| 69 return [this._addButton, this._refreshButton]; | |
| 70 }, | |
| 71 | |
| 72 /** | |
| 73 * @return {boolean} | |
| 74 */ | |
| 75 hasExpressions: function() | |
| 76 { | |
| 77 return !!this._watchExpressionsSetting.get().length; | |
| 78 }, | |
| 79 | |
| 80 _saveExpressions: function() | |
| 81 { | |
| 82 var toSave = []; | |
| 83 for (var i = 0; i < this._watchExpressions.length; i++) | |
| 84 if (this._watchExpressions[i].expression()) | |
| 85 toSave.push(this._watchExpressions[i].expression()); | |
| 86 | |
| 87 this._watchExpressionsSetting.set(toSave); | |
| 88 }, | |
| 89 | |
| 90 /** | |
| 91 * @param {!WebInspector.Event=} event | |
| 92 */ | |
| 93 _addButtonClicked: function(event) | |
| 94 { | |
| 95 if (event) | |
| 96 event.consume(true); | |
| 97 WebInspector.viewManager.showView("sources.watch"); | |
| 98 this._createWatchExpression(null).startEditing(); | |
| 99 }, | |
| 100 | |
| 101 /** | |
| 102 * @param {!WebInspector.Event} event | |
| 103 */ | |
| 104 _refreshButtonClicked: function(event) | |
| 105 { | |
| 106 event.consume(); | |
| 107 this.update(); | |
| 108 }, | |
| 109 | |
| 110 /** | |
| 111 * @override | |
| 112 * @return {!Promise.<?>} | |
| 113 */ | |
| 114 doUpdate: function() | |
| 115 { | |
| 116 this._linkifier.reset(); | |
| 117 this._bodyElement.removeChildren(); | |
| 118 this._watchExpressions = []; | |
| 119 this._emptyElement = this._bodyElement.createChild("div", "gray-info-mes
sage"); | |
| 120 this._emptyElement.textContent = WebInspector.UIString("No Watch Express
ions"); | |
| 121 var watchExpressionStrings = this._watchExpressionsSetting.get(); | |
| 122 for (var i = 0; i < watchExpressionStrings.length; ++i) { | |
| 123 var expression = watchExpressionStrings[i]; | |
| 124 if (!expression) | |
| 125 continue; | |
| 126 | |
| 127 this._createWatchExpression(expression); | |
| 128 } | |
| 129 return Promise.resolve(); | |
| 130 }, | |
| 131 | |
| 132 /** | |
| 133 * @param {?string} expression | |
| 134 * @return {!WebInspector.WatchExpression} | |
| 135 */ | |
| 136 _createWatchExpression: function(expression) | |
| 137 { | |
| 138 this._emptyElement.classList.add("hidden"); | |
| 139 var watchExpression = new WebInspector.WatchExpression(expression, this.
_expandController, this._linkifier); | |
| 140 watchExpression.addEventListener(WebInspector.WatchExpression.Events.Exp
ressionUpdated, this._watchExpressionUpdated.bind(this)); | |
| 141 this._bodyElement.appendChild(watchExpression.element()); | |
| 142 this._watchExpressions.push(watchExpression); | |
| 143 return watchExpression; | |
| 144 }, | |
| 145 | |
| 146 /** | |
| 147 * @param {!WebInspector.Event} event | |
| 148 */ | |
| 149 _watchExpressionUpdated: function(event) | |
| 150 { | |
| 151 var watchExpression = /** @type {!WebInspector.WatchExpression} */ (even
t.target); | |
| 152 if (!watchExpression.expression()) { | |
| 153 this._watchExpressions.remove(watchExpression); | |
| 154 this._bodyElement.removeChild(watchExpression.element()); | |
| 155 this._emptyElement.classList.toggle("hidden", !!this._watchExpressio
ns.length); | |
| 156 } | |
| 157 | |
| 158 this._saveExpressions(); | |
| 159 }, | |
| 160 | |
| 161 /** | |
| 162 * @param {!Event} event | |
| 163 */ | |
| 164 _contextMenu: function(event) | |
| 165 { | |
| 166 var contextMenu = new WebInspector.ContextMenu(event); | |
| 167 this._populateContextMenu(contextMenu, event); | |
| 168 contextMenu.show(); | |
| 169 }, | |
| 170 | |
| 171 /** | |
| 172 * @param {!WebInspector.ContextMenu} contextMenu | |
| 173 * @param {!Event} event | |
| 174 */ | |
| 175 _populateContextMenu: function(contextMenu, event) | |
| 176 { | |
| 177 var isEditing = false; | |
| 178 for (var watchExpression of this._watchExpressions) | |
| 179 isEditing |= watchExpression.isEditing(); | |
| 180 | |
| 181 if (!isEditing) | |
| 182 contextMenu.appendItem(WebInspector.UIString.capitalize("Add ^watch
^expression"), this._addButtonClicked.bind(this)); | |
| 183 | |
| 184 if (this._watchExpressions.length > 1) | |
| 185 contextMenu.appendItem(WebInspector.UIString.capitalize("Delete ^all
^watch ^expressions"), this._deleteAllButtonClicked.bind(this)); | |
| 186 | |
| 187 var target = event.deepElementFromPoint(); | |
| 188 if (!target) | |
| 189 return; | |
| 190 for (var watchExpression of this._watchExpressions) | |
| 191 if (watchExpression.element().isSelfOrAncestor(target)) | |
| 192 watchExpression._populateContextMenu(contextMenu, event); | |
| 193 }, | |
| 194 | |
| 195 _deleteAllButtonClicked: function() | |
| 196 { | |
| 197 this._watchExpressions = []; | |
| 198 this._saveExpressions(); | |
| 199 this.update(); | |
| 200 }, | |
| 201 | |
| 202 /** | |
| 203 * @override | |
| 204 * @param {!WebInspector.Context} context | |
| 205 * @param {string} actionId | |
| 206 * @return {boolean} | |
| 207 */ | |
| 208 handleAction: function(context, actionId) | |
| 209 { | |
| 210 var frame = WebInspector.context.flavor(WebInspector.UISourceCodeFrame); | |
| 211 if (!frame) | |
| 212 return false; | |
| 213 var text = frame.textEditor.text(frame.textEditor.selection()); | |
| 214 WebInspector.viewManager.showView("sources.watch"); | |
| 215 this.doUpdate(); | |
| 216 this._createWatchExpression(text); | |
| 217 this._saveExpressions(); | |
| 218 return true; | |
| 219 }, | |
| 220 | |
| 221 /** | |
| 222 * @override | |
| 223 * @param {!Event} event | |
| 224 * @param {!WebInspector.ContextMenu} contextMenu | |
| 225 * @param {!Object} target | |
| 226 */ | |
| 227 appendApplicableItems: function(event, contextMenu, target) | |
| 228 { | |
| 229 contextMenu.appendAction("sources.add-to-watch"); | |
| 230 }, | |
| 231 | |
| 232 __proto__: WebInspector.ThrottledWidget.prototype | |
| 233 }; | |
| 234 | |
| 235 /** | 220 /** |
| 236 * @constructor | 221 * @unrestricted |
| 237 * @extends {WebInspector.Object} | |
| 238 * @param {?string} expression | |
| 239 * @param {!WebInspector.ObjectPropertiesSectionExpandController} expandControll
er | |
| 240 * @param {!WebInspector.Linkifier} linkifier | |
| 241 */ | 222 */ |
| 242 WebInspector.WatchExpression = function(expression, expandController, linkifier) | 223 WebInspector.WatchExpression = class extends WebInspector.Object { |
| 243 { | 224 /** |
| 225 * @param {?string} expression |
| 226 * @param {!WebInspector.ObjectPropertiesSectionExpandController} expandContro
ller |
| 227 * @param {!WebInspector.Linkifier} linkifier |
| 228 */ |
| 229 constructor(expression, expandController, linkifier) { |
| 230 super(); |
| 244 this._expression = expression; | 231 this._expression = expression; |
| 245 this._expandController = expandController; | 232 this._expandController = expandController; |
| 246 this._element = createElementWithClass("div", "watch-expression monospace"); | 233 this._element = createElementWithClass('div', 'watch-expression monospace'); |
| 247 this._editing = false; | 234 this._editing = false; |
| 248 this._linkifier = linkifier; | 235 this._linkifier = linkifier; |
| 249 | 236 |
| 250 this._createWatchExpression(null); | 237 this._createWatchExpression(null); |
| 251 this.update(); | 238 this.update(); |
| 239 } |
| 240 |
| 241 /** |
| 242 * @return {!Element} |
| 243 */ |
| 244 element() { |
| 245 return this._element; |
| 246 } |
| 247 |
| 248 /** |
| 249 * @return {?string} |
| 250 */ |
| 251 expression() { |
| 252 return this._expression; |
| 253 } |
| 254 |
| 255 update() { |
| 256 var currentExecutionContext = WebInspector.context.flavor(WebInspector.Execu
tionContext); |
| 257 if (currentExecutionContext && this._expression) |
| 258 currentExecutionContext.evaluate( |
| 259 this._expression, WebInspector.WatchExpression._watchObjectGroupId, fa
lse, true, false, false, false, |
| 260 this._createWatchExpression.bind(this)); |
| 261 } |
| 262 |
| 263 startEditing() { |
| 264 this._editing = true; |
| 265 this._element.removeChild(this._objectPresentationElement); |
| 266 var newDiv = this._element.createChild('div'); |
| 267 newDiv.textContent = this._nameElement.textContent; |
| 268 this._textPrompt = new WebInspector.ObjectPropertyPrompt(); |
| 269 this._textPrompt.renderAsBlock(); |
| 270 var proxyElement = this._textPrompt.attachAndStartEditing(newDiv, this._fini
shEditing.bind(this)); |
| 271 proxyElement.classList.add('watch-expression-text-prompt-proxy'); |
| 272 proxyElement.addEventListener('keydown', this._promptKeyDown.bind(this), fal
se); |
| 273 this._element.getComponentSelection().setBaseAndExtent(newDiv, 0, newDiv, 1)
; |
| 274 } |
| 275 |
| 276 /** |
| 277 * @return {boolean} |
| 278 */ |
| 279 isEditing() { |
| 280 return !!this._editing; |
| 281 } |
| 282 |
| 283 /** |
| 284 * @param {!Event} event |
| 285 * @param {boolean=} canceled |
| 286 */ |
| 287 _finishEditing(event, canceled) { |
| 288 if (event) |
| 289 event.consume(true); |
| 290 |
| 291 this._editing = false; |
| 292 this._textPrompt.detach(); |
| 293 var newExpression = canceled ? this._expression : this._textPrompt.text(); |
| 294 delete this._textPrompt; |
| 295 this._element.removeChildren(); |
| 296 this._element.appendChild(this._objectPresentationElement); |
| 297 this._updateExpression(newExpression); |
| 298 } |
| 299 |
| 300 /** |
| 301 * @param {!Event} event |
| 302 */ |
| 303 _dblClickOnWatchExpression(event) { |
| 304 event.consume(); |
| 305 if (!this.isEditing()) |
| 306 this.startEditing(); |
| 307 } |
| 308 |
| 309 /** |
| 310 * @param {?string} newExpression |
| 311 */ |
| 312 _updateExpression(newExpression) { |
| 313 if (this._expression) |
| 314 this._expandController.stopWatchSectionsWithId(this._expression); |
| 315 this._expression = newExpression; |
| 316 this.update(); |
| 317 this.dispatchEventToListeners(WebInspector.WatchExpression.Events.Expression
Updated); |
| 318 } |
| 319 |
| 320 /** |
| 321 * @param {!Event} event |
| 322 */ |
| 323 _deleteWatchExpression(event) { |
| 324 event.consume(true); |
| 325 this._updateExpression(null); |
| 326 } |
| 327 |
| 328 /** |
| 329 * @param {?WebInspector.RemoteObject} result |
| 330 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails |
| 331 */ |
| 332 _createWatchExpression(result, exceptionDetails) { |
| 333 this._result = result; |
| 334 |
| 335 var headerElement = createElementWithClass('div', 'watch-expression-header')
; |
| 336 var deleteButton = headerElement.createChild('button', 'watch-expression-del
ete-button'); |
| 337 deleteButton.title = WebInspector.UIString('Delete watch expression'); |
| 338 deleteButton.addEventListener('click', this._deleteWatchExpression.bind(this
), false); |
| 339 |
| 340 var titleElement = headerElement.createChild('div', 'watch-expression-title'
); |
| 341 this._nameElement = WebInspector.ObjectPropertiesSection.createNameElement(t
his._expression); |
| 342 if (!!exceptionDetails || !result) { |
| 343 this._valueElement = createElementWithClass('span', 'watch-expression-erro
r value'); |
| 344 titleElement.classList.add('dimmed'); |
| 345 this._valueElement.textContent = WebInspector.UIString('<not available>'); |
| 346 } else { |
| 347 this._valueElement = WebInspector.ObjectPropertiesSection.createValueEleme
ntWithCustomSupport( |
| 348 result, !!exceptionDetails, titleElement, this._linkifier); |
| 349 } |
| 350 var separatorElement = createElementWithClass('span', 'watch-expressions-sep
arator'); |
| 351 separatorElement.textContent = ': '; |
| 352 titleElement.appendChildren(this._nameElement, separatorElement, this._value
Element); |
| 353 |
| 354 this._element.removeChildren(); |
| 355 this._objectPropertiesSection = null; |
| 356 if (!exceptionDetails && result && result.hasChildren && !result.customPrevi
ew()) { |
| 357 headerElement.classList.add('watch-expression-object-header'); |
| 358 this._objectPropertiesSection = new WebInspector.ObjectPropertiesSection(r
esult, headerElement, this._linkifier); |
| 359 this._objectPresentationElement = this._objectPropertiesSection.element; |
| 360 this._expandController.watchSection(/** @type {string} */ (this._expressio
n), this._objectPropertiesSection); |
| 361 var objectTreeElement = this._objectPropertiesSection.objectTreeElement(); |
| 362 objectTreeElement.toggleOnClick = false; |
| 363 objectTreeElement.listItemElement.addEventListener('click', this._onSectio
nClick.bind(this), false); |
| 364 objectTreeElement.listItemElement.addEventListener('dblclick', this._dblCl
ickOnWatchExpression.bind(this)); |
| 365 } else { |
| 366 this._objectPresentationElement = headerElement; |
| 367 this._objectPresentationElement.addEventListener('dblclick', this._dblClic
kOnWatchExpression.bind(this)); |
| 368 } |
| 369 |
| 370 this._element.appendChild(this._objectPresentationElement); |
| 371 } |
| 372 |
| 373 /** |
| 374 * @param {!Event} event |
| 375 */ |
| 376 _onSectionClick(event) { |
| 377 event.consume(true); |
| 378 if (event.detail === 1) { |
| 379 this._preventClickTimeout = setTimeout(handleClick.bind(this), 333); |
| 380 } else { |
| 381 clearTimeout(this._preventClickTimeout); |
| 382 delete this._preventClickTimeout; |
| 383 } |
| 384 |
| 385 /** |
| 386 * @this {WebInspector.WatchExpression} |
| 387 */ |
| 388 function handleClick() { |
| 389 if (!this._objectPropertiesSection) |
| 390 return; |
| 391 |
| 392 var objectTreeElement = this._objectPropertiesSection.objectTreeElement(); |
| 393 if (objectTreeElement.expanded) |
| 394 objectTreeElement.collapse(); |
| 395 else |
| 396 objectTreeElement.expand(); |
| 397 } |
| 398 } |
| 399 |
| 400 /** |
| 401 * @param {!Event} event |
| 402 */ |
| 403 _promptKeyDown(event) { |
| 404 if (isEnterKey(event) || isEscKey(event)) |
| 405 this._finishEditing(event, isEscKey(event)); |
| 406 } |
| 407 |
| 408 /** |
| 409 * @param {!WebInspector.ContextMenu} contextMenu |
| 410 * @param {!Event} event |
| 411 */ |
| 412 _populateContextMenu(contextMenu, event) { |
| 413 if (!this.isEditing()) |
| 414 contextMenu.appendItem( |
| 415 WebInspector.UIString.capitalize('Delete ^watch ^expression'), this._u
pdateExpression.bind(this, null)); |
| 416 |
| 417 if (!this.isEditing() && this._result && (this._result.type === 'number' ||
this._result.type === 'string')) |
| 418 contextMenu.appendItem(WebInspector.UIString.capitalize('Copy ^value'), th
is._copyValueButtonClicked.bind(this)); |
| 419 |
| 420 var target = event.deepElementFromPoint(); |
| 421 if (target && this._valueElement.isSelfOrAncestor(target)) |
| 422 contextMenu.appendApplicableItems(this._result); |
| 423 } |
| 424 |
| 425 _copyValueButtonClicked() { |
| 426 InspectorFrontendHost.copyText(this._valueElement.textContent); |
| 427 } |
| 252 }; | 428 }; |
| 253 | 429 |
| 254 WebInspector.WatchExpression._watchObjectGroupId = "watch-group"; | 430 WebInspector.WatchExpression._watchObjectGroupId = 'watch-group'; |
| 255 | 431 |
| 256 /** @enum {symbol} */ | 432 /** @enum {symbol} */ |
| 257 WebInspector.WatchExpression.Events = { | 433 WebInspector.WatchExpression.Events = { |
| 258 ExpressionUpdated: Symbol("ExpressionUpdated") | 434 ExpressionUpdated: Symbol('ExpressionUpdated') |
| 259 }; | 435 }; |
| 260 | |
| 261 WebInspector.WatchExpression.prototype = { | |
| 262 | |
| 263 /** | |
| 264 * @return {!Element} | |
| 265 */ | |
| 266 element: function() | |
| 267 { | |
| 268 return this._element; | |
| 269 }, | |
| 270 | |
| 271 /** | |
| 272 * @return {?string} | |
| 273 */ | |
| 274 expression: function() | |
| 275 { | |
| 276 return this._expression; | |
| 277 }, | |
| 278 | |
| 279 update: function() | |
| 280 { | |
| 281 var currentExecutionContext = WebInspector.context.flavor(WebInspector.E
xecutionContext); | |
| 282 if (currentExecutionContext && this._expression) | |
| 283 currentExecutionContext.evaluate(this._expression, WebInspector.Watc
hExpression._watchObjectGroupId, false, true, false, false, false, this._createW
atchExpression.bind(this)); | |
| 284 }, | |
| 285 | |
| 286 startEditing: function() | |
| 287 { | |
| 288 this._editing = true; | |
| 289 this._element.removeChild(this._objectPresentationElement); | |
| 290 var newDiv = this._element.createChild("div"); | |
| 291 newDiv.textContent = this._nameElement.textContent; | |
| 292 this._textPrompt = new WebInspector.ObjectPropertyPrompt(); | |
| 293 this._textPrompt.renderAsBlock(); | |
| 294 var proxyElement = this._textPrompt.attachAndStartEditing(newDiv, this._
finishEditing.bind(this)); | |
| 295 proxyElement.classList.add("watch-expression-text-prompt-proxy"); | |
| 296 proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this),
false); | |
| 297 this._element.getComponentSelection().setBaseAndExtent(newDiv, 0, newDiv
, 1); | |
| 298 }, | |
| 299 | |
| 300 /** | |
| 301 * @return {boolean} | |
| 302 */ | |
| 303 isEditing: function() | |
| 304 { | |
| 305 return !!this._editing; | |
| 306 }, | |
| 307 | |
| 308 /** | |
| 309 * @param {!Event} event | |
| 310 * @param {boolean=} canceled | |
| 311 */ | |
| 312 _finishEditing: function(event, canceled) | |
| 313 { | |
| 314 if (event) | |
| 315 event.consume(true); | |
| 316 | |
| 317 this._editing = false; | |
| 318 this._textPrompt.detach(); | |
| 319 var newExpression = canceled ? this._expression : this._textPrompt.text(
); | |
| 320 delete this._textPrompt; | |
| 321 this._element.removeChildren(); | |
| 322 this._element.appendChild(this._objectPresentationElement); | |
| 323 this._updateExpression(newExpression); | |
| 324 }, | |
| 325 | |
| 326 /** | |
| 327 * @param {!Event} event | |
| 328 */ | |
| 329 _dblClickOnWatchExpression: function(event) | |
| 330 { | |
| 331 event.consume(); | |
| 332 if (!this.isEditing()) | |
| 333 this.startEditing(); | |
| 334 }, | |
| 335 | |
| 336 /** | |
| 337 * @param {?string} newExpression | |
| 338 */ | |
| 339 _updateExpression: function(newExpression) | |
| 340 { | |
| 341 if (this._expression) | |
| 342 this._expandController.stopWatchSectionsWithId(this._expression); | |
| 343 this._expression = newExpression; | |
| 344 this.update(); | |
| 345 this.dispatchEventToListeners(WebInspector.WatchExpression.Events.Expres
sionUpdated); | |
| 346 }, | |
| 347 | |
| 348 /** | |
| 349 * @param {!Event} event | |
| 350 */ | |
| 351 _deleteWatchExpression: function(event) | |
| 352 { | |
| 353 event.consume(true); | |
| 354 this._updateExpression(null); | |
| 355 }, | |
| 356 | |
| 357 /** | |
| 358 * @param {?WebInspector.RemoteObject} result | |
| 359 * @param {!RuntimeAgent.ExceptionDetails=} exceptionDetails | |
| 360 */ | |
| 361 _createWatchExpression: function(result, exceptionDetails) | |
| 362 { | |
| 363 this._result = result; | |
| 364 | |
| 365 var headerElement = createElementWithClass("div", "watch-expression-head
er"); | |
| 366 var deleteButton = headerElement.createChild("button", "watch-expression
-delete-button"); | |
| 367 deleteButton.title = WebInspector.UIString("Delete watch expression"); | |
| 368 deleteButton.addEventListener("click", this._deleteWatchExpression.bind(
this), false); | |
| 369 | |
| 370 var titleElement = headerElement.createChild("div", "watch-expression-ti
tle"); | |
| 371 this._nameElement = WebInspector.ObjectPropertiesSection.createNameEleme
nt(this._expression); | |
| 372 if (!!exceptionDetails || !result) { | |
| 373 this._valueElement = createElementWithClass("span", "watch-expressio
n-error value"); | |
| 374 titleElement.classList.add("dimmed"); | |
| 375 this._valueElement.textContent = WebInspector.UIString("<not availab
le>"); | |
| 376 } else { | |
| 377 this._valueElement = WebInspector.ObjectPropertiesSection.createValu
eElementWithCustomSupport(result, !!exceptionDetails, titleElement, this._linkif
ier); | |
| 378 } | |
| 379 var separatorElement = createElementWithClass("span", "watch-expressions
-separator"); | |
| 380 separatorElement.textContent = ": "; | |
| 381 titleElement.appendChildren(this._nameElement, separatorElement, this._v
alueElement); | |
| 382 | |
| 383 this._element.removeChildren(); | |
| 384 this._objectPropertiesSection = null; | |
| 385 if (!exceptionDetails && result && result.hasChildren && !result.customP
review()) { | |
| 386 headerElement.classList.add("watch-expression-object-header"); | |
| 387 this._objectPropertiesSection = new WebInspector.ObjectPropertiesSec
tion(result, headerElement, this._linkifier); | |
| 388 this._objectPresentationElement = this._objectPropertiesSection.elem
ent; | |
| 389 this._expandController.watchSection(/** @type {string} */ (this._exp
ression), this._objectPropertiesSection); | |
| 390 var objectTreeElement = this._objectPropertiesSection.objectTreeElem
ent(); | |
| 391 objectTreeElement.toggleOnClick = false; | |
| 392 objectTreeElement.listItemElement.addEventListener("click", this._on
SectionClick.bind(this), false); | |
| 393 objectTreeElement.listItemElement.addEventListener("dblclick", this.
_dblClickOnWatchExpression.bind(this)); | |
| 394 } else { | |
| 395 this._objectPresentationElement = headerElement; | |
| 396 this._objectPresentationElement.addEventListener("dblclick", this._d
blClickOnWatchExpression.bind(this)); | |
| 397 } | |
| 398 | |
| 399 this._element.appendChild(this._objectPresentationElement); | |
| 400 }, | |
| 401 | |
| 402 /** | |
| 403 * @param {!Event} event | |
| 404 */ | |
| 405 _onSectionClick: function(event) | |
| 406 { | |
| 407 event.consume(true); | |
| 408 if (event.detail === 1) { | |
| 409 this._preventClickTimeout = setTimeout(handleClick.bind(this), 333); | |
| 410 } else { | |
| 411 clearTimeout(this._preventClickTimeout); | |
| 412 delete this._preventClickTimeout; | |
| 413 } | |
| 414 | |
| 415 /** | |
| 416 * @this {WebInspector.WatchExpression} | |
| 417 */ | |
| 418 function handleClick() | |
| 419 { | |
| 420 if (!this._objectPropertiesSection) | |
| 421 return; | |
| 422 | |
| 423 var objectTreeElement = this._objectPropertiesSection.objectTreeElem
ent(); | |
| 424 if (objectTreeElement.expanded) | |
| 425 objectTreeElement.collapse(); | |
| 426 else | |
| 427 objectTreeElement.expand(); | |
| 428 } | |
| 429 }, | |
| 430 | |
| 431 /** | |
| 432 * @param {!Event} event | |
| 433 */ | |
| 434 _promptKeyDown: function(event) | |
| 435 { | |
| 436 if (isEnterKey(event) || isEscKey(event)) | |
| 437 this._finishEditing(event, isEscKey(event)); | |
| 438 }, | |
| 439 | |
| 440 /** | |
| 441 * @param {!WebInspector.ContextMenu} contextMenu | |
| 442 * @param {!Event} event | |
| 443 */ | |
| 444 _populateContextMenu: function(contextMenu, event) | |
| 445 { | |
| 446 if (!this.isEditing()) | |
| 447 contextMenu.appendItem(WebInspector.UIString.capitalize("Delete ^wat
ch ^expression"), this._updateExpression.bind(this, null)); | |
| 448 | |
| 449 if (!this.isEditing() && this._result && (this._result.type === "number"
|| this._result.type === "string")) | |
| 450 contextMenu.appendItem(WebInspector.UIString.capitalize("Copy ^value
"), this._copyValueButtonClicked.bind(this)); | |
| 451 | |
| 452 var target = event.deepElementFromPoint(); | |
| 453 if (target && this._valueElement.isSelfOrAncestor(target)) | |
| 454 contextMenu.appendApplicableItems(this._result); | |
| 455 }, | |
| 456 | |
| 457 _copyValueButtonClicked: function() | |
| 458 { | |
| 459 InspectorFrontendHost.copyText(this._valueElement.textContent); | |
| 460 }, | |
| 461 | |
| 462 __proto__: WebInspector.Object.prototype | |
| 463 }; | |
| OLD | NEW |