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/rect_track.css"> 9 10<link rel="import" href="/tracing/base/sorted_array_utils.html"> 11<link rel="import" href="/tracing/model/proxy_selectable_item.html"> 12<link rel="import" href="/tracing/ui/base/draw_helpers.html"> 13<link rel="import" href="/tracing/ui/base/fast_rect_renderer.html"> 14<link rel="import" href="/tracing/ui/base/heading.html"> 15<link rel="import" href="/tracing/ui/base/ui.html"> 16<link rel="import" href="/tracing/ui/tracks/track.html"> 17 18<script> 19'use strict'; 20 21tr.exportTo('tr.ui.tracks', function() { 22 23 /** 24 * A track that displays an array of Rect objects. 25 * @constructor 26 * @extends {Track} 27 */ 28 var RectTrack = tr.ui.b.define( 29 'rect-track', tr.ui.tracks.Track); 30 31 RectTrack.prototype = { 32 33 __proto__: tr.ui.tracks.Track.prototype, 34 35 decorate: function(viewport) { 36 tr.ui.tracks.Track.prototype.decorate.call(this, viewport); 37 this.classList.add('rect-track'); 38 this.asyncStyle_ = false; 39 this.rects_ = null; 40 41 this.heading_ = document.createElement('tr-ui-heading'); 42 this.appendChild(this.heading_); 43 }, 44 45 set heading(heading) { 46 this.heading_.heading = heading; 47 }, 48 49 get heading() { 50 return this.heading_.heading; 51 }, 52 53 set tooltip(tooltip) { 54 this.heading_.tooltip = tooltip; 55 }, 56 57 set selectionGenerator(generator) { 58 this.heading_.selectionGenerator = generator; 59 }, 60 61 set expanded(expanded) { 62 this.heading_.expanded = !!expanded; 63 }, 64 65 set arrowVisible(arrowVisible) { 66 this.heading_.arrowVisible = !!arrowVisible; 67 }, 68 69 get expanded() { 70 return this.heading_.expanded; 71 }, 72 73 get asyncStyle() { 74 return this.asyncStyle_; 75 }, 76 77 set asyncStyle(v) { 78 this.asyncStyle_ = !!v; 79 }, 80 81 get rects() { 82 return this.rects_; 83 }, 84 85 set rects(rects) { 86 this.rects_ = rects || []; 87 this.invalidateDrawingContainer(); 88 }, 89 90 get height() { 91 return window.getComputedStyle(this).height; 92 }, 93 94 set height(height) { 95 this.style.height = height; 96 this.invalidateDrawingContainer(); 97 }, 98 99 get hasVisibleContent() { 100 return this.rects_.length > 0; 101 }, 102 103 draw: function(type, viewLWorld, viewRWorld) { 104 switch (type) { 105 case tr.ui.tracks.DrawType.GENERAL_EVENT: 106 this.drawRects_(viewLWorld, viewRWorld); 107 break; 108 } 109 }, 110 111 drawRects_: function(viewLWorld, viewRWorld) { 112 var ctx = this.context(); 113 114 ctx.save(); 115 var bounds = this.getBoundingClientRect(); 116 tr.ui.b.drawSlices( 117 ctx, 118 this.viewport.currentDisplayTransform, 119 viewLWorld, 120 viewRWorld, 121 bounds.height, 122 this.rects_, 123 this.asyncStyle_); 124 ctx.restore(); 125 126 if (bounds.height <= 6) 127 return; 128 129 var fontSize, yOffset; 130 if (bounds.height < 15) { 131 fontSize = 6; 132 yOffset = 1.0; 133 } else { 134 fontSize = 10; 135 yOffset = 2.5; 136 } 137 tr.ui.b.drawLabels( 138 ctx, 139 this.viewport.currentDisplayTransform, 140 viewLWorld, 141 viewRWorld, 142 this.rects_, 143 this.asyncStyle_, 144 fontSize, 145 yOffset); 146 }, 147 148 addEventsToTrackMap: function(eventToTrackMap) { 149 if (this.rects_ === undefined || this.rects_ === null) 150 return; 151 152 this.rects_.forEach(function(rect) { 153 rect.addToTrackMap(eventToTrackMap, this); 154 }, this); 155 }, 156 157 addIntersectingEventsInRangeToSelectionInWorldSpace: function( 158 loWX, hiWX, viewPixWidthWorld, selection) { 159 function onRect(rect) { 160 rect.addToSelection(selection); 161 } 162 onRect = onRect.bind(this); 163 var instantEventWidth = 2 * viewPixWidthWorld; 164 tr.b.iterateOverIntersectingIntervals(this.rects_, 165 function(x) { return x.start; }, 166 function(x) { return x.duration == 0 ? 167 x.duration + instantEventWidth : 168 x.duration; }, 169 loWX, hiWX, 170 onRect); 171 }, 172 173 /** 174 * Add the item to the left or right of the provided event, if any, to the 175 * selection. 176 * @param {rect} The current rect. 177 * @param {Number} offset Number of rects away from the event to look. 178 * @param {Selection} selection The selection to add an event to, 179 * if found. 180 * @return {boolean} Whether an event was found. 181 * @private 182 */ 183 addEventNearToProvidedEventToSelection: function(event, offset, selection) { 184 var index = tr.b.findFirstIndexInArray(this.rects_, function(rect) { 185 return rect.modelItem === event; 186 }); 187 if (index === -1) 188 return false; 189 190 var newIndex = index + offset; 191 if (newIndex < 0 || newIndex >= this.rects_.length) 192 return false; 193 194 this.rects_[newIndex].addToSelection(selection); 195 return true; 196 }, 197 198 addAllEventsMatchingFilterToSelection: function(filter, selection) { 199 for (var i = 0; i < this.rects_.length; ++i) { 200 // TODO(petrcermak): Rather than unpacking the proxy item here, 201 // we should probably add an addToSelectionIfMatching(selection, filter) 202 // method to SelectableItem (#900). 203 var modelItem = this.rects_[i].modelItem; 204 if (!modelItem) 205 continue; 206 if (filter.matchSlice(modelItem)) 207 selection.push(modelItem); 208 } 209 }, 210 211 addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY, 212 selection) { 213 var rect = tr.b.findClosestIntervalInSortedIntervals( 214 this.rects_, 215 function(x) { return x.start; }, 216 function(x) { return x.end; }, 217 worldX, 218 worldMaxDist); 219 220 if (!rect) 221 return; 222 223 rect.addToSelection(selection); 224 } 225 }; 226 227 /** 228 * A filled rectangle with a title. 229 * 230 * @constructor 231 * @extends {ProxySelectableItem} 232 */ 233 function Rect(modelItem, title, colorId, start, duration) { 234 tr.model.ProxySelectableItem.call(this, modelItem); 235 this.title = title; 236 this.colorId = colorId; 237 this.start = start; 238 this.duration = duration; 239 this.end = start + duration; 240 }; 241 242 Rect.prototype = { 243 __proto__: tr.model.ProxySelectableItem.prototype 244 }; 245 246 return { 247 RectTrack: RectTrack, 248 Rect: Rect 249 }; 250}); 251</script> 252