Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / TimelineGrid.js
1 /*
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.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
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.
18  *
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.
29  */
30
31 /**
32  * @constructor
33  */
34 WebInspector.TimelineGrid = function()
35 {
36     this.element = document.createElement("div");
37
38     this._itemsGraphsElement = document.createElement("div");
39     this._itemsGraphsElement.id = "resources-graphs";
40     this.element.appendChild(this._itemsGraphsElement);
41
42     this._dividersElement = this.element.createChild("div", "resources-dividers");
43
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);
48
49     this._leftCurtainElement = this.element.createChild("div", "timeline-cpu-curtain-left");
50     this._rightCurtainElement = this.element.createChild("div", "timeline-cpu-curtain-right");
51
52     this._gridSliceTime = 1;
53 }
54
55 WebInspector.TimelineGrid.prototype = {
56     get itemsGraphsElement()
57     {
58         return this._itemsGraphsElement;
59     },
60
61     get dividersElement()
62     {
63         return this._dividersElement;
64     },
65
66     get dividersLabelBarElement()
67     {
68         return this._dividersLabelBarElement;
69     },
70
71     get gridHeaderElement()
72     {
73         return this._gridHeaderElement;
74     },
75
76     get gridSliceTime() {
77         return this._gridSliceTime;
78     },
79
80     removeDividers: function()
81     {
82         this._dividersElement.removeChildren();
83         this._dividersLabelBarElement.removeChildren();
84     },
85
86     /**
87      * @return {boolean}
88      */
89     updateDividers: function(calculator)
90     {
91         const minGridSlicePx = 64; // minimal distance between grid lines.
92         const gridFreeZoneAtLeftPx = 50;
93
94         var dividersElementClientWidth = this._dividersElement.clientWidth;
95         var dividersCount = dividersElementClientWidth / minGridSlicePx;
96         var gridSliceTime = calculator.boundarySpan() / dividersCount;
97         var pixelsPerTime = dividersElementClientWidth / calculator.boundarySpan();
98
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.
103
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;
111
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);
119
120         // Reuse divider elements and labels.
121         var divider = this._dividersElement.firstChild;
122         var dividerLabelBar = this._dividersLabelBarElement.firstChild;
123
124         var skipLeftmostDividers = calculator.paddingLeft === 0;
125
126         if (!gridSliceTime)
127             dividersCount = 0;
128
129         for (var i = 0; i < dividersCount; ++i) {
130             var left = calculator.computePosition(firstDividerTime + gridSliceTime * i);
131             if (skipLeftmostDividers && left < gridFreeZoneAtLeftPx)
132                 continue;
133
134             if (!divider) {
135                 divider = document.createElement("div");
136                 divider.className = "resources-divider";
137                 this._dividersElement.appendChild(divider);
138
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);
146             }
147
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 + "%";
152
153             divider = divider.nextSibling;
154             dividerLabelBar = dividerLabelBar.nextSibling;
155         }
156
157         // Remove extras.
158         while (divider) {
159             var nextDivider = divider.nextSibling;
160             this._dividersElement.removeChild(divider);
161             divider = nextDivider;
162         }
163         while (dividerLabelBar) {
164             var nextDivider = dividerLabelBar.nextSibling;
165             this._dividersLabelBarElement.removeChild(dividerLabelBar);
166             dividerLabelBar = nextDivider;
167         }
168         return true;
169     },
170
171     addEventDivider: function(divider)
172     {
173         this._eventDividersElement.appendChild(divider);
174     },
175
176     addEventDividers: function(dividers)
177     {
178         this._gridHeaderElement.removeChild(this._eventDividersElement);
179         for (var i = 0; i < dividers.length; ++i) {
180             if (dividers[i])
181                 this._eventDividersElement.appendChild(dividers[i]);
182         }
183         this._gridHeaderElement.appendChild(this._eventDividersElement);
184     },
185
186     removeEventDividers: function()
187     {
188         this._eventDividersElement.removeChildren();
189     },
190
191     hideEventDividers: function()
192     {
193         this._eventDividersElement.classList.add("hidden");
194     },
195
196     showEventDividers: function()
197     {
198         this._eventDividersElement.classList.remove("hidden");
199     },
200
201     hideDividers: function()
202     {
203         this._dividersElement.classList.add("hidden");
204     },
205
206     showDividers: function()
207     {
208         this._dividersElement.classList.remove("hidden");
209     },
210
211     hideCurtains: function()
212     {
213         this._leftCurtainElement.classList.add("hidden");
214         this._rightCurtainElement.classList.add("hidden");
215     },
216
217     /**
218      * @param {number} gapOffset
219      * @param {number} gapWidth
220      */
221     showCurtains: function(gapOffset, gapWidth)
222     {
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");
227     },
228
229     setScrollAndDividerTop: function(scrollTop, dividersTop)
230     {
231         this._dividersElement.style.top = scrollTop + "px";
232         this._leftCurtainElement.style.top = scrollTop + "px";
233         this._rightCurtainElement.style.top = scrollTop + "px";
234     }
235 }
236
237 /**
238  * @interface
239  */
240 WebInspector.TimelineGrid.Calculator = function() { }
241
242 WebInspector.TimelineGrid.Calculator.prototype = {
243     /**
244      * @param {number} time
245      * @return {number}
246      */
247     computePosition: function(time) { return 0; },
248
249     /**
250      * @param {number} time
251      * @param {boolean=} hires
252      * @return {string}
253      */
254     formatTime: function(time, hires) { },
255
256     /** @return {number} */
257     minimumBoundary: function() { },
258
259     /** @return {number} */
260     zeroTime: function() { },
261
262     /** @return {number} */
263     maximumBoundary: function() { },
264
265     /** @return {number} */
266     boundarySpan: function() { }
267 }