Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / src / tracing / tracks / object_instance_track.js
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 'use strict';
6
7 tvcm.requireStylesheet('tracing.tracks.object_instance_track');
8
9 tvcm.require('tvcm.sorted_array_utils');
10 tvcm.require('tracing.trace_model.event');
11 tvcm.require('tracing.tracks.heading_track');
12 tvcm.require('tracing.color_scheme');
13 tvcm.require('tvcm.ui');
14
15 tvcm.exportTo('tracing.tracks', function() {
16
17   var SelectionState = tracing.trace_model.SelectionState;
18   var EventPresenter = tracing.EventPresenter;
19
20   /**
21    * A track that displays an array of Slice objects.
22    * @constructor
23    * @extends {HeadingTrack}
24    */
25
26   var ObjectInstanceTrack = tvcm.ui.define(
27       'object-instance-track', tracing.tracks.HeadingTrack);
28
29   ObjectInstanceTrack.prototype = {
30     __proto__: tracing.tracks.HeadingTrack.prototype,
31
32     decorate: function(viewport) {
33       tracing.tracks.HeadingTrack.prototype.decorate.call(this, viewport);
34       this.classList.add('object-instance-track');
35       this.objectInstances_ = [];
36       this.objectSnapshots_ = [];
37     },
38
39     get objectInstances() {
40       return this.objectInstances_;
41     },
42
43     set objectInstances(objectInstances) {
44       if (!objectInstances || objectInstances.length == 0) {
45         this.heading = '';
46         this.objectInstances_ = [];
47         this.objectSnapshots_ = [];
48         return;
49       }
50       this.heading = objectInstances[0].typeName;
51       this.objectInstances_ = objectInstances;
52       this.objectSnapshots_ = [];
53       this.objectInstances_.forEach(function(instance) {
54         this.objectSnapshots_.push.apply(
55             this.objectSnapshots_, instance.snapshots);
56       }, this);
57     },
58
59     get height() {
60       return window.getComputedStyle(this).height;
61     },
62
63     set height(height) {
64       this.style.height = height;
65     },
66
67     get snapshotRadiusView() {
68       return 7 * (window.devicePixelRatio || 1);
69     },
70
71     draw: function(type, viewLWorld, viewRWorld) {
72       switch (type) {
73         case tracing.tracks.DrawType.SLICE:
74           this.drawSlices_(viewLWorld, viewRWorld);
75           break;
76       }
77     },
78
79     drawSlices_: function(viewLWorld, viewRWorld) {
80       var ctx = this.context();
81       var pixelRatio = window.devicePixelRatio || 1;
82
83       var bounds = this.getBoundingClientRect();
84       var height = bounds.height * pixelRatio;
85       var halfHeight = height * 0.5;
86       var twoPi = Math.PI * 2;
87
88       // Culling parameters.
89       var dt = this.viewport.currentDisplayTransform;
90       var snapshotRadiusView = this.snapshotRadiusView;
91       var snapshotRadiusWorld = dt.xViewVectorToWorld(height);
92       var loI;
93
94       // Begin rendering in world space.
95       ctx.save();
96       dt.applyTransformToCanvas(ctx);
97
98       // Instances
99       var objectInstances = this.objectInstances_;
100       var loI = tvcm.findLowIndexInSortedArray(
101           objectInstances,
102           function(instance) {
103             return instance.deletionTs;
104           },
105           viewLWorld);
106       ctx.strokeStyle = 'rgb(0,0,0)';
107       for (var i = loI; i < objectInstances.length; ++i) {
108         var instance = objectInstances[i];
109         var x = instance.creationTs;
110         if (x > viewRWorld)
111           break;
112
113         var right = instance.deletionTs == Number.MAX_VALUE ?
114             viewRWorld : instance.deletionTs;
115         ctx.fillStyle = EventPresenter.getObjectInstanceColor(instance);
116         ctx.fillRect(x, pixelRatio, right - x, height - 2 * pixelRatio);
117       }
118       ctx.restore();
119
120       // Snapshots. Has to run in worldspace because ctx.arc gets transformed.
121       var objectSnapshots = this.objectSnapshots_;
122       loI = tvcm.findLowIndexInSortedArray(
123           objectSnapshots,
124           function(snapshot) {
125             return snapshot.ts + snapshotRadiusWorld;
126           },
127           viewLWorld);
128       for (var i = loI; i < objectSnapshots.length; ++i) {
129         var snapshot = objectSnapshots[i];
130         var x = snapshot.ts;
131         if (x - snapshotRadiusWorld > viewRWorld)
132           break;
133         var xView = dt.xWorldToView(x);
134
135         ctx.fillStyle = EventPresenter.getObjectSnapshotColor(snapshot);
136         ctx.beginPath();
137         ctx.arc(xView, halfHeight, snapshotRadiusView, 0, twoPi);
138         ctx.fill();
139         if (snapshot.selected) {
140           ctx.lineWidth = 5;
141           ctx.strokeStyle = 'rgb(100,100,0)';
142           ctx.stroke();
143
144           ctx.beginPath();
145           ctx.arc(xView, halfHeight, snapshotRadiusView - 1, 0, twoPi);
146           ctx.lineWidth = 2;
147           ctx.strokeStyle = 'rgb(255,255,0)';
148           ctx.stroke();
149         } else {
150           ctx.lineWidth = 1;
151           ctx.strokeStyle = 'rgb(0,0,0)';
152           ctx.stroke();
153         }
154       }
155       ctx.lineWidth = 1;
156
157       // For performance reasons we only check the SelectionState of the first
158       // instance. If it's DIMMED we assume that all are DIMMED.
159       // TODO(egraether): Allow partial highlight.
160       var selectionState = SelectionState.NONE;
161       if (objectInstances.length &&
162           objectInstances[0].selectionState === SelectionState.DIMMED) {
163         selectionState = SelectionState.DIMMED;
164       }
165
166       // Dim the track when there is an active highlight.
167       if (selectionState === SelectionState.DIMMED) {
168         var width = bounds.width * pixelRatio;
169         ctx.fillStyle = 'rgba(255,255,255,0.5)';
170         ctx.fillRect(0, 0, width, height);
171         ctx.restore();
172       }
173     },
174
175     addEventsToTrackMap: function(eventToTrackMap) {
176       if (this.objectInstance_ !== undefined) {
177         this.objectInstance_.forEach(function(obj) {
178           eventToTrackMap.addEvent(obj, this);
179         }, this);
180       }
181
182       if (this.objectSnapshots_ !== undefined) {
183         this.objectSnapshots_.forEach(function(obj) {
184           eventToTrackMap.addEvent(obj, this);
185         }, this);
186       }
187     },
188
189     addIntersectingItemsInRangeToSelectionInWorldSpace: function(
190         loWX, hiWX, viewPixWidthWorld, selection) {
191       // Pick snapshots first.
192       var foundSnapshot = false;
193       function onSnapshot(snapshot) {
194         selection.push(snapshot);
195         foundSnapshot = true;
196       }
197       var snapshotRadiusView = this.snapshotRadiusView;
198       var snapshotRadiusWorld = viewPixWidthWorld * snapshotRadiusView;
199       tvcm.iterateOverIntersectingIntervals(
200           this.objectSnapshots_,
201           function(x) { return x.ts - snapshotRadiusWorld; },
202           function(x) { return 2 * snapshotRadiusWorld; },
203           loWX, hiWX,
204           onSnapshot);
205       if (foundSnapshot)
206         return;
207
208       // Try picking instances.
209       tvcm.iterateOverIntersectingIntervals(
210           this.objectInstances_,
211           function(x) { return x.creationTs; },
212           function(x) { return x.deletionTs - x.creationTs; },
213           loWX, hiWX,
214           selection.push.bind(selection));
215     },
216
217     /**
218      * Add the item to the left or right of the provided event, if any, to the
219      * selection.
220      * @param {event} The current event item.
221      * @param {Number} offset Number of slices away from the event to look.
222      * @param {Selection} selection The selection to add an event to,
223      * if found.
224      * @return {boolean} Whether an event was found.
225      * @private
226      */
227     addItemNearToProvidedEventToSelection: function(event, offset, selection) {
228       var events;
229       if (event instanceof tracing.trace_model.ObjectSnapshot)
230         events = this.objectSnapshots_;
231       else if (event instanceof tracing.trace_model.ObjectInstance)
232         events = this.objectInstances_;
233       else
234         throw new Error('Unrecognized event');
235
236       var index = events.indexOf(event);
237       var newIndex = index + offset;
238       if (newIndex >= 0 && newIndex < events.length) {
239         selection.push(events[newIndex]);
240         return true;
241       }
242       return false;
243     },
244
245     addAllObjectsMatchingFilterToSelection: function(filter, selection) {
246     },
247
248     addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
249                                          selection) {
250       var snapshot = tvcm.findClosestElementInSortedArray(
251           this.objectSnapshots_,
252           function(x) { return x.ts; },
253           worldX,
254           worldMaxDist);
255
256       if (!snapshot)
257         return;
258
259       selection.push(snapshot);
260
261       // TODO(egraether): Search for object instances as well, which was not
262       // implemented because it makes little sense with the current visual and
263       // needs to take care of overlapping intervals.
264     }
265   };
266
267   ObjectInstanceTrack.typeNameToTrackConstructorMap = {};
268   ObjectInstanceTrack.register = function(typeName, constructor) {
269     if (ObjectInstanceTrack.typeNameToTrackConstructorMap[typeName])
270       throw new Error('Handler already registered for ' + typeName);
271     ObjectInstanceTrack.typeNameToTrackConstructorMap[typeName] =
272         constructor;
273   };
274
275   ObjectInstanceTrack.getTrackConstructor = function(typeName) {
276     return ObjectInstanceTrack.typeNameToTrackConstructorMap[typeName];
277   };
278
279   return {
280     ObjectInstanceTrack: ObjectInstanceTrack
281   };
282 });