12da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// Use of this source code is governed by a BSD-style license that can be
32da489cd246702bee5938545b18a6f710ed214bcJamie Gennis// found in the LICENSE file.
42da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
52da489cd246702bee5938545b18a6f710ed214bcJamie Gennis'use strict';
62da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.require('base.sorted_array_utils');
866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennisbase.require('tracing.tracks.container_track');
92da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('ui');
102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1188448d9ae4dfff1805045790ef5f32495d62abccJeff Brownbase.exportTo('tracing.tracks', function() {
122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  /**
1488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown   * A track that displays a SliceGroup.
152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   * @constructor
1688448d9ae4dfff1805045790ef5f32495d62abccJeff Brown   * @extends {ContainerTrack}
172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis   */
182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis  var SliceGroupTrack = ui.define(
2066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      'slice-group-track', tracing.tracks.ContainerTrack);
212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown  SliceGroupTrack.prototype = {
232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    __proto__: tracing.tracks.ContainerTrack.prototype,
252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    decorate: function(viewport) {
2766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      tracing.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
2888448d9ae4dfff1805045790ef5f32495d62abccJeff Brown      this.classList.add('slice-group-track');
2966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.tooltip_ = '';
3066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.heading_ = '';
312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    get group() {
342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return this.group_;
352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    set group(g) {
382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.group_ = g;
3966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.updateContents_();
4066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
4166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
4266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    get heading() {
4366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return this.heading_;
442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    set heading(h) {
4766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.heading_ = h;
4866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.updateContents_();
4966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
5066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
5166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    get tooltip() {
5266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return this.tooltip_;
532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    set tooltip(t) {
5666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.tooltip_ = t;
5766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.updateContents_();
582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    set decorateHit(f) {
612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.decorateHit_ = f;
6266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.updateContents_();
632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    addSliceTrack_: function(slices) {
6666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var track = new tracing.tracks.SliceTrack(this.viewport);
672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      track.slices = slices;
682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      track.decorateHit = this.decorateHit_;
6966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      track.categoryFilter_ = this.categoryFilter;
7066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.appendChild(track);
712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return track;
722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
7466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    get subRows() {
7566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return base.asArray(this.children).map(function(sliceTrack) {
7666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        return sliceTrack.slices;
7766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      });
7866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
7966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
8066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    get hasVisibleContent() {
8166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      return this.children.length > 0;
8266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
8366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
8466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    updateContents_: function() {
852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (!this.group_) {
8666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        this.updateHeadingAndTooltip_();
872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return;
882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var slices = tracing.filterSliceArray(this.categoryFilter,
912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                            this.group_.slices);
9266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      if (this.areArrayContentsSame_(this.filteredSlices_, slices)) {
9366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        this.updateHeadingAndTooltip_();
942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return;
952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.filteredSlices_ = slices;
9866a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.detach();
10066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      if (!slices.length)
10166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        return;
10266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      var subRows = this.buildSubRows_(slices);
10366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      for (var srI = 0; srI < subRows.length; srI++) {
10466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        var subRow = subRows[srI];
10566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        if (!subRow.length)
10666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis          continue;
10766a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        this.addSliceTrack_(subRow);
1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
10966a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.updateHeadingAndTooltip_();
11066a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    },
11166a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis
11266a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis    updateHeadingAndTooltip_: function() {
11366a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      if (!this.firstChild)
11466a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis        return;
11566a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.firstChild.heading = this.heading_;
11666a37686207944273ced825e0e8b6b6375f8c3deJamie Gennis      this.firstChild.tooltip = this.tooltip_;
1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    /**
1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * Breaks up the list of slices into N rows, each of which is a list of
1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     * slices that are non overlapping.
1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis     */
1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    buildSubRows_: function(slices) {
1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // This function works by walking through slices by start time.
1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //
1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // The basic idea here is to insert each slice as deep into the subrow
1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // list as it can go such that every subSlice is fully contained by its
1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // parent slice.
1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //
1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // Visually, if we start with this:
1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //  0:  [    a       ]
1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //  1:    [  b  ]
1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //  2:    [c][d]
1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //
1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // To place this slice:
1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //               [e]
1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // We first check row 2's last item, [d]. [e] wont fit into [d] (they dont
1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // even intersect). So we go to row 1. That gives us [b], and [d] wont fit
1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // into that either. So, we go to row 0 and its last slice, [a]. That can
1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // completely contain [e], so that means we should add [e] as a subchild
1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // of [a]. That puts it on row 1, yielding:
1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //  0:  [    a       ]
1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //  1:    [  b  ][e]
1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //  2:    [c][d]
1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //
1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // If we then get this slice:
1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //                      [f]
1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // We do the same deepest-to-shallowest walk of the subrows trying to fit
1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // it. This time, it doesn't fit in any open slice. So, we simply append
1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      // it to row 0:
1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //  0:  [    a       ]  [f]
1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //  1:    [  b  ][e]
1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      //  2:    [c][d]
1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (!slices.length)
1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return [];
1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var ops = [];
1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < slices.length; i++) {
1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (slices[i].subSlices)
1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          slices[i].subSlices.splice(0,
1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis                                     slices[i].subSlices.length);
1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        ops.push(i);
1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      ops.sort(function(ix, iy) {
1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var x = slices[ix];
1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var y = slices[iy];
1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (x.start != y.start)
1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          return x.start - y.start;
1706e58f015d94bedc1072f08b30f0a5a6ac6e653efJamie Gennis
1716e58f015d94bedc1072f08b30f0a5a6ac6e653efJamie Gennis        // Elements get inserted into the slices array in order of when the
1726e58f015d94bedc1072f08b30f0a5a6ac6e653efJamie Gennis        // slices end.  Because slices must be properly nested, we break
1736e58f015d94bedc1072f08b30f0a5a6ac6e653efJamie Gennis        // start-time ties by assuming that the elements appearing earlier in
1746e58f015d94bedc1072f08b30f0a5a6ac6e653efJamie Gennis        // the slices array (and thus ending earlier) start later.
1756e58f015d94bedc1072f08b30f0a5a6ac6e653efJamie Gennis        return iy - ix;
1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      });
1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      var subRows = [[]];
1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      this.badSlices_ = [];  // TODO(simonjam): Connect this again.
1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < ops.length; i++) {
1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var op = ops[i];
1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var slice = slices[op];
1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        // Try to fit the slice into the existing subrows.
1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        var inserted = false;
1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        for (var j = subRows.length - 1; j >= 0; j--) {
1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          if (subRows[j].length == 0)
1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            continue;
1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          var insertedSlice = subRows[j][subRows[j].length - 1];
1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          if (slice.start < insertedSlice.start) {
1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            this.badSlices_.push(slice);
1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            inserted = true;
1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          }
1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          if (slice.start >= insertedSlice.start &&
1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              slice.end <= insertedSlice.end) {
1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            // Insert it into subRow j + 1.
1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            while (subRows.length <= j + 1)
2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              subRows.push([]);
2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            subRows[j + 1].push(slice);
2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            if (insertedSlice.subSlices)
2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis              insertedSlice.subSlices.push(slice);
2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            inserted = true;
2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis            break;
2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          }
2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        }
2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (inserted)
2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          continue;
2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        // Append it to subRow[0] as a root.
2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        subRows[0].push(slice);
2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return subRows;
2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    },
2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    areArrayContentsSame_: function(a, b) {
2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (!a || !b)
2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return false;
2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (!a.length || !b.length)
2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return false;
2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      if (a.length != b.length)
2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        return false;
2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      for (var i = 0; i < a.length; ++i) {
2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis        if (a[i] != b[i])
2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis          return false;
2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      }
2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis      return true;
2302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis    }
2312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  };
2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis
2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  return {
23488448d9ae4dfff1805045790ef5f32495d62abccJeff Brown    SliceGroupTrack: SliceGroupTrack
2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis  };
2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis});
237