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="import" href="/tracing/ui/tracks/multi_row_track.html"> 9<link rel="import" href="/tracing/base/sorted_array_utils.html"> 10<link rel="import" href="/tracing/ui/base/ui.html"> 11 12<script> 13'use strict'; 14 15tr.exportTo('tr.ui.tracks', function() { 16 /** 17 * A track that displays a SliceGroup. 18 * @constructor 19 * @extends {MultiRowTrack} 20 */ 21 var SliceGroupTrack = tr.ui.b.define( 22 'slice-group-track', tr.ui.tracks.MultiRowTrack); 23 24 SliceGroupTrack.prototype = { 25 26 __proto__: tr.ui.tracks.MultiRowTrack.prototype, 27 28 decorate: function(viewport) { 29 tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this, viewport); 30 this.classList.add('slice-group-track'); 31 this.group_ = undefined; 32 // Set the collapse threshold so we don't collapse by default, but the 33 // user can explicitly collapse if they want it. 34 this.defaultToCollapsedWhenSubRowCountMoreThan = 100; 35 }, 36 37 addSubTrack_: function(slices) { 38 var track = new tr.ui.tracks.SliceTrack(this.viewport); 39 track.slices = slices; 40 this.appendChild(track); 41 return track; 42 }, 43 44 get group() { 45 return this.group_; 46 }, 47 48 set group(group) { 49 this.group_ = group; 50 this.setItemsToGroup(this.group_.slices, this.group_); 51 }, 52 53 get eventContainer() { 54 return this.group; 55 }, 56 57 addContainersToTrackMap: function(containerToTrackMap) { 58 tr.ui.tracks.MultiRowTrack.prototype.addContainersToTrackMap.apply( 59 this, arguments); 60 containerToTrackMap.addContainer(this.group, this); 61 }, 62 63 /** 64 * Breaks up the list of slices into N rows, each of which is a list of 65 * slices that are non overlapping. 66 */ 67 buildSubRows_: function(slices) { 68 var precisionUnit = this.group.model.intrinsicTimeUnit; 69 70 // This function works by walking through slices by start time. 71 // 72 // The basic idea here is to insert each slice as deep into the subrow 73 // list as it can go such that every subSlice is fully contained by its 74 // parent slice. 75 // 76 // Visually, if we start with this: 77 // 0: [ a ] 78 // 1: [ b ] 79 // 2: [c][d] 80 // 81 // To place this slice: 82 // [e] 83 // We first check row 2's last item, [d]. [e] wont fit into [d] (they dont 84 // even intersect). So we go to row 1. That gives us [b], and [d] wont fit 85 // into that either. So, we go to row 0 and its last slice, [a]. That can 86 // completely contain [e], so that means we should add [e] as a subchild 87 // of [a]. That puts it on row 1, yielding: 88 // 0: [ a ] 89 // 1: [ b ][e] 90 // 2: [c][d] 91 // 92 // If we then get this slice: 93 // [f] 94 // We do the same deepest-to-shallowest walk of the subrows trying to fit 95 // it. This time, it doesn't fit in any open slice. So, we simply append 96 // it to row 0: 97 // 0: [ a ] [f] 98 // 1: [ b ][e] 99 // 2: [c][d] 100 if (!slices.length) 101 return []; 102 103 var ops = []; 104 for (var i = 0; i < slices.length; i++) { 105 if (slices[i].subSlices) 106 slices[i].subSlices.splice(0, 107 slices[i].subSlices.length); 108 ops.push(i); 109 } 110 111 ops.sort(function(ix, iy) { 112 var x = slices[ix]; 113 var y = slices[iy]; 114 if (x.start != y.start) 115 return x.start - y.start; 116 117 // Elements get inserted into the slices array in order of when the 118 // slices start. Because slices must be properly nested, we break 119 // start-time ties by assuming that the elements appearing earlier in 120 // the slices array (and thus ending earlier) start earlier. 121 return ix - iy; 122 }); 123 124 var subRows = [[]]; 125 this.badSlices_ = []; // TODO(simonjam): Connect this again. 126 127 for (var i = 0; i < ops.length; i++) { 128 var op = ops[i]; 129 var slice = slices[op]; 130 131 // Try to fit the slice into the existing subrows. 132 var inserted = false; 133 for (var j = subRows.length - 1; j >= 0; j--) { 134 if (subRows[j].length == 0) 135 continue; 136 137 var insertedSlice = subRows[j][subRows[j].length - 1]; 138 if (slice.start < insertedSlice.start) { 139 this.badSlices_.push(slice); 140 inserted = true; 141 } 142 if (insertedSlice.bounds(slice, precisionUnit)) { 143 // Insert it into subRow j + 1. 144 while (subRows.length <= j + 1) 145 subRows.push([]); 146 subRows[j + 1].push(slice); 147 if (insertedSlice.subSlices) 148 insertedSlice.subSlices.push(slice); 149 inserted = true; 150 break; 151 } 152 } 153 if (inserted) 154 continue; 155 156 // Append it to subRow[0] as a root. 157 subRows[0].push(slice); 158 } 159 160 return subRows; 161 } 162 }; 163 164 return { 165 SliceGroupTrack: SliceGroupTrack 166 }; 167}); 168</script> 169