Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / trace_viewer / tracing / tracks / trace_model_track.html
1 <!DOCTYPE html>
2 <!--
3 Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
6 -->
7
8 <link rel="stylesheet" href="/tracing/tracks/trace_model_track.css">
9
10 <link rel="import" href="/tracing/tracks/container_track.html">
11 <link rel="import" href="/tracing/tracks/kernel_track.html">
12 <link rel="import" href="/tracing/tracks/process_track.html">
13 <link rel="import" href="/tracing/draw_helpers.html">
14 <link rel="import" href="/base/measuring_stick.html">
15 <link rel="import" href="/base/ui.html">
16
17 <script>
18 'use strict';
19
20 tv.exportTo('tracing.tracks', function() {
21   /**
22    * Visualizes a Model by building ProcessTracks and
23    * CpuTracks.
24    * @constructor
25    */
26   var TraceModelTrack = tv.ui.define(
27       'trace-model-track', tracing.tracks.ContainerTrack);
28
29   TraceModelTrack.prototype = {
30
31     __proto__: tracing.tracks.ContainerTrack.prototype,
32
33     decorate: function(viewport) {
34       tracing.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
35       this.classList.add('model-track');
36     },
37
38     detach: function() {
39       tracing.tracks.ContainerTrack.prototype.detach.call(this);
40     },
41
42     get model() {
43       return this.model_;
44     },
45
46     set model(model) {
47       this.model_ = model;
48       this.updateContents_();
49     },
50
51     get hasVisibleContent() {
52       return this.children.length > 0;
53     },
54
55     updateContents_: function() {
56       this.textContent = '';
57       if (!this.model_)
58         return;
59
60       this.appendKernelTrack_();
61
62       // Get a sorted list of processes.
63       var processes = this.model_.getAllProcesses();
64       processes.sort(tracing.trace_model.Process.compare);
65
66       for (var i = 0; i < processes.length; ++i) {
67         var process = processes[i];
68
69         var track = new tracing.tracks.ProcessTrack(this.viewport);
70         track.process = process;
71         if (!track.hasVisibleContent)
72           continue;
73
74         this.appendChild(track);
75       }
76       this.viewport_.rebuildEventToTrackMap();
77     },
78
79     addEventsToTrackMap: function(eventToTrackMap) {
80       if (!this.model_)
81         return;
82
83       var tracks = this.children;
84       for (var i = 0; i < tracks.length; ++i)
85         tracks[i].addEventsToTrackMap(eventToTrackMap);
86
87       if (this.instantEvents === undefined)
88         return;
89
90       var vp = this.viewport_;
91       this.instantEvents.forEach(function(ev) {
92         eventToTrackMap.addEvent(ev, this);
93       }.bind(this));
94     },
95
96     appendKernelTrack_: function() {
97       var kernel = this.model.kernel;
98       var track = new tracing.tracks.KernelTrack(this.viewport);
99       track.kernel = this.model.kernel;
100       if (!track.hasVisibleContent)
101         return;
102       this.appendChild(track);
103     },
104
105     drawTrack: function(type) {
106       var ctx = this.context();
107
108       var pixelRatio = window.devicePixelRatio || 1;
109       var bounds = this.getBoundingClientRect();
110       var canvasBounds = ctx.canvas.getBoundingClientRect();
111
112       ctx.save();
113       ctx.translate(0, pixelRatio * (bounds.top - canvasBounds.top));
114
115       var dt = this.viewport.currentDisplayTransform;
116       var viewLWorld = dt.xViewToWorld(0);
117       var viewRWorld = dt.xViewToWorld(bounds.width * pixelRatio);
118
119       switch (type) {
120         case tracing.tracks.DrawType.GRID:
121           this.viewport.drawMajorMarkLines(ctx);
122           // The model is the only thing that draws grid lines.
123           ctx.restore();
124           return;
125
126         case tracing.tracks.DrawType.FLOW_ARROWS:
127           if (this.model_.flowIntervalTree.size === 0) {
128             ctx.restore();
129             return;
130           }
131
132           this.drawFlowArrows_(viewLWorld, viewRWorld);
133           ctx.restore();
134           return;
135
136         case tracing.tracks.DrawType.INSTANT_EVENT:
137           if (!this.model_.instantEvents ||
138               this.model_.instantEvents.length === 0)
139             break;
140
141           tracing.drawInstantSlicesAsLines(
142               ctx,
143               this.viewport.currentDisplayTransform,
144               viewLWorld,
145               viewRWorld,
146               bounds.height,
147               this.model_.instantEvents,
148               1);
149
150           break;
151
152         case tracing.tracks.DrawType.MARKERS:
153           if (!this.viewport.interestRange.isEmpty) {
154             this.viewport.interestRange.draw(ctx, viewLWorld, viewRWorld);
155             this.viewport.interestRange.drawIndicators(
156                 ctx, viewLWorld, viewRWorld);
157           }
158           ctx.restore();
159           return;
160       }
161       ctx.restore();
162
163       tracing.tracks.ContainerTrack.prototype.drawTrack.call(this, type);
164     },
165
166     drawFlowArrows_: function(viewLWorld, viewRWorld) {
167       var ctx = this.context();
168       var dt = this.viewport.currentDisplayTransform;
169       dt.applyTransformToCanvas(ctx);
170
171       var pixWidth = dt.xViewVectorToWorld(1);
172
173       ctx.strokeStyle = 'rgba(0, 0, 0, 0.4)';
174       ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
175       ctx.lineWidth = pixWidth > 1.0 ? 1 : pixWidth;
176
177       var events =
178           this.model_.flowIntervalTree.findIntersection(viewLWorld, viewRWorld);
179
180       var minWidth = 2 * pixWidth;
181       var canvasBounds = ctx.canvas.getBoundingClientRect();
182
183       for (var i = 0; i < events.length; ++i) {
184         var startEvent = events[i][0];
185         var endEvent = events[i][1];
186
187         // Skip lines that will be, essentially, vertical.
188         var distance = endEvent.start - startEvent.start;
189         if (distance <= minWidth)
190           continue;
191
192         this.drawFlowArrowBetween_(
193             ctx, startEvent, endEvent, canvasBounds, pixWidth);
194       }
195     },
196
197     drawFlowArrowBetween_: function(ctx, startEvent, endEvent,
198                                     canvasBounds, pixWidth) {
199       var pixelRatio = window.devicePixelRatio || 1;
200
201       var startTrack = this.viewport.trackForEvent(startEvent);
202       var endTrack = this.viewport.trackForEvent(endEvent);
203
204       var startBounds = startTrack.getBoundingClientRect();
205       var endBounds = endTrack.getBoundingClientRect();
206
207       if (startEvent.selected || endEvent.selected) {
208         ctx.shadowBlur = 1;
209         ctx.shadowColor = 'red';
210         ctx.shadowOffsety = 2;
211         ctx.strokeStyle = 'red';
212       }
213
214       var startSize = startBounds.left + startBounds.top +
215           startBounds.bottom + startBounds.right;
216       var endSize = endBounds.left + endBounds.top +
217           endBounds.bottom + endBounds.right;
218       // Nothing to do if both ends of the track are collapsed.
219       if (startSize === 0 && endSize === 0)
220         return;
221
222       var startY = this.calculateTrackY_(startTrack, canvasBounds);
223       var endY = this.calculateTrackY_(endTrack, canvasBounds);
224
225       var pixelStartY = pixelRatio * startY;
226       var pixelEndY = pixelRatio * endY;
227       var half = (endEvent.start - startEvent.start) / 2;
228
229       ctx.beginPath();
230       ctx.moveTo(startEvent.start, pixelStartY);
231       ctx.bezierCurveTo(
232           startEvent.start + half, pixelStartY,
233           startEvent.start + half, pixelEndY,
234           endEvent.start, pixelEndY);
235       ctx.stroke();
236
237       if (startEvent.selected || endEvent.selected) {
238         ctx.shadowBlur = 0;
239         ctx.shadowOffsetX = 0;
240         ctx.strokeStyle = 'rgba(0, 0, 0, 0.4)';
241       }
242
243       var arrowWidth = 5 * pixWidth * pixelRatio;
244       var distance = endEvent.start - startEvent.start;
245       if (distance <= (2 * arrowWidth))
246         return;
247
248       var tipX = endEvent.start;
249       var tipY = pixelEndY;
250       var arrowHeight = (endBounds.height / 4) * pixelRatio;
251       tracing.drawTriangle(ctx,
252           tipX, tipY,
253           tipX - arrowWidth, tipY - arrowHeight,
254           tipX - arrowWidth, tipY + arrowHeight);
255       ctx.fill();
256     },
257
258     calculateTrackY_: function(track, canvasBounds) {
259       var bounds = track.getBoundingClientRect();
260       var size = bounds.left + bounds.top + bounds.bottom + bounds.right;
261       if (size === 0)
262         return this.calculateTrackY_(track.parentNode, canvasBounds);
263
264       return bounds.top - canvasBounds.top + (bounds.height / 2);
265     },
266
267     addIntersectingItemsInRangeToSelectionInWorldSpace: function(
268         loWX, hiWX, viewPixWidthWorld, selection) {
269       function onPickHit(instantEvent) {
270         selection.push(instantEvent);
271       }
272       tv.iterateOverIntersectingIntervals(this.model_.instantEvents,
273           function(x) { return x.start; },
274           function(x) { return x.duration; },
275           loWX, hiWX,
276           onPickHit.bind(this));
277
278       tracing.tracks.ContainerTrack.prototype.
279           addIntersectingItemsInRangeToSelectionInWorldSpace.
280           apply(this, arguments);
281     },
282
283     addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
284                                          selection) {
285       this.addClosestInstantEventToSelection(this.model_.instantEvents,
286                                              worldX, worldMaxDist, selection);
287       tracing.tracks.ContainerTrack.prototype.addClosestEventToSelection.
288           apply(this, arguments);
289     }
290   };
291
292   return {
293     TraceModelTrack: TraceModelTrack
294   };
295 });
296 </script>