1<!DOCTYPE html>
2<!--
3Copyright (c) 2013 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<link rel="stylesheet" href="/tracing/ui/tracks/thread_track.css">
9
10<link rel="import" href="/tracing/base/iteration_helpers.html">
11<link rel="import" href="/tracing/core/filter.html">
12<link rel="import" href="/tracing/model/event_set.html">
13<link rel="import" href="/tracing/ui/base/ui.html">
14<link rel="import" href="/tracing/ui/tracks/async_slice_group_track.html">
15<link rel="import" href="/tracing/ui/tracks/container_track.html">
16<link rel="import" href="/tracing/ui/tracks/sample_track.html">
17<link rel="import" href="/tracing/ui/tracks/slice_group_track.html">
18<link rel="import" href="/tracing/ui/tracks/slice_track.html">
19
20<script>
21'use strict';
22
23tr.exportTo('tr.ui.tracks', function() {
24  /**
25   * Visualizes a Thread using a series of SliceTracks.
26   * @constructor
27   */
28  var ThreadTrack = tr.ui.b.define('thread-track',
29                                   tr.ui.tracks.ContainerTrack);
30  ThreadTrack.prototype = {
31    __proto__: tr.ui.tracks.ContainerTrack.prototype,
32
33    decorate: function(viewport) {
34      tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
35      this.classList.add('thread-track');
36    },
37
38    get thread() {
39      return this.thread_;
40    },
41
42    set thread(thread) {
43      this.thread_ = thread;
44      this.updateContents_();
45    },
46
47    get hasVisibleContent() {
48      return this.tracks_.length > 0;
49    },
50
51    get eventContainer() {
52      return this.thread;
53    },
54
55    addContainersToTrackMap: function(containerToTrackMap) {
56      tr.ui.tracks.ContainerTrack.prototype.addContainersToTrackMap.apply(
57        this, arguments);
58      containerToTrackMap.addContainer(this.thread, this);
59    },
60
61    updateContents_: function() {
62      this.detach();
63
64      if (!this.thread_)
65        return;
66
67      this.heading = this.thread_.userFriendlyName + ': ';
68      this.tooltip = this.thread_.userFriendlyDetails;
69
70      if (this.thread_.asyncSliceGroup.length)
71        this.appendAsyncSliceTracks_();
72
73      this.appendThreadSamplesTracks_();
74
75      if (this.thread_.timeSlices) {
76        var timeSlicesTrack = new tr.ui.tracks.SliceTrack(this.viewport);
77        timeSlicesTrack.heading = '';
78        timeSlicesTrack.height = tr.ui.b.THIN_SLICE_HEIGHT + 'px';
79        timeSlicesTrack.slices = this.thread_.timeSlices;
80        if (timeSlicesTrack.hasVisibleContent)
81          this.appendChild(timeSlicesTrack);
82      }
83
84      if (this.thread_.sliceGroup.length) {
85        var track = new tr.ui.tracks.SliceGroupTrack(this.viewport);
86        track.heading = this.thread_.userFriendlyName;
87        track.tooltip = this.thread_.userFriendlyDetails;
88        track.group = this.thread_.sliceGroup;
89        if (track.hasVisibleContent)
90          this.appendChild(track);
91      }
92    },
93
94    appendAsyncSliceTracks_: function() {
95      var subGroups = this.thread_.asyncSliceGroup.viewSubGroups;
96      subGroups.forEach(function(subGroup) {
97        var asyncTrack = new tr.ui.tracks.AsyncSliceGroupTrack(this.viewport);
98        var title = subGroup.slices[0].viewSubGroupTitle;
99        asyncTrack.group = subGroup;
100        asyncTrack.heading = title;
101        if (asyncTrack.hasVisibleContent)
102          this.appendChild(asyncTrack);
103      }, this);
104    },
105
106    appendThreadSamplesTracks_: function() {
107      var threadSamples = this.thread_.samples;
108      if (threadSamples === undefined || threadSamples.length === 0)
109        return;
110      var samplesByTitle = {};
111      threadSamples.forEach(function(sample) {
112        if (samplesByTitle[sample.title] === undefined)
113          samplesByTitle[sample.title] = [];
114        samplesByTitle[sample.title].push(sample);
115      });
116
117      var sampleTitles = tr.b.dictionaryKeys(samplesByTitle);
118      sampleTitles.sort();
119
120      sampleTitles.forEach(function(sampleTitle) {
121        var samples = samplesByTitle[sampleTitle];
122        var samplesTrack = new tr.ui.tracks.SampleTrack(this.viewport);
123        samplesTrack.group = this.thread_;
124        samplesTrack.samples = samples;
125        samplesTrack.heading = this.thread_.userFriendlyName + ': ' +
126            sampleTitle;
127        samplesTrack.tooltip = this.thread_.userFriendlyDetails;
128        samplesTrack.selectionGenerator = function() {
129          var selection = new tr.model.EventSet();
130          for (var i = 0; i < samplesTrack.samples.length; i++) {
131            selection.push(samplesTrack.samples[i]);
132          }
133          return selection;
134        };
135        this.appendChild(samplesTrack);
136      }, this);
137    },
138
139    collapsedDidChange: function(collapsed) {
140      if (collapsed) {
141        var h = parseInt(this.tracks[0].height);
142        for (var i = 0; i < this.tracks.length; ++i) {
143          if (h > 2) {
144            this.tracks[i].height = Math.floor(h) + 'px';
145          } else {
146            this.tracks[i].style.display = 'none';
147          }
148          h = h * 0.5;
149        }
150      } else {
151        for (var i = 0; i < this.tracks.length; ++i) {
152          this.tracks[i].height = this.tracks[0].height;
153          this.tracks[i].style.display = '';
154        }
155      }
156    }
157  };
158
159  return {
160    ThreadTrack: ThreadTrack
161  };
162});
163</script>
164