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/ui/tracks/slice_track.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 AsyncSliceGroup. 18 * @constructor 19 * @extends {MultiRowTrack} 20 */ 21 var AsyncSliceGroupTrack = tr.ui.b.define( 22 'async-slice-group-track', 23 tr.ui.tracks.MultiRowTrack); 24 25 AsyncSliceGroupTrack.prototype = { 26 27 __proto__: tr.ui.tracks.MultiRowTrack.prototype, 28 29 decorate: function(viewport) { 30 tr.ui.tracks.MultiRowTrack.prototype.decorate.call(this, viewport); 31 this.classList.add('async-slice-group-track'); 32 this.group_ = undefined; 33 }, 34 35 addSubTrack_: function(slices) { 36 var track = new tr.ui.tracks.SliceTrack(this.viewport); 37 track.slices = slices; 38 this.appendChild(track); 39 track.asyncStyle = true; 40 return track; 41 }, 42 43 get group() { 44 return this.group_; 45 }, 46 47 set group(group) { 48 this.group_ = group; 49 this.setItemsToGroup(this.group_.slices, this.group_); 50 }, 51 52 get eventContainer() { 53 return this.group; 54 }, 55 56 addContainersToTrackMap: function(containerToTrackMap) { 57 tr.ui.tracks.MultiRowTrack.prototype.addContainersToTrackMap.apply( 58 this, arguments); 59 containerToTrackMap.addContainer(this.group, this); 60 }, 61 62 /** 63 * Breaks up the list of slices into N rows, each of which is a list of 64 * slices that are non overlapping. 65 * 66 * It uses a very simple approach: walk through the slices in sorted order 67 * by start time. For each slice, try to fit it in an existing subRow. If 68 * it doesn't fit in any subrow, make another subRow. It then fits nested 69 * subSlices recursively into rows below parent slice according to which 70 * nested level the child is in. 71 */ 72 buildSubRows_: function(slices, opt_skipSort) { 73 if (!opt_skipSort) { 74 slices.sort(function(x, y) { 75 return x.start - y.start; 76 }); 77 } 78 79 // Helper function that returns true if it can put the slice on row n. 80 var findLevel = function(sliceToPut, rows, n) { 81 if (n >= rows.length) 82 return true; // We always can make empty rows to put the slice. 83 var subRow = rows[n]; 84 var lastSliceInSubRow = subRow[subRow.length - 1]; 85 if (sliceToPut.start >= lastSliceInSubRow.end) { 86 if (sliceToPut.subSlices === undefined || 87 sliceToPut.subSlices.length === 0) { 88 return true; 89 } 90 // Make sure nested sub slices can be fitted in as well. 91 for (var i = 0; i < sliceToPut.subSlices.length; i++) { 92 if (!findLevel(sliceToPut.subSlices[i], rows, n + 1)) 93 return false; 94 } 95 return true; 96 } 97 return false; 98 }; 99 100 var subRows = []; 101 for (var i = 0; i < slices.length; i++) { 102 var slice = slices[i]; 103 104 var found = false; 105 var index = subRows.length; 106 for (var j = 0; j < subRows.length; j++) { 107 if (findLevel(slice, subRows, j)) { 108 found = true; 109 index = j; 110 break; 111 } 112 } 113 if (!found) 114 subRows.push([]); 115 subRows[index].push(slice); 116 117 // Fit subSlices recursively into rows below parent. 118 var fitSubSlicesRecursively = function(subSlices, level, rows) { 119 if (subSlices === undefined || subSlices.length === 0) 120 return; 121 if (level === rows.length) 122 rows.push([]); 123 for (var h = 0; h < subSlices.length; h++) { 124 rows[level].push(subSlices[h]); 125 fitSubSlicesRecursively(subSlices[h].subSlices, level + 1, rows); 126 } 127 }; 128 fitSubSlicesRecursively(slice.subSlices, index + 1, subRows); 129 } 130 return subRows; 131 } 132 }; 133 134 return { 135 AsyncSliceGroupTrack: AsyncSliceGroupTrack 136 }; 137}); 138</script> 139