2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008, 2009 Anthony Ricaud <rik@webkit.org>
4 * Copyright (C) 2009 Google Inc. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 WebInspector.TimelineGrid = function()
36 this.element = document.createElement("div");
38 this._itemsGraphsElement = document.createElement("div");
39 this._itemsGraphsElement.id = "resources-graphs";
40 this.element.appendChild(this._itemsGraphsElement);
42 this._dividersElement = this.element.createChild("div", "resources-dividers");
44 this._gridHeaderElement = document.createElement("div");
45 this._eventDividersElement = this._gridHeaderElement.createChild("div", "resources-event-dividers");
46 this._dividersLabelBarElement = this._gridHeaderElement.createChild("div", "resources-dividers-label-bar");
47 this.element.appendChild(this._gridHeaderElement);
49 this._leftCurtainElement = this.element.createChild("div", "timeline-cpu-curtain-left");
50 this._rightCurtainElement = this.element.createChild("div", "timeline-cpu-curtain-right");
52 this._gridSliceTime = 1;
55 WebInspector.TimelineGrid.prototype = {
56 get itemsGraphsElement()
58 return this._itemsGraphsElement;
63 return this._dividersElement;
66 get dividersLabelBarElement()
68 return this._dividersLabelBarElement;
71 get gridHeaderElement()
73 return this._gridHeaderElement;
77 return this._gridSliceTime;
80 removeDividers: function()
82 this._dividersElement.removeChildren();
83 this._dividersLabelBarElement.removeChildren();
89 updateDividers: function(calculator)
91 const minGridSlicePx = 64; // minimal distance between grid lines.
92 const gridFreeZoneAtLeftPx = 50;
94 var dividersElementClientWidth = this._dividersElement.clientWidth;
95 var dividersCount = dividersElementClientWidth / minGridSlicePx;
96 var gridSliceTime = calculator.boundarySpan() / dividersCount;
97 var pixelsPerTime = dividersElementClientWidth / calculator.boundarySpan();
99 // Align gridSliceTime to a nearest round value.
100 // We allow spans that fit into the formula: span = (1|2|5)x10^n,
101 // e.g.: ... .1 .2 .5 1 2 5 10 20 50 ...
102 // After a span has been chosen make grid lines at multiples of the span.
104 var logGridSliceTime = Math.ceil(Math.log(gridSliceTime) / Math.LN10);
105 gridSliceTime = Math.pow(10, logGridSliceTime);
106 if (gridSliceTime * pixelsPerTime >= 5 * minGridSlicePx)
107 gridSliceTime = gridSliceTime / 5;
108 if (gridSliceTime * pixelsPerTime >= 2 * minGridSlicePx)
109 gridSliceTime = gridSliceTime / 2;
110 this._gridSliceTime = gridSliceTime;
112 var firstDividerTime = Math.ceil((calculator.minimumBoundary() - calculator.zeroTime()) / gridSliceTime) * gridSliceTime + calculator.zeroTime();
113 var lastDividerTime = calculator.maximumBoundary();
114 // Add some extra space past the right boundary as the rightmost divider label text
115 // may be partially shown rather than just pop up when a new rightmost divider gets into the view.
116 if (calculator.paddingLeft > 0)
117 lastDividerTime = lastDividerTime + minGridSlicePx / pixelsPerTime;
118 dividersCount = Math.ceil((lastDividerTime - firstDividerTime) / gridSliceTime);
120 // Reuse divider elements and labels.
121 var divider = this._dividersElement.firstChild;
122 var dividerLabelBar = this._dividersLabelBarElement.firstChild;
124 var skipLeftmostDividers = calculator.paddingLeft === 0;
129 for (var i = 0; i < dividersCount; ++i) {
130 var left = calculator.computePosition(firstDividerTime + gridSliceTime * i);
131 if (skipLeftmostDividers && left < gridFreeZoneAtLeftPx)
135 divider = document.createElement("div");
136 divider.className = "resources-divider";
137 this._dividersElement.appendChild(divider);
139 dividerLabelBar = document.createElement("div");
140 dividerLabelBar.className = "resources-divider";
141 var label = document.createElement("div");
142 label.className = "resources-divider-label";
143 dividerLabelBar._labelElement = label;
144 dividerLabelBar.appendChild(label);
145 this._dividersLabelBarElement.appendChild(dividerLabelBar);
148 dividerLabelBar._labelElement.textContent = calculator.formatTime(firstDividerTime + gridSliceTime * i - calculator.minimumBoundary());
149 var percentLeft = 100 * left / dividersElementClientWidth;
150 divider.style.left = percentLeft + "%";
151 dividerLabelBar.style.left = percentLeft + "%";
153 divider = divider.nextSibling;
154 dividerLabelBar = dividerLabelBar.nextSibling;
159 var nextDivider = divider.nextSibling;
160 this._dividersElement.removeChild(divider);
161 divider = nextDivider;
163 while (dividerLabelBar) {
164 var nextDivider = dividerLabelBar.nextSibling;
165 this._dividersLabelBarElement.removeChild(dividerLabelBar);
166 dividerLabelBar = nextDivider;
171 addEventDivider: function(divider)
173 this._eventDividersElement.appendChild(divider);
176 addEventDividers: function(dividers)
178 this._gridHeaderElement.removeChild(this._eventDividersElement);
179 for (var i = 0; i < dividers.length; ++i) {
181 this._eventDividersElement.appendChild(dividers[i]);
183 this._gridHeaderElement.appendChild(this._eventDividersElement);
186 removeEventDividers: function()
188 this._eventDividersElement.removeChildren();
191 hideEventDividers: function()
193 this._eventDividersElement.classList.add("hidden");
196 showEventDividers: function()
198 this._eventDividersElement.classList.remove("hidden");
201 hideDividers: function()
203 this._dividersElement.classList.add("hidden");
206 showDividers: function()
208 this._dividersElement.classList.remove("hidden");
211 hideCurtains: function()
213 this._leftCurtainElement.classList.add("hidden");
214 this._rightCurtainElement.classList.add("hidden");
218 * @param {number} gapOffset
219 * @param {number} gapWidth
221 showCurtains: function(gapOffset, gapWidth)
223 this._leftCurtainElement.style.width = gapOffset + "px";
224 this._leftCurtainElement.classList.remove("hidden");
225 this._rightCurtainElement.style.left = (gapOffset + gapWidth) + "px";
226 this._rightCurtainElement.classList.remove("hidden");
229 setScrollAndDividerTop: function(scrollTop, dividersTop)
231 this._dividersElement.style.top = scrollTop + "px";
232 this._leftCurtainElement.style.top = scrollTop + "px";
233 this._rightCurtainElement.style.top = scrollTop + "px";
240 WebInspector.TimelineGrid.Calculator = function() { }
242 WebInspector.TimelineGrid.Calculator.prototype = {
244 * @param {number} time
247 computePosition: function(time) { return 0; },
250 * @param {number} time
251 * @param {boolean=} hires
254 formatTime: function(time, hires) { },
256 /** @return {number} */
257 minimumBoundary: function() { },
259 /** @return {number} */
260 zeroTime: function() { },
262 /** @return {number} */
263 maximumBoundary: function() { },
265 /** @return {number} */
266 boundarySpan: function() { }