Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / trace_viewer / tracing / tracks / slice_group_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.require('tvcm.sorted_array_utils');
8 tvcm.require('tracing.tracks.container_track');
9 tvcm.require('tvcm.ui');
10
11 tvcm.exportTo('tracing.tracks', function() {
12
13   /**
14    * A track that displays a SliceGroup.
15    * @constructor
16    * @extends {ContainerTrack}
17    */
18
19   var SliceGroupTrack = tvcm.ui.define(
20       'slice-group-track', tracing.tracks.ContainerTrack);
21
22   SliceGroupTrack.prototype = {
23
24     __proto__: tracing.tracks.ContainerTrack.prototype,
25
26     decorate: function(viewport) {
27       tracing.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
28       this.classList.add('slice-group-track');
29       this.tooltip_ = '';
30       this.heading_ = '';
31     },
32
33     get group() {
34       return this.group_;
35     },
36
37     set group(g) {
38       this.group_ = g;
39       this.updateContents_();
40     },
41
42     get heading() {
43       return this.heading_;
44     },
45
46     set heading(h) {
47       this.heading_ = h;
48       this.updateContents_();
49     },
50
51     get tooltip() {
52       return this.tooltip_;
53     },
54
55     set tooltip(t) {
56       this.tooltip_ = t;
57       this.updateContents_();
58     },
59
60     addSliceTrack_: function(slices) {
61       var track = new tracing.tracks.SliceTrack(this.viewport);
62       track.slices = slices;
63       this.appendChild(track);
64       return track;
65     },
66
67     get subRows() {
68       return tvcm.asArray(this.children).map(function(sliceTrack) {
69         return sliceTrack.slices;
70       });
71     },
72
73     get hasVisibleContent() {
74       return this.children.length > 0;
75     },
76
77     updateContents_: function() {
78       if (!this.group_) {
79         this.updateHeadingAndTooltip_();
80         return;
81       }
82
83       var slices = this.group_.slices;
84       if (this.areArrayContentsSame_(this.filteredSlices_, slices)) {
85         this.updateHeadingAndTooltip_();
86         return;
87       }
88
89       this.filteredSlices_ = slices;
90
91       this.detach();
92       if (!slices.length)
93         return;
94       var subRows = this.buildSubRows_(slices);
95       for (var srI = 0; srI < subRows.length; srI++) {
96         var subRow = subRows[srI];
97         if (!subRow.length)
98           continue;
99         this.addSliceTrack_(subRow);
100       }
101       this.updateHeadingAndTooltip_();
102     },
103
104     updateHeadingAndTooltip_: function() {
105       if (!this.firstChild)
106         return;
107       this.firstChild.heading = this.heading_;
108       this.firstChild.tooltip = this.tooltip_;
109     },
110
111     /**
112      * Breaks up the list of slices into N rows, each of which is a list of
113      * slices that are non overlapping.
114      */
115     buildSubRows_: function(slices) {
116       // This function works by walking through slices by start time.
117       //
118       // The basic idea here is to insert each slice as deep into the subrow
119       // list as it can go such that every subSlice is fully contained by its
120       // parent slice.
121       //
122       // Visually, if we start with this:
123       //  0:  [    a       ]
124       //  1:    [  b  ]
125       //  2:    [c][d]
126       //
127       // To place this slice:
128       //               [e]
129       // We first check row 2's last item, [d]. [e] wont fit into [d] (they dont
130       // even intersect). So we go to row 1. That gives us [b], and [d] wont fit
131       // into that either. So, we go to row 0 and its last slice, [a]. That can
132       // completely contain [e], so that means we should add [e] as a subchild
133       // of [a]. That puts it on row 1, yielding:
134       //  0:  [    a       ]
135       //  1:    [  b  ][e]
136       //  2:    [c][d]
137       //
138       // If we then get this slice:
139       //                      [f]
140       // We do the same deepest-to-shallowest walk of the subrows trying to fit
141       // it. This time, it doesn't fit in any open slice. So, we simply append
142       // it to row 0:
143       //  0:  [    a       ]  [f]
144       //  1:    [  b  ][e]
145       //  2:    [c][d]
146       if (!slices.length)
147         return [];
148
149       var ops = [];
150       for (var i = 0; i < slices.length; i++) {
151         if (slices[i].subSlices)
152           slices[i].subSlices.splice(0,
153                                      slices[i].subSlices.length);
154         ops.push(i);
155       }
156
157       ops.sort(function(ix, iy) {
158         var x = slices[ix];
159         var y = slices[iy];
160         if (x.start != y.start)
161           return x.start - y.start;
162
163         // Elements get inserted into the slices array in order of when the
164         // slices start. Because slices must be properly nested, we break
165         // start-time ties by assuming that the elements appearing earlier in
166         // the slices array (and thus ending earlier) start earlier.
167         return ix - iy;
168       });
169
170       var subRows = [[]];
171       this.badSlices_ = [];  // TODO(simonjam): Connect this again.
172
173       for (var i = 0; i < ops.length; i++) {
174         var op = ops[i];
175         var slice = slices[op];
176
177         // Try to fit the slice into the existing subrows.
178         var inserted = false;
179         for (var j = subRows.length - 1; j >= 0; j--) {
180           if (subRows[j].length == 0)
181             continue;
182
183           var insertedSlice = subRows[j][subRows[j].length - 1];
184           if (slice.start < insertedSlice.start) {
185             this.badSlices_.push(slice);
186             inserted = true;
187           }
188           if (insertedSlice.bounds(slice)) {
189             // Insert it into subRow j + 1.
190             while (subRows.length <= j + 1)
191               subRows.push([]);
192             subRows[j + 1].push(slice);
193             if (insertedSlice.subSlices)
194               insertedSlice.subSlices.push(slice);
195             inserted = true;
196             break;
197           }
198         }
199         if (inserted)
200           continue;
201
202         // Append it to subRow[0] as a root.
203         subRows[0].push(slice);
204       }
205
206       return subRows;
207     },
208
209     areArrayContentsSame_: function(a, b) {
210       if (!a || !b)
211         return false;
212       if (!a.length || !b.length)
213         return false;
214       if (a.length != b.length)
215         return false;
216       for (var i = 0; i < a.length; ++i) {
217         if (a[i] != b[i])
218           return false;
219       }
220       return true;
221     }
222   };
223
224   return {
225     SliceGroupTrack: SliceGroupTrack
226   };
227 });