2011-02-01 Pavel Podivilov <podivilov@chromium.org>
[WebKit-https.git] / Source / WebCore / inspector / front-end / BreakpointsSidebarPane.js
1 /*
2  * Copyright (C) 2008 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.JavaScriptBreakpointsSidebarPane = function(title)
27 {
28     WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));
29
30     this.listElement = document.createElement("ol");
31     this.listElement.className = "breakpoint-list";
32
33     this.emptyElement = document.createElement("div");
34     this.emptyElement.className = "info";
35     this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");
36
37     this.bodyElement.appendChild(this.emptyElement);
38
39     this._items = {};
40
41     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointAdded, this._breakpointAdded, this);
42     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
43     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
44     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
45     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
46     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
47     WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.ProjectChanged, this._projectChanged, this);
48 }
49
50 WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
51     _breakpointAdded: function(event)
52     {
53         var breakpoint = event.data;
54         var breakpointId = breakpoint.id;
55
56         if (breakpoint.url && !WebInspector.debuggerModel.scriptsForURL(breakpoint.url).length)
57             return;
58
59         var element = document.createElement("li");
60
61         var checkbox = document.createElement("input");
62         checkbox.className = "checkbox-elem";
63         checkbox.type = "checkbox";
64         checkbox.checked = breakpoint.enabled;
65         checkbox.addEventListener("click", this._breakpointItemCheckboxClicked.bind(this, breakpointId), false);
66         element.appendChild(checkbox);
67
68         var label = document.createElement("span");
69         element.appendChild(label);
70
71         element._data = breakpoint;
72         var currentElement = this.listElement.firstChild;
73         while (currentElement) {
74             if (currentElement._data && this._compareBreakpoints(currentElement._data, element._data) > 0)
75                 break;
76             currentElement = currentElement.nextSibling;
77         }
78         this._addListElement(element, currentElement);
79
80         element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this, breakpointId), true);
81
82         this._setupBreakpointElement(breakpoint, element);
83
84         var breakpointItem = {};
85         breakpointItem.element = element;
86         breakpointItem.checkbox = checkbox;
87         this._items[breakpointId] = breakpointItem;
88
89         if (!this.expanded)
90             this.expanded = true;
91     },
92
93     _breakpointRemoved: function(event)
94     {
95         var breakpointId = event.data;
96         var breakpointItem = this._items[breakpointId];
97         if (breakpointItem) {
98             delete this._items[breakpointId];
99             this._removeListElement(breakpointItem.element);
100         }
101     },
102
103     _breakpointResolved: function(event)
104     {
105         var breakpoint = event.data;
106         this._breakpointRemoved({ data: breakpoint.id });
107         this._breakpointAdded({ data: breakpoint });
108     },
109
110     _parsedScriptSource: function(event)
111     {
112         var url = event.data.sourceURL;
113         var breakpoints = WebInspector.debuggerModel.breakpoints;
114         for (var id in breakpoints) {
115             if (!(id in this._items))
116                 this._breakpointAdded({ data: breakpoints[id] });
117         }
118     },
119
120     _breakpointEnableChanged: function(enabled, event)
121     {
122         var breakpointId = event.data;
123         var breakpointItem = this._items[breakpointId];
124         if (breakpointItem)
125             breakpointItem.checkbox.checked = enabled;
126     },
127
128     _breakpointItemCheckboxClicked: function(breakpointId, event)
129     {
130         var breakpoint = WebInspector.debuggerModel.breakpointForId(breakpointId);
131         WebInspector.debuggerModel.updateBreakpoint(breakpointId, breakpoint.condition, event.target.checked);
132
133         // Breakpoint element may have it's own click handler.
134         event.stopPropagation();
135     },
136
137     _contextMenuEventFired: function(breakpointId, event)
138     {
139         var contextMenu = new WebInspector.ContextMenu();
140         contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), this._removeBreakpoint.bind(this, breakpointId));
141         contextMenu.show(event);
142     },
143
144     _debuggerPaused: function(event)
145     {
146         var breakpointId = this._breakpointIdForDebuggerPausedEvent(event.data);
147         if (!breakpointId)
148             return;
149         var breakpointItem = this._items[breakpointId];
150         if (!breakpointItem)
151             return;
152         breakpointItem.element.addStyleClass("breakpoint-hit");
153         this._lastHitBreakpointItem = breakpointItem;
154     },
155
156     _debuggerResumed: function()
157     {
158         if (this._lastHitBreakpointItem) {
159             this._lastHitBreakpointItem.element.removeStyleClass("breakpoint-hit");
160             delete this._lastHitBreakpointItem;
161         }
162     },
163
164     _addListElement: function(element, beforeElement)
165     {
166         if (beforeElement)
167             this.listElement.insertBefore(element, beforeElement);
168         else {
169             if (!this.listElement.firstChild) {
170                 this.bodyElement.removeChild(this.emptyElement);
171                 this.bodyElement.appendChild(this.listElement);
172             }
173             this.listElement.appendChild(element);
174         }
175     },
176
177     _removeListElement: function(element)
178     {
179         this.listElement.removeChild(element);
180         if (!this.listElement.firstChild) {
181             this.bodyElement.removeChild(this.listElement);
182             this.bodyElement.appendChild(this.emptyElement);
183         }
184     },
185
186     _projectChanged: function()
187     {
188         this.listElement.removeChildren();
189         if (this.listElement.parentElement) {
190             this.bodyElement.removeChild(this.listElement);
191             this.bodyElement.appendChild(this.emptyElement);
192         }
193         this._items = {};
194     },
195
196     _compare: function(x, y)
197     {
198         if (x !== y)
199             return x < y ? -1 : 1;
200         return 0;
201     },
202
203     _compareBreakpoints: function(b1, b2)
204     {
205         return this._compare(b1.url, b2.url) || this._compare(b1.lineNumber, b2.lineNumber);
206     },
207
208     _setupBreakpointElement: function(data, element)
209     {
210         var sourceID;
211         var lineNumber = data.lineNumber;
212         if (data.locations.length) {
213             sourceID = data.locations[0].sourceID;
214             lineNumber = data.locations[0].lineNumber;
215         }
216
217         var displayName = data.url ? WebInspector.displayNameForURL(data.url) : WebInspector.UIString("(program)");
218         var labelElement = document.createTextNode(displayName + ":" + (lineNumber + 1));
219         element.appendChild(labelElement);
220
221         var sourceTextElement = document.createElement("div");
222         sourceTextElement.className = "source-text monospace";
223         element.appendChild(sourceTextElement);
224
225         if (sourceID) {
226             function didGetSourceLine(text)
227             {
228                 sourceTextElement.textContent = text;
229             }
230             var script = WebInspector.debuggerModel.scriptForSourceID(sourceID);
231             script.sourceLine(lineNumber, didGetSourceLine.bind(this));
232         }
233
234         element.addStyleClass("cursor-pointer");
235         var clickHandler = WebInspector.panels.scripts.showSourceLine.bind(WebInspector.panels.scripts, data.url, data.lineNumber + 1);
236         element.addEventListener("click", clickHandler, false);
237     },
238
239     _breakpointIdForDebuggerPausedEvent: function(details)
240     {
241         var callFrame = details.callFrames[0];
242         var breakpoint = WebInspector.debuggerModel.findBreakpoint(callFrame.sourceID, callFrame.line);
243         if (breakpoint)
244             return breakpoint.id;
245    },
246
247     _removeBreakpoint: function(breakpointId)
248     {
249         WebInspector.debuggerModel.removeBreakpoint(breakpointId);
250     }
251 }
252
253 WebInspector.JavaScriptBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
254
255 WebInspector.NativeBreakpointsSidebarPane = function(title)
256 {
257     WebInspector.SidebarPane.call(this, title);
258
259     this.listElement = document.createElement("ol");
260     this.listElement.className = "breakpoint-list";
261
262     this.emptyElement = document.createElement("div");
263     this.emptyElement.className = "info";
264     this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");
265
266     this.bodyElement.appendChild(this.emptyElement);
267
268     WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.ProjectChanged, this._projectChanged, this);
269 }
270
271 WebInspector.NativeBreakpointsSidebarPane.prototype = {
272     addBreakpointItem: function(breakpointItem)
273     {
274         var element = breakpointItem.element;
275         element._breakpointItem = breakpointItem;
276
277         breakpointItem.addEventListener("breakpoint-hit", this.expand, this);
278         breakpointItem.addEventListener("removed", this._removeListElement.bind(this, element), this);
279
280         var currentElement = this.listElement.firstChild;
281         while (currentElement) {
282             if (currentElement._breakpointItem && currentElement._breakpointItem.compareTo(element._breakpointItem) > 0)
283                 break;
284             currentElement = currentElement.nextSibling;
285         }
286         this._addListElement(element, currentElement);
287
288         if (breakpointItem.click) {
289             element.addStyleClass("cursor-pointer");
290             element.addEventListener("click", breakpointItem.click.bind(breakpointItem), false);
291         }
292         element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this, breakpointItem), true);
293     },
294
295     _contextMenuEventFired: function(breakpointItem, event)
296     {
297         var contextMenu = new WebInspector.ContextMenu();
298         contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), breakpointItem.remove.bind(breakpointItem));
299         contextMenu.show(event);
300     },
301
302     _addListElement: function(element, beforeElement)
303     {
304         if (beforeElement)
305             this.listElement.insertBefore(element, beforeElement);
306         else {
307             if (!this.listElement.firstChild) {
308                 this.bodyElement.removeChild(this.emptyElement);
309                 this.bodyElement.appendChild(this.listElement);
310             }
311             this.listElement.appendChild(element);
312         }
313     },
314
315     _removeListElement: function(element)
316     {
317         this.listElement.removeChild(element);
318         if (!this.listElement.firstChild) {
319             this.bodyElement.removeChild(this.listElement);
320             this.bodyElement.appendChild(this.emptyElement);
321         }
322     },
323
324     _projectChanged: function()
325     {
326         this.listElement.removeChildren();
327         if (this.listElement.parentElement) {
328             this.bodyElement.removeChild(this.listElement);
329             this.bodyElement.appendChild(this.emptyElement);
330         }
331     }
332 }
333
334 WebInspector.NativeBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;
335
336 WebInspector.XHRBreakpointsSidebarPane = function()
337 {
338     WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("XHR Breakpoints"));
339
340     function addButtonClicked(event)
341     {
342         event.stopPropagation();
343         this._startEditingBreakpoint(null);
344     }
345
346     var addButton = document.createElement("button");
347     addButton.className = "add";
348     addButton.addEventListener("click", addButtonClicked.bind(this), false);
349     this.titleElement.appendChild(addButton);
350 }
351
352 WebInspector.XHRBreakpointsSidebarPane.prototype = {
353     addBreakpointItem: function(breakpointItem)
354     {
355         WebInspector.NativeBreakpointsSidebarPane.prototype.addBreakpointItem.call(this, breakpointItem);
356         breakpointItem._labelElement.addEventListener("dblclick", this._startEditingBreakpoint.bind(this, breakpointItem), false);
357     },
358
359     _startEditingBreakpoint: function(breakpointItem)
360     {
361         if (this._editingBreakpoint)
362             return;
363         this._editingBreakpoint = true;
364
365         if (!this.expanded)
366             this.expanded = true;
367
368         var inputElement = document.createElement("span");
369         inputElement.className = "breakpoint-condition editing";
370         if (breakpointItem) {
371             breakpointItem.populateEditElement(inputElement);
372             this.listElement.insertBefore(inputElement, breakpointItem.element);
373             breakpointItem.element.addStyleClass("hidden");
374         } else
375             this._addListElement(inputElement, this.listElement.firstChild);
376
377         var commitHandler = this._hideEditBreakpointDialog.bind(this, inputElement, true, breakpointItem);
378         var cancelHandler = this._hideEditBreakpointDialog.bind(this, inputElement, false, breakpointItem);
379         WebInspector.startEditing(inputElement, {
380             commitHandler: commitHandler,
381             cancelHandler: cancelHandler
382         });
383     },
384
385     _hideEditBreakpointDialog: function(inputElement, accept, breakpointItem)
386     {
387         this._removeListElement(inputElement);
388         this._editingBreakpoint = false;
389         if (accept) {
390             if (breakpointItem)
391                 breakpointItem.remove();
392             WebInspector.breakpointManager.createXHRBreakpoint(inputElement.textContent.toLowerCase());
393         } else if (breakpointItem)
394             breakpointItem.element.removeStyleClass("hidden");
395     }
396 }
397
398 WebInspector.XHRBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype;
399
400 WebInspector.BreakpointItem = function(breakpoint)
401 {
402     this._breakpoint = breakpoint;
403
404     this._element = document.createElement("li");
405
406     var checkboxElement = document.createElement("input");
407     checkboxElement.className = "checkbox-elem";
408     checkboxElement.type = "checkbox";
409     checkboxElement.checked = this._breakpoint.enabled;
410     checkboxElement.addEventListener("click", this._checkboxClicked.bind(this), false);
411     this._element.appendChild(checkboxElement);
412
413     this._createLabelElement();
414
415     this._breakpoint.addEventListener("enable-changed", this._enableChanged, this);
416     this._breakpoint.addEventListener("hit-state-changed", this._hitStateChanged, this);
417     this._breakpoint.addEventListener("label-changed", this._labelChanged, this);
418     this._breakpoint.addEventListener("removed", this.dispatchEventToListeners.bind(this, "removed"));
419     if (breakpoint.click)
420         this.click = breakpoint.click.bind(breakpoint);
421 }
422
423 WebInspector.BreakpointItem.prototype = {
424     get element()
425     {
426         return this._element;
427     },
428
429     compareTo: function(other)
430     {
431         return this._breakpoint.compareTo(other._breakpoint);
432     },
433
434     populateEditElement: function(element)
435     {
436         this._breakpoint.populateEditElement(element);
437     },
438
439     remove: function()
440     {
441         this._breakpoint.remove();
442     },
443
444     _checkboxClicked: function(event)
445     {
446         this._breakpoint.enabled = !this._breakpoint.enabled;
447
448         // Breakpoint element may have it's own click handler.
449         event.stopPropagation();
450     },
451
452     _enableChanged: function(event)
453     {
454         var checkbox = this._element.firstChild;
455         checkbox.checked = this._breakpoint.enabled;
456     },
457
458     _hitStateChanged: function(event)
459     {
460         if (event.target.hit) {
461             this._element.addStyleClass("breakpoint-hit");
462             this.dispatchEventToListeners("breakpoint-hit");
463         } else
464             this._element.removeStyleClass("breakpoint-hit");
465     },
466
467     _labelChanged: function(event)
468     {
469         this._element.removeChild(this._labelElement);
470         this._createLabelElement();
471     },
472
473     _createLabelElement: function()
474     {
475         this._labelElement = document.createElement("span");
476         this._breakpoint.populateLabelElement(this._labelElement);
477         this._element.appendChild(this._labelElement);
478     }
479 }
480
481 WebInspector.BreakpointItem.prototype.__proto__ = WebInspector.Object.prototype;
482
483 WebInspector.EventListenerBreakpointsSidebarPane = function()
484 {
485     WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints"));
486
487     this.categoriesElement = document.createElement("ol");
488     this.categoriesElement.tabIndex = 0;
489     this.categoriesElement.addStyleClass("properties-tree event-listener-breakpoints");
490     this.categoriesTreeOutline = new TreeOutline(this.categoriesElement);
491     this.bodyElement.appendChild(this.categoriesElement);
492
493     WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.ProjectChanged, this._projectChanged, this);
494     WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.EventListenerBreakpointAdded, this._breakpointAdded, this);
495
496     this._breakpointItems = {};
497     this._createCategory(WebInspector.UIString("Keyboard"), "listener", ["keydown", "keyup", "keypress", "textInput"]);
498     this._createCategory(WebInspector.UIString("Mouse"), "listener", ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel"]);
499     // FIXME: uncomment following once inspector stops being drop targer in major ports.
500     // Otherwise, inspector page reacts on drop event and tries to load the event data.
501     // this._createCategory(WebInspector.UIString("Drag"), "listener", ["drag", "drop", "dragstart", "dragend", "dragenter", "dragleave", "dragover"]);
502     this._createCategory(WebInspector.UIString("Control"), "listener", ["resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"]);
503     this._createCategory(WebInspector.UIString("Clipboard"), "listener", ["copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"]);
504     this._createCategory(WebInspector.UIString("Load"), "listener", ["load", "unload", "abort", "error"]);
505     this._createCategory(WebInspector.UIString("DOM Mutation"), "listener", ["DOMActivate", "DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOMNodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMSubtreeModified", "DOMContentLoaded"]);
506     this._createCategory(WebInspector.UIString("Device"), "listener", ["deviceorientation", "devicemotion"]);
507     this._createCategory(WebInspector.UIString("Timer"), "instrumentation", ["setTimer", "clearTimer", "timerFired"]);
508 }
509
510 WebInspector.EventListenerBreakpointsSidebarPane.prototype = {
511     _createCategory: function(name, type, eventNames)
512     {
513         var categoryItem = {};
514         categoryItem.element = new TreeElement(name);
515         this.categoriesTreeOutline.appendChild(categoryItem.element);
516         categoryItem.element.listItemElement.addStyleClass("event-category");
517         categoryItem.element.selectable = true;
518
519         categoryItem.checkbox = this._createCheckbox(categoryItem.element);
520         categoryItem.checkbox.addEventListener("click", this._categoryCheckboxClicked.bind(this, categoryItem), true);
521
522         categoryItem.children = {};
523         for (var i = 0; i < eventNames.length; ++i) {
524             var eventName = type + ":" + eventNames[i];
525
526             var breakpointItem = {};
527             var title = WebInspector.EventListenerBreakpointView.eventNameForUI(eventName);
528             breakpointItem.element = new TreeElement(title);
529             categoryItem.element.appendChild(breakpointItem.element);
530             var hitMarker = document.createElement("div");
531             hitMarker.className = "breakpoint-hit-marker";
532             breakpointItem.element.listItemElement.appendChild(hitMarker);
533             breakpointItem.element.listItemElement.addStyleClass("source-code");
534             breakpointItem.element.selectable = true;
535
536             breakpointItem.checkbox = this._createCheckbox(breakpointItem.element);
537             breakpointItem.checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, breakpointItem), true);
538             breakpointItem.parent = categoryItem;
539             breakpointItem.eventName = eventName;
540
541             this._breakpointItems[eventName] = breakpointItem;
542             categoryItem.children[eventName] = breakpointItem;
543         }
544     },
545
546     _createCheckbox: function(treeElement)
547     {
548         var checkbox = document.createElement("input");
549         checkbox.className = "checkbox-elem";
550         checkbox.type = "checkbox";
551         treeElement.listItemElement.insertBefore(checkbox, treeElement.listItemElement.firstChild);
552         return checkbox;
553     },
554
555     _categoryCheckboxClicked: function(categoryItem)
556     {
557         var checked = categoryItem.checkbox.checked;
558         for (var eventName in categoryItem.children) {
559             var breakpointItem = categoryItem.children[eventName];
560             if (breakpointItem.checkbox.checked !== checked) {
561                 breakpointItem.checkbox.checked = checked;
562                 this._breakpointCheckboxClicked(breakpointItem);
563             }
564         }
565     },
566
567     _breakpointCheckboxClicked: function(breakpointItem)
568     {
569         if (breakpointItem.checkbox.checked)
570             WebInspector.breakpointManager.createEventListenerBreakpoint(breakpointItem.eventName);
571         else
572             breakpointItem.breakpoint.remove();
573     },
574
575     _breakpointAdded: function(event)
576     {
577         var breakpoint = event.data;
578
579         var breakpointItem = this._breakpointItems[breakpoint.eventName];
580         breakpointItem.breakpoint = breakpoint;
581         breakpoint.addEventListener("hit-state-changed", this._breakpointHitStateChanged.bind(this, breakpointItem));
582         breakpoint.addEventListener("removed", this._breakpointRemoved.bind(this, breakpointItem));
583         breakpointItem.checkbox.checked = true;
584         this._updateCategoryCheckbox(breakpointItem);
585     },
586
587     _breakpointHitStateChanged: function(breakpointItem, event)
588     {
589         if (event.target.hit) {
590             this.expanded = true;
591             var categoryItem = breakpointItem.parent;
592             categoryItem.element.expand();
593             breakpointItem.element.listItemElement.addStyleClass("breakpoint-hit");
594         } else
595             breakpointItem.element.listItemElement.removeStyleClass("breakpoint-hit");
596     },
597
598     _breakpointRemoved: function(breakpointItem)
599     {
600         breakpointItem.breakpoint = null;
601         breakpointItem.checkbox.checked = false;
602         this._updateCategoryCheckbox(breakpointItem);
603     },
604
605     _updateCategoryCheckbox: function(breakpointItem)
606     {
607         var categoryItem = breakpointItem.parent;
608         var hasEnabled = false, hasDisabled = false;
609         for (var eventName in categoryItem.children) {
610             var breakpointItem = categoryItem.children[eventName];
611             if (breakpointItem.checkbox.checked)
612                 hasEnabled = true;
613             else
614                 hasDisabled = true;
615         }
616         categoryItem.checkbox.checked = hasEnabled;
617         categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled;
618     },
619
620     _projectChanged: function()
621     {
622         for (var eventName in this._breakpointItems) {
623             var breakpointItem = this._breakpointItems[eventName];
624             breakpointItem.breakpoint = null;
625             breakpointItem.checkbox.checked = false;
626             this._updateCategoryCheckbox(breakpointItem);
627         }
628     }
629 }
630
631 WebInspector.EventListenerBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;