2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
26 WebInspector.BreakpointTreeElement = class BreakpointTreeElement extends WebInspector.GeneralTreeElement
28 constructor(breakpoint, className, title)
30 console.assert(breakpoint instanceof WebInspector.Breakpoint);
33 className = WebInspector.BreakpointTreeElement.GenericLineIconStyleClassName;
35 super(["breakpoint", className], title, null, breakpoint, false);
37 this._breakpoint = breakpoint;
39 this._listeners = new WebInspector.EventListenerSet(this, "BreakpointTreeElement listeners");
41 this._listeners.register(breakpoint, WebInspector.Breakpoint.Event.LocationDidChange, this._breakpointLocationDidChange);
42 this._listeners.register(breakpoint, WebInspector.Breakpoint.Event.DisabledStateDidChange, this._updateStatus);
43 this._listeners.register(breakpoint, WebInspector.Breakpoint.Event.AutoContinueDidChange, this._updateStatus);
44 this._listeners.register(breakpoint, WebInspector.Breakpoint.Event.ResolvedStateDidChange, this._updateStatus);
45 this._listeners.register(WebInspector.debuggerManager, WebInspector.DebuggerManager.Event.BreakpointsEnabledDidChange, this._updateStatus);
47 this._listeners.register(WebInspector.probeManager, WebInspector.ProbeManager.Event.ProbeSetAdded, this._probeSetAdded);
48 this._listeners.register(WebInspector.probeManager, WebInspector.ProbeManager.Event.ProbeSetRemoved, this._probeSetRemoved);
50 this._statusImageElement = document.createElement("img");
51 this._statusImageElement.className = WebInspector.BreakpointTreeElement.StatusImageElementStyleClassName;
52 this._listeners.register(this._statusImageElement, "mousedown", this._statusImageElementMouseDown);
53 this._listeners.register(this._statusImageElement, "click", this._statusImageElementClicked);
59 this.status = this._statusImageElement;
62 this._iconAnimationLayerElement = document.createElement("span");
63 this.iconElement.appendChild(this._iconAnimationLayerElement);
70 return this._breakpoint;
75 return {text: this.breakpoint.url};
80 if (!WebInspector.debuggerManager.isBreakpointRemovable(this._breakpoint))
83 WebInspector.debuggerManager.removeBreakpoint(this._breakpoint);
89 this._breakpoint.cycleToNextMode();
95 this._breakpoint.cycleToNextMode();
101 var contextMenu = new WebInspector.ContextMenu(event);
102 this._breakpoint.appendContextMenuItems(contextMenu, this._statusImageElement);
108 WebInspector.GeneralTreeElement.prototype.onattach.call(this);
110 this._listeners.install();
112 for (var probeSet of WebInspector.probeManager.probeSets)
113 if (probeSet.breakpoint === this._breakpoint)
114 this._addProbeSet(probeSet);
119 WebInspector.GeneralTreeElement.prototype.ondetach.call(this);
121 this._listeners.uninstall();
124 this._removeProbeSet(this._probeSet);
129 this._statusImageElement.remove();
130 this._statusImageElement = null;
137 var sourceCodeLocation = this._breakpoint.sourceCodeLocation;
139 var displayLineNumber = sourceCodeLocation.displayLineNumber;
140 var displayColumnNumber = sourceCodeLocation.displayColumnNumber;
141 if (displayColumnNumber > 0)
142 this.mainTitle = WebInspector.UIString("Line %d:%d").format(displayLineNumber + 1, displayColumnNumber + 1); // The user visible line and column numbers are 1-based.
144 this.mainTitle = WebInspector.UIString("Line %d").format(displayLineNumber + 1); // The user visible line number is 1-based.
146 if (sourceCodeLocation.hasMappedLocation()) {
147 this.subtitle = sourceCodeLocation.formattedLocationString();
149 if (sourceCodeLocation.hasFormattedLocation())
150 this.subtitleElement.classList.add(WebInspector.BreakpointTreeElement.FormattedLocationStyleClassName);
152 this.subtitleElement.classList.remove(WebInspector.BreakpointTreeElement.FormattedLocationStyleClassName);
154 this.tooltip = this.mainTitle + " \u2014 " + WebInspector.UIString("originally %s").format(sourceCodeLocation.originalLocationString());
160 if (!this._statusImageElement)
163 if (this._breakpoint.disabled)
164 this._statusImageElement.classList.add(WebInspector.BreakpointTreeElement.StatusImageDisabledStyleClassName);
166 this._statusImageElement.classList.remove(WebInspector.BreakpointTreeElement.StatusImageDisabledStyleClassName);
168 if (this._breakpoint.autoContinue)
169 this._statusImageElement.classList.add(WebInspector.BreakpointTreeElement.StatusImageAutoContinueStyleClassName);
171 this._statusImageElement.classList.remove(WebInspector.BreakpointTreeElement.StatusImageAutoContinueStyleClassName);
173 if (this._breakpoint.resolved && WebInspector.debuggerManager.breakpointsEnabled)
174 this._statusImageElement.classList.add(WebInspector.BreakpointTreeElement.StatusImageResolvedStyleClassName);
176 this._statusImageElement.classList.remove(WebInspector.BreakpointTreeElement.StatusImageResolvedStyleClassName);
179 _addProbeSet(probeSet)
181 console.assert(probeSet instanceof WebInspector.ProbeSet);
182 console.assert(probeSet.breakpoint === this._breakpoint);
183 console.assert(probeSet !== this._probeSet);
185 this._probeSet = probeSet;
186 probeSet.addEventListener(WebInspector.ProbeSet.Event.SamplesCleared, this._samplesCleared, this);
187 probeSet.dataTable.addEventListener(WebInspector.ProbeSetDataTable.Event.FrameInserted, this._dataUpdated, this);
190 _removeProbeSet(probeSet)
192 console.assert(probeSet instanceof WebInspector.ProbeSet);
193 console.assert(probeSet === this._probeSet);
195 probeSet.removeEventListener(WebInspector.ProbeSet.Event.SamplesCleared, this._samplesCleared, this);
196 probeSet.dataTable.removeEventListener(WebInspector.ProbeSetDataTable.Event.FrameInserted, this._dataUpdated, this);
197 delete this._probeSet;
200 _probeSetAdded(event)
202 var probeSet = event.data.probeSet;
203 if (probeSet.breakpoint === this._breakpoint)
204 this._addProbeSet(probeSet);
207 _probeSetRemoved(event)
209 var probeSet = event.data.probeSet;
210 if (probeSet.breakpoint === this._breakpoint)
211 this._removeProbeSet(probeSet);
214 _samplesCleared(event)
216 console.assert(this._probeSet);
218 var oldTable = event.data.oldTable;
219 oldTable.removeEventListener(WebInspector.ProbeSetDataTable.Event.FrameInserted, this._dataUpdated, this);
220 this._probeSet.dataTable.addEventListener(WebInspector.ProbeSetDataTable.Event.FrameInserted, this._dataUpdated, this);
225 if (this.element.classList.contains(WebInspector.BreakpointTreeElement.ProbeDataUpdatedStyleClassName)) {
226 clearTimeout(this._removeIconAnimationTimeoutIdentifier);
227 this.element.classList.remove(WebInspector.BreakpointTreeElement.ProbeDataUpdatedStyleClassName);
228 // We want to restart the animation, which can only be done by removing the class,
229 // performing layout, and re-adding the class. Try adding class back on next run loop.
230 window.requestAnimationFrame(this._dataUpdated.bind(this));
234 this.element.classList.add(WebInspector.BreakpointTreeElement.ProbeDataUpdatedStyleClassName);
235 this._removeIconAnimationTimeoutIdentifier = setTimeout(function() {
236 this.element.classList.remove(WebInspector.BreakpointTreeElement.ProbeDataUpdatedStyleClassName);
237 }.bind(this), WebInspector.BreakpointTreeElement.ProbeDataUpdatedAnimationDuration);
241 _breakpointLocationDidChange(event)
243 console.assert(event.target === this._breakpoint);
245 // The Breakpoint has a new display SourceCode. The sidebar will remove us, and ondetach() will clear listeners.
246 if (event.data.oldDisplaySourceCode === this._breakpoint.displaySourceCode)
249 this._updateTitles();
252 _statusImageElementMouseDown(event)
254 // To prevent the tree element from selecting.
255 event.stopPropagation();
258 _statusImageElementClicked(event)
260 this._breakpoint.cycleToNextMode();
264 WebInspector.BreakpointTreeElement.GenericLineIconStyleClassName = "breakpoint-generic-line-icon";
265 WebInspector.BreakpointTreeElement.StatusImageElementStyleClassName = "status-image";
266 WebInspector.BreakpointTreeElement.StatusImageResolvedStyleClassName = "resolved";
267 WebInspector.BreakpointTreeElement.StatusImageAutoContinueStyleClassName = "auto-continue";
268 WebInspector.BreakpointTreeElement.StatusImageDisabledStyleClassName = "disabled";
269 WebInspector.BreakpointTreeElement.FormattedLocationStyleClassName = "formatted-location";
270 WebInspector.BreakpointTreeElement.ProbeDataUpdatedStyleClassName = "data-updated";
272 WebInspector.BreakpointTreeElement.ProbeDataUpdatedAnimationDuration = 400; // milliseconds