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 |
(...skipping 18 matching lines...) Expand all Loading... |
29 */ | 29 */ |
30 | 30 |
31 /** | 31 /** |
32 * @constructor | 32 * @constructor |
33 * @extends {WebInspector.SidebarPane} | 33 * @extends {WebInspector.SidebarPane} |
34 */ | 34 */ |
35 WebInspector.WatchExpressionsSidebarPane = function() | 35 WebInspector.WatchExpressionsSidebarPane = function() |
36 { | 36 { |
37 WebInspector.SidebarPane.call(this, WebInspector.UIString("Watch Expressions
")); | 37 WebInspector.SidebarPane.call(this, WebInspector.UIString("Watch Expressions
")); |
38 | 38 |
39 this.section = new WebInspector.WatchExpressionsSection(); | 39 this._requiresUpdate = true; |
40 this.bodyElement.appendChild(this.section.element); | 40 /** @type {!Array.<!WebInspector.WatchExpression>} */ |
| 41 this._watchExpressions = []; |
| 42 |
| 43 |
| 44 this.bodyElement.classList.add("vbox", "watch-expressions"); |
| 45 this.bodyElement.addEventListener("contextmenu", this._contextMenu.bind(this
), false); |
41 | 46 |
42 var refreshButton = this.titleElement.createChild("button", "pane-title-butt
on refresh"); | 47 var refreshButton = this.titleElement.createChild("button", "pane-title-butt
on refresh"); |
43 refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this
), false); | 48 refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this
), false); |
44 refreshButton.title = WebInspector.UIString("Refresh"); | 49 refreshButton.title = WebInspector.UIString("Refresh"); |
45 | 50 |
46 var addButton = this.titleElement.createChild("button", "pane-title-button a
dd"); | 51 var addButton = this.titleElement.createChild("button", "pane-title-button a
dd"); |
47 addButton.addEventListener("click", this._addButtonClicked.bind(this), false
); | 52 addButton.addEventListener("click", this._addButtonClicked.bind(this), false
); |
48 addButton.title = WebInspector.UIString("Add watch expression"); | 53 addButton.title = WebInspector.UIString("Add watch expression"); |
49 | |
50 this._requiresUpdate = true; | |
51 WebInspector.context.addFlavorChangeListener(WebInspector.ExecutionContext,
this.refreshExpressions, this); | 54 WebInspector.context.addFlavorChangeListener(WebInspector.ExecutionContext,
this.refreshExpressions, this); |
52 } | 55 } |
53 | 56 |
54 WebInspector.WatchExpressionsSidebarPane.prototype = { | 57 WebInspector.WatchExpressionsSidebarPane.prototype = { |
55 wasShown: function() | 58 wasShown: function() |
56 { | 59 { |
57 this._refreshExpressionsIfNeeded(); | 60 this._refreshExpressionsIfNeeded(); |
58 }, | 61 }, |
59 | 62 |
60 refreshExpressions: function() | 63 refreshExpressions: function() |
61 { | 64 { |
62 this._requiresUpdate = true; | 65 this._requiresUpdate = true; |
63 this._refreshExpressionsIfNeeded(); | 66 this._refreshExpressionsIfNeeded(); |
64 }, | 67 }, |
65 | 68 |
66 /** | 69 /** |
67 * @param {string} expression | 70 * @param {string} expressionString |
68 */ | 71 */ |
69 addExpression: function(expression) | 72 addExpression: function(expressionString) |
70 { | 73 { |
71 this.section.addExpression(expression); | |
72 this.expand(); | 74 this.expand(); |
| 75 if (this._requiresUpdate) { |
| 76 this._rebuildWatchExpressions(); |
| 77 delete this._requiresUpdate; |
| 78 } |
| 79 this._createWatchExpression(expressionString); |
| 80 this._saveExpressions(); |
| 81 }, |
| 82 |
| 83 _saveExpressions: function() |
| 84 { |
| 85 var toSave = []; |
| 86 for (var i = 0; i < this._watchExpressions.length; i++) |
| 87 if (this._watchExpressions[i].expression()) |
| 88 toSave.push(this._watchExpressions[i].expression()); |
| 89 |
| 90 WebInspector.settings.watchExpressions.set(toSave); |
73 }, | 91 }, |
74 | 92 |
75 _refreshExpressionsIfNeeded: function() | 93 _refreshExpressionsIfNeeded: function() |
76 { | 94 { |
77 if (this._requiresUpdate && this.isShowing()) { | 95 if (this._requiresUpdate && this.isShowing()) { |
78 this.section.update(); | 96 this._rebuildWatchExpressions(); |
79 delete this._requiresUpdate; | 97 delete this._requiresUpdate; |
80 } else | 98 } else |
81 this._requiresUpdate = true; | 99 this._requiresUpdate = true; |
82 }, | 100 }, |
83 | 101 |
| 102 /** |
| 103 * @param {?Event} event |
| 104 */ |
84 _addButtonClicked: function(event) | 105 _addButtonClicked: function(event) |
85 { | 106 { |
86 event.consume(); | 107 if (event) |
| 108 event.consume(true); |
87 this.expand(); | 109 this.expand(); |
88 this.section.addNewExpressionAndEdit(); | 110 this._createWatchExpression(null).startEditing(); |
89 }, | 111 }, |
90 | 112 |
| 113 /** |
| 114 * @param {!Event} event |
| 115 */ |
91 _refreshButtonClicked: function(event) | 116 _refreshButtonClicked: function(event) |
92 { | 117 { |
93 event.consume(); | 118 event.consume(); |
94 this.refreshExpressions(); | 119 this.refreshExpressions(); |
95 }, | 120 }, |
96 | 121 |
| 122 _rebuildWatchExpressions: function() |
| 123 { |
| 124 this.bodyElement.removeChildren(); |
| 125 this._watchExpressions = []; |
| 126 this._emptyElement = this.bodyElement.createChild("div", "info"); |
| 127 this._emptyElement.textContent = WebInspector.UIString("No Watch Express
ions"); |
| 128 var watchExpressionStrings = WebInspector.settings.watchExpressions.get(
); |
| 129 for (var i = 0; i < watchExpressionStrings.length; ++i) { |
| 130 var expression = watchExpressionStrings[i]; |
| 131 if (!expression) |
| 132 continue; |
| 133 |
| 134 this._createWatchExpression(expression); |
| 135 } |
| 136 }, |
| 137 |
| 138 /** |
| 139 * @param {?string} expression |
| 140 * @return {!WebInspector.WatchExpression} |
| 141 */ |
| 142 _createWatchExpression: function(expression) |
| 143 { |
| 144 this._emptyElement.classList.add("hidden"); |
| 145 var watchExpression = new WebInspector.WatchExpression(expression); |
| 146 watchExpression.addEventListener(WebInspector.WatchExpression.Events.Exp
ressionUpdated, this._watchExpressionUpdated.bind(this)); |
| 147 this.bodyElement.appendChild(watchExpression.element()); |
| 148 this._watchExpressions.push(watchExpression); |
| 149 return watchExpression; |
| 150 }, |
| 151 |
| 152 /** |
| 153 * @param {!WebInspector.Event} event |
| 154 */ |
| 155 _watchExpressionUpdated: function(event) |
| 156 { |
| 157 var watchExpression = /** @type {!WebInspector.WatchExpression} */ (even
t.target); |
| 158 if (!watchExpression.expression()) { |
| 159 this._watchExpressions.remove(watchExpression); |
| 160 this.bodyElement.removeChild(watchExpression.element()); |
| 161 this._emptyElement.classList.toggle("hidden", !!this._watchExpressio
ns.length); |
| 162 } |
| 163 |
| 164 this._saveExpressions(); |
| 165 }, |
| 166 |
| 167 /** |
| 168 * @param {!Event} event |
| 169 */ |
| 170 _contextMenu: function(event) |
| 171 { |
| 172 var contextMenu = new WebInspector.ContextMenu(event); |
| 173 this._populateContextMenu(contextMenu, event); |
| 174 contextMenu.show(); |
| 175 }, |
| 176 |
| 177 /** |
| 178 * @param {!WebInspector.ContextMenu} contextMenu |
| 179 * @param {!Event} event |
| 180 */ |
| 181 _populateContextMenu: function(contextMenu, event) |
| 182 { |
| 183 var isEditing = false; |
| 184 for (var watchExpression of this._watchExpressions) |
| 185 isEditing |= watchExpression.isEditing(); |
| 186 |
| 187 if (!isEditing) |
| 188 contextMenu.appendItem(WebInspector.UIString.capitalize("Add ^watch
^expression"), this._addButtonClicked.bind(this)); |
| 189 |
| 190 if (this._watchExpressions.length > 1) |
| 191 contextMenu.appendItem(WebInspector.UIString.capitalize("Delete ^all
^watch ^expressions"), this._deleteAllButtonClicked.bind(this)); |
| 192 |
| 193 for (var watchExpression of this._watchExpressions) |
| 194 if (watchExpression.element().containsEventPoint(event)) |
| 195 watchExpression._populateContextMenu(contextMenu, event); |
| 196 }, |
| 197 |
| 198 _deleteAllButtonClicked: function() |
| 199 { |
| 200 this._watchExpressions = []; |
| 201 this._saveExpressions(); |
| 202 this._rebuildWatchExpressions(); |
| 203 }, |
| 204 |
97 __proto__: WebInspector.SidebarPane.prototype | 205 __proto__: WebInspector.SidebarPane.prototype |
98 } | 206 } |
99 | 207 |
100 /** | 208 /** |
101 * @constructor | 209 * @constructor |
102 * @extends {WebInspector.PropertiesSection} | 210 * @extends {WebInspector.Object} |
| 211 * @param {?string} expression |
103 */ | 212 */ |
104 WebInspector.WatchExpressionsSection = function() | 213 WebInspector.WatchExpression = function(expression) |
105 { | 214 { |
106 this._watchObjectGroupId = "watch-group"; | 215 this._expression = expression; |
107 | 216 this._element = createElementWithClass("div", "watch-expression monospace"); |
108 WebInspector.PropertiesSection.call(this, ""); | 217 this._editing = false; |
109 this.treeElementConstructor = WebInspector.ObjectPropertyTreeElement; | 218 |
110 this.skipProto = false; | 219 this._createWatchExpression(null, false); |
111 | 220 this.update(); |
112 this.emptyElement = createElementWithClass("div", "info"); | |
113 this.emptyElement.textContent = WebInspector.UIString("No Watch Expressions"
); | |
114 | |
115 /** @type {!Array.<string>} */ | |
116 this.watchExpressions = WebInspector.settings.watchExpressions.get(); | |
117 | |
118 this.headerElement.className = "hidden"; | |
119 this.editable = true; | |
120 this.expand(); | |
121 this.propertiesElement.classList.add("watch-expressions"); | |
122 | |
123 this.element.addEventListener("mousemove", this._mouseMove.bind(this), true)
; | |
124 this.element.addEventListener("mouseleave", this._mouseLeave.bind(this), tru
e); | |
125 this.element.addEventListener("dblclick", this._sectionDoubleClick.bind(this
), false); | |
126 this.emptyElement.addEventListener("contextmenu", this._emptyElementContextM
enu.bind(this), false); | |
127 } | 221 } |
128 | 222 |
129 WebInspector.WatchExpressionsSection.NewWatchExpression = "\xA0"; | 223 WebInspector.WatchExpression._watchObjectGroupId = "watch-group"; |
130 | 224 |
131 WebInspector.WatchExpressionsSection.prototype = { | 225 WebInspector.WatchExpression.Events = { |
132 /** | 226 ExpressionUpdated: "ExpressionUpdated" |
133 * @param {!Event=} e | 227 } |
134 */ | 228 |
135 update: function(e) | 229 WebInspector.WatchExpression.prototype = { |
136 { | 230 |
137 if (e) | 231 /** |
138 e.consume(); | 232 * @return {!Element} |
139 | 233 */ |
140 /*** | 234 element: function() |
141 * @param {string} expression | 235 { |
142 * @param {number} watchIndex | 236 return this._element; |
143 * @param {?WebInspector.RemoteObject} result | 237 }, |
144 * @param {boolean} wasThrown | 238 |
145 * @this {WebInspector.WatchExpressionsSection} | 239 /** |
146 */ | 240 * @return {?string} |
147 function appendResult(expression, watchIndex, result, wasThrown) | 241 */ |
148 { | 242 expression: function() |
149 if (!result) | 243 { |
150 return; | 244 return this._expression; |
151 | 245 }, |
152 var property = new WebInspector.RemoteObjectProperty(expression, res
ult); | 246 |
153 property.watchIndex = watchIndex; | 247 update: function() |
154 property.wasThrown = wasThrown; | 248 { |
155 | |
156 // To clarify what's going on here: | |
157 // In the outer function, we calculate the number of properties | |
158 // that we're going to be updating, and set that in the | |
159 // propertyCount variable. | |
160 // In this function, we test to see when we are processing the | |
161 // last property, and then call the superclass's updateProperties() | |
162 // method to get all the properties refreshed at once. | |
163 properties.push(property); | |
164 | |
165 if (properties.length == propertyCount) { | |
166 this.updateProperties(properties); | |
167 | |
168 // check to see if we just added a new watch expression, | |
169 // which will always be the last property | |
170 if (this._newExpressionAdded) { | |
171 delete this._newExpressionAdded; | |
172 | |
173 var treeElement = this.findAddedTreeElement(); | |
174 if (treeElement) | |
175 treeElement.startEditing(); | |
176 } | |
177 | |
178 // Force displaying delete button for hovered element. | |
179 if (this._lastMouseMovePageY) | |
180 this._updateHoveredElement(this._lastMouseMovePageY); | |
181 } | |
182 } | |
183 | |
184 // TODO: pass exact injected script id. | |
185 WebInspector.targetManager.targets().forEach(function(target) { target.r
untimeAgent().releaseObjectGroup(this._watchObjectGroupId); }, this); | |
186 var properties = []; | |
187 | |
188 // Count the properties, so we known when to call this.updateProperties(
) | |
189 // in appendResult() | |
190 var propertyCount = 0; | |
191 for (var i = 0; i < this.watchExpressions.length; ++i) { | |
192 if (!this.watchExpressions[i]) | |
193 continue; | |
194 ++propertyCount; | |
195 } | |
196 | |
197 // Now process all the expressions, since we have the actual count, | |
198 // which is checked in the appendResult inner function. | |
199 var currentExecutionContext = WebInspector.context.flavor(WebInspector.E
xecutionContext); | 249 var currentExecutionContext = WebInspector.context.flavor(WebInspector.E
xecutionContext); |
200 if (currentExecutionContext) { | 250 if (currentExecutionContext && this._expression) |
201 for (var i = 0; i < this.watchExpressions.length; ++i) { | 251 currentExecutionContext.evaluate(this._expression, WebInspector.Watc
hExpression._watchObjectGroupId, false, true, false, false, this._createWatchExp
ression.bind(this)); |
202 var expression = this.watchExpressions[i]; | 252 }, |
203 if (!expression) | 253 |
204 continue; | 254 startEditing: function() |
205 | 255 { |
206 currentExecutionContext.evaluate(expression, this._watchObjectGr
oupId, false, true, false, false, appendResult.bind(this, expression, i)); | 256 this._editing = true; |
207 } | 257 this._element.removeChild(this._objectPresentationElement); |
208 } | 258 var newDiv = this._element.createChild("div"); |
209 | 259 newDiv.textContent = this._nameElement.textContent; |
210 if (!propertyCount) { | 260 this._textPrompt = new WebInspector.ObjectPropertyPrompt(); |
211 this.element.appendChild(this.emptyElement); | 261 this._textPrompt.renderAsBlock(); |
212 this.propertiesElement.remove(); | 262 var proxyElement = this._textPrompt.attachAndStartEditing(newDiv, this._
finishEditing.bind(this, this._expression)); |
213 this.propertiesTreeOutline.removeChildren(); | 263 proxyElement.classList.add("watch-expression-text-prompt-proxy"); |
| 264 proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this),
false); |
| 265 this._element.getComponentSelection().setBaseAndExtent(newDiv, 0, newDiv
, 1); |
| 266 }, |
| 267 |
| 268 /** |
| 269 * @return {boolean} |
| 270 */ |
| 271 isEditing: function() |
| 272 { |
| 273 return !!this._editing; |
| 274 }, |
| 275 |
| 276 /** |
| 277 * @param {?string} newExpression |
| 278 * @param {!Event} event |
| 279 */ |
| 280 _finishEditing: function(newExpression, event) |
| 281 { |
| 282 if (event) |
| 283 event.consume(true); |
| 284 |
| 285 this._editing = false; |
| 286 this._textPrompt.detach(); |
| 287 delete this._textPrompt; |
| 288 this._element.removeChildren(); |
| 289 this._element.appendChild(this._objectPresentationElement); |
| 290 this._updateExpression(newExpression); |
| 291 }, |
| 292 |
| 293 /** |
| 294 * @param {!Event} event |
| 295 */ |
| 296 _dblClickOnWatchExpression: function(event) |
| 297 { |
| 298 event.consume(); |
| 299 if (!this.isEditing()) |
| 300 this.startEditing(); |
| 301 }, |
| 302 |
| 303 /** |
| 304 * @param {?string} newExpression |
| 305 */ |
| 306 _updateExpression: function(newExpression) |
| 307 { |
| 308 this._expression = newExpression; |
| 309 this.update(); |
| 310 this.dispatchEventToListeners(WebInspector.WatchExpression.Events.Expres
sionUpdated); |
| 311 }, |
| 312 |
| 313 /** |
| 314 * @param {!Event} event |
| 315 */ |
| 316 _deleteWatchExpression: function(event) |
| 317 { |
| 318 event.consume(true); |
| 319 this._updateExpression(null); |
| 320 }, |
| 321 |
| 322 /** |
| 323 * @param {?WebInspector.RemoteObject} result |
| 324 * @param {boolean} wasThrown |
| 325 */ |
| 326 _createWatchExpression: function(result, wasThrown) |
| 327 { |
| 328 this._result = result; |
| 329 |
| 330 var titleElement = createElementWithClass("div", "watch-expression-title
"); |
| 331 this._nameElement = WebInspector.ObjectPropertiesSection.createNameEleme
nt(this._expression); |
| 332 if (wasThrown || !result) { |
| 333 this._valueElement = createElementWithClass("span", "console-formatt
ed-undefined value"); |
| 334 titleElement.classList.add("dimmed"); |
| 335 this._valueElement.textContent = WebInspector.UIString("<not availab
le>"); |
214 } else { | 336 } else { |
215 this.element.appendChild(this.propertiesElement); | 337 this._valueElement = WebInspector.ObjectPropertiesSection.createValu
eElement(result, wasThrown, titleElement); |
216 this.emptyElement.remove(); | 338 } |
217 } | 339 var separatorElement = createElementWithClass("span", "separator"); |
218 }, | 340 separatorElement.textContent = ": "; |
219 | 341 titleElement.appendChildren(this._nameElement, separatorElement, this._v
alueElement); |
220 /** | 342 |
221 * @param {!Array.<!WebInspector.RemoteObjectProperty>} properties | 343 if (!wasThrown && result && result.hasChildren) { |
222 */ | 344 var objectPropertiesSection = new WebInspector.ObjectPropertiesSecti
on(result, titleElement); |
223 updateProperties: function(properties) | 345 this._objectPresentationElement = objectPropertiesSection.element; |
224 { | 346 objectPropertiesSection.headerElement.addEventListener("click", this
._onSectionClick.bind(this, objectPropertiesSection), false); |
225 this.propertiesTreeOutline.removeChildren(); | 347 objectPropertiesSection.doNotExpandOnTitleClick(); |
226 WebInspector.ObjectPropertyTreeElement.populateWithProperties(this.prope
rtiesTreeOutline, properties, [], | 348 this._installHover(objectPropertiesSection.headerElement); |
227 WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressio
nsSection.CompareProperties, false, null); | |
228 | |
229 this.propertiesForTest = properties; | |
230 }, | |
231 | |
232 /** | |
233 * @param {string} expression | |
234 */ | |
235 addExpression: function(expression) | |
236 { | |
237 this.watchExpressions.push(expression); | |
238 this.saveExpressions(); | |
239 this.update(); | |
240 }, | |
241 | |
242 addNewExpressionAndEdit: function() | |
243 { | |
244 this._newExpressionAdded = true; | |
245 this.watchExpressions.push(WebInspector.WatchExpressionsSection.NewWatch
Expression); | |
246 this.update(); | |
247 }, | |
248 | |
249 _sectionDoubleClick: function(event) | |
250 { | |
251 if (event.target !== this.element && event.target !== this.propertiesEle
ment && event.target !== this.emptyElement) | |
252 return; | |
253 event.consume(); | |
254 this.addNewExpressionAndEdit(); | |
255 }, | |
256 | |
257 /** | |
258 * @param {!WebInspector.ObjectPropertyTreeElement} element | |
259 * @param {?string} value | |
260 */ | |
261 updateExpression: function(element, value) | |
262 { | |
263 if (value === null) { | |
264 var index = element.property.watchIndex; | |
265 this.watchExpressions.splice(index, 1); | |
266 } else { | 349 } else { |
267 this.watchExpressions[element.property.watchIndex] = value; | 350 this._objectPresentationElement = this._element.createChild("div", "
primitive-value"); |
268 } | 351 this._objectPresentationElement.appendChild(titleElement); |
269 this.saveExpressions(); | 352 this._installHover(this._objectPresentationElement); |
270 this.update(); | 353 } |
271 }, | 354 |
272 | 355 this._element.removeChildren(); |
273 _deleteAllExpressions: function() | 356 this._element.appendChild(this._objectPresentationElement); |
274 { | 357 this._element.addEventListener("dblclick", this._dblClickOnWatchExpressi
on.bind(this)); |
275 this.watchExpressions = []; | 358 }, |
276 this.saveExpressions(); | 359 |
277 this.update(); | 360 /** |
278 }, | 361 * @param {!Element} hoverableElement |
279 | 362 */ |
280 /** | 363 _installHover: function(hoverableElement) |
281 * @return {?TreeElement} | 364 { |
282 */ | |
283 findAddedTreeElement: function() | |
284 { | |
285 var children = this.propertiesTreeOutline.children; | |
286 for (var i = 0; i < children.length; ++i) { | |
287 if (children[i].property.name === WebInspector.WatchExpressionsSecti
on.NewWatchExpression) | |
288 return children[i]; | |
289 } | |
290 return null; | |
291 }, | |
292 | |
293 /** | |
294 * @return {number} | |
295 */ | |
296 saveExpressions: function() | |
297 { | |
298 var toSave = []; | |
299 for (var i = 0; i < this.watchExpressions.length; i++) | |
300 if (this.watchExpressions[i]) | |
301 toSave.push(this.watchExpressions[i]); | |
302 | |
303 WebInspector.settings.watchExpressions.set(toSave); | |
304 return toSave.length; | |
305 }, | |
306 | |
307 _mouseMove: function(e) | |
308 { | |
309 if (this.propertiesElement.firstChild) | |
310 this._updateHoveredElement(e.pageY); | |
311 }, | |
312 | |
313 _mouseLeave: function() | |
314 { | |
315 if (this._hoveredElement) { | |
316 this._hoveredElement.classList.remove("hovered"); | |
317 delete this._hoveredElement; | |
318 } | |
319 delete this._lastMouseMovePageY; | |
320 }, | |
321 | |
322 _updateHoveredElement: function(pageY) | |
323 { | |
324 var candidateElement = this.propertiesElement.firstChild; | |
325 while (true) { | |
326 var next = candidateElement.nextSibling; | |
327 while (next && !next.clientHeight) | |
328 next = next.nextSibling; | |
329 if (!next || next.totalOffsetTop() > pageY) | |
330 break; | |
331 candidateElement = next; | |
332 } | |
333 | |
334 if (this._hoveredElement !== candidateElement) { | |
335 if (this._hoveredElement) | |
336 this._hoveredElement.classList.remove("hovered"); | |
337 if (candidateElement) | |
338 candidateElement.classList.add("hovered"); | |
339 this._hoveredElement = candidateElement; | |
340 } | |
341 | |
342 this._lastMouseMovePageY = pageY; | |
343 }, | |
344 | |
345 _emptyElementContextMenu: function(event) | |
346 { | |
347 var contextMenu = new WebInspector.ContextMenu(event); | |
348 contextMenu.appendItem(WebInspector.UIString.capitalize("Add ^watch ^exp
ression"), this.addNewExpressionAndEdit.bind(this)); | |
349 contextMenu.show(); | |
350 }, | |
351 | |
352 __proto__: WebInspector.PropertiesSection.prototype | |
353 } | |
354 | |
355 /** | |
356 * @param {!WebInspector.RemoteObjectProperty} propertyA | |
357 * @param {!WebInspector.RemoteObjectProperty} propertyB | |
358 * @return {number} | |
359 */ | |
360 WebInspector.WatchExpressionsSection.CompareProperties = function(propertyA, pro
pertyB) | |
361 { | |
362 if (propertyA.watchIndex == propertyB.watchIndex) | |
363 return 0; | |
364 else if (propertyA.watchIndex < propertyB.watchIndex) | |
365 return -1; | |
366 else | |
367 return 1; | |
368 } | |
369 | |
370 /** | |
371 * @constructor | |
372 * @extends {WebInspector.ObjectPropertyTreeElement} | |
373 * @param {!WebInspector.RemoteObjectProperty} property | |
374 */ | |
375 WebInspector.WatchExpressionTreeElement = function(property) | |
376 { | |
377 WebInspector.ObjectPropertyTreeElement.call(this, property); | |
378 } | |
379 | |
380 WebInspector.WatchExpressionTreeElement.prototype = { | |
381 /** | |
382 * @override | |
383 * @return {*} | |
384 */ | |
385 elementIdentity: function() | |
386 { | |
387 return this.property.name; | |
388 }, | |
389 | |
390 update: function() | |
391 { | |
392 WebInspector.ObjectPropertyTreeElement.prototype.update.call(this); | |
393 | |
394 if (this.property.wasThrown) { | |
395 this.valueElement.textContent = WebInspector.UIString("<not availabl
e>"); | |
396 this.listItemElement.classList.add("dimmed"); | |
397 } else { | |
398 this.listItemElement.classList.remove("dimmed"); | |
399 } | |
400 | |
401 var deleteButton = createElementWithClass("button", "delete-button"); | 365 var deleteButton = createElementWithClass("button", "delete-button"); |
402 deleteButton.title = WebInspector.UIString("Delete watch expression"); | 366 deleteButton.title = WebInspector.UIString("Delete watch expression"); |
403 deleteButton.addEventListener("click", this._deleteButtonClicked.bind(th
is), false); | 367 deleteButton.addEventListener("click", this._deleteWatchExpression.bind(
this), false); |
404 this.listItemElement.addEventListener("contextmenu", this._contextMenu.b
ind(this), false); | 368 hoverableElement.insertBefore(deleteButton, hoverableElement.firstChild)
; |
405 this.listItemElement.insertBefore(deleteButton, this.listItemElement.fir
stChild); | 369 }, |
| 370 |
| 371 /** |
| 372 * @param {!WebInspector.ObjectPropertiesSection} objectPropertiesSection |
| 373 * @param {!Event} event |
| 374 */ |
| 375 _onSectionClick: function(objectPropertiesSection, event) |
| 376 { |
| 377 event.consume(true); |
| 378 if (event.detail == 1) { |
| 379 this._preventClickTimeout = setTimeout(handleClick, 333); |
| 380 } else { |
| 381 clearTimeout(this._preventClickTimeout); |
| 382 delete this._preventClickTimeout; |
| 383 } |
| 384 |
| 385 function handleClick() |
| 386 { |
| 387 if (objectPropertiesSection.expanded) |
| 388 objectPropertiesSection.collapse(); |
| 389 else |
| 390 objectPropertiesSection.expand(); |
| 391 } |
| 392 }, |
| 393 |
| 394 /** |
| 395 * @param {!Event} event |
| 396 */ |
| 397 _promptKeyDown: function(event) |
| 398 { |
| 399 if (isEnterKey(event)) { |
| 400 this._finishEditing(this._textPrompt.text(), event); |
| 401 return; |
| 402 } |
| 403 if (event.keyIdentifier === "U+001B") { // Esc |
| 404 this._finishEditing(this._expression, event); |
| 405 return; |
| 406 } |
406 }, | 407 }, |
407 | 408 |
408 /** | 409 /** |
409 * @param {!WebInspector.ContextMenu} contextMenu | 410 * @param {!WebInspector.ContextMenu} contextMenu |
410 * @override | 411 * @param {!Event} event |
411 */ | 412 */ |
412 populateContextMenu: function(contextMenu) | 413 _populateContextMenu: function(contextMenu, event) |
413 { | 414 { |
414 if (!this.isEditing()) { | 415 if (!this.isEditing()) |
415 contextMenu.appendItem(WebInspector.UIString.capitalize("Add ^watch
^expression"), this.treeOutline.section.addNewExpressionAndEdit.bind(this.treeOu
tline.section)); | 416 contextMenu.appendItem(WebInspector.UIString.capitalize("Delete ^wat
ch ^expression"), this._updateExpression.bind(this, null)); |
416 contextMenu.appendItem(WebInspector.UIString.capitalize("Delete ^wat
ch ^expression"), this._deleteButtonClicked.bind(this, null)); | 417 |
417 } | 418 if (!this.isEditing() && this._result && (this._result.type === "number"
|| this._result.type === "string")) |
418 if (this.treeOutline.section.watchExpressions.length > 1) | |
419 contextMenu.appendItem(WebInspector.UIString.capitalize("Delete ^all
^watch ^expressions"), this._deleteAllButtonClicked.bind(this)); | |
420 if (!this.isEditing() && (this.property.value.type === "number" || this.
property.value.type === "string")) | |
421 contextMenu.appendItem(WebInspector.UIString.capitalize("Copy ^value
"), this._copyValueButtonClicked.bind(this)); | 419 contextMenu.appendItem(WebInspector.UIString.capitalize("Copy ^value
"), this._copyValueButtonClicked.bind(this)); |
422 }, | 420 |
423 | 421 if (this._valueElement.containsEventPoint(event)) |
424 _contextMenu: function(event) | 422 contextMenu.appendApplicableItems(this._result); |
425 { | |
426 var contextMenu = new WebInspector.ContextMenu(event); | |
427 this.populateContextMenu(contextMenu); | |
428 contextMenu.show(); | |
429 }, | |
430 | |
431 _deleteAllButtonClicked: function() | |
432 { | |
433 this.treeOutline.section._deleteAllExpressions(); | |
434 }, | |
435 | |
436 _deleteButtonClicked: function(event) | |
437 { | |
438 if (event) | |
439 event.consume(); | |
440 this.treeOutline.section.updateExpression(this, null); | |
441 }, | 423 }, |
442 | 424 |
443 _copyValueButtonClicked: function() | 425 _copyValueButtonClicked: function() |
444 { | 426 { |
445 InspectorFrontendHost.copyText(this.valueElement.textContent); | 427 InspectorFrontendHost.copyText(this._valueElement.textContent); |
446 }, | 428 }, |
447 | 429 |
448 /** | 430 __proto__: WebInspector.Object.prototype |
449 * @override | |
450 * @return {boolean} | |
451 */ | |
452 renderPromptAsBlock: function() | |
453 { | |
454 return true; | |
455 }, | |
456 | |
457 /** | |
458 * @override | |
459 * @return {{element: !Element, value: (string|undefined)}} | |
460 */ | |
461 elementAndValueToEdit: function() | |
462 { | |
463 return { element: this.nameElement, value: this.property.name.trim() }; | |
464 }, | |
465 | |
466 /** | |
467 * @override | |
468 */ | |
469 editingCancelled: function(element, context) | |
470 { | |
471 if (!context.elementToEdit.textContent) | |
472 this.treeOutline.section.updateExpression(this, null); | |
473 | |
474 WebInspector.ObjectPropertyTreeElement.prototype.editingCancelled.call(t
his, element, context); | |
475 }, | |
476 | |
477 /** | |
478 * @override | |
479 * @param {string} expression | |
480 */ | |
481 applyExpression: function(expression) | |
482 { | |
483 expression = expression.trim(); | |
484 this.property.name = expression || null; | |
485 this.treeOutline.section.updateExpression(this, expression); | |
486 }, | |
487 | |
488 __proto__: WebInspector.ObjectPropertyTreeElement.prototype | |
489 } | 431 } |
OLD | NEW |