1<!DOCTYPE html> 2<!-- 3Copyright (c) 2015 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/base/color_scheme.html"> 9<link rel="import" href="/tracing/base/sorted_array_utils.html"> 10<link rel="import" href="/tracing/model/proxy_selectable_item.html"> 11<link rel="import" href="/tracing/ui/base/event_presenter.html"> 12<link rel="import" href="/tracing/ui/base/heading.html"> 13<link rel="import" href="/tracing/ui/base/ui.html"> 14<link rel="import" href="/tracing/ui/tracks/track.html"> 15 16<style> 17.letter-dot-track { 18 height: 18px; 19} 20</style> 21 22<script> 23'use strict'; 24 25tr.exportTo('tr.ui.tracks', function() { 26 var EventPresenter = tr.ui.b.EventPresenter; 27 var SelectionState = tr.model.SelectionState; 28 29 /** 30 * A track that displays an array of dots with filled letters inside them. 31 * @constructor 32 * @extends {Track} 33 */ 34 var LetterDotTrack = tr.ui.b.define( 35 'letter-dot-track', tr.ui.tracks.Track); 36 37 LetterDotTrack.prototype = { 38 __proto__: tr.ui.tracks.Track.prototype, 39 40 decorate: function(viewport) { 41 tr.ui.tracks.Track.prototype.decorate.call(this, viewport); 42 this.classList.add('letter-dot-track'); 43 this.items_ = undefined; 44 45 this.heading_ = document.createElement('tr-ui-heading'); 46 this.appendChild(this.heading_); 47 }, 48 49 set heading(heading) { 50 this.heading_.heading = heading; 51 }, 52 53 get heading() { 54 return this.heading_.heading; 55 }, 56 57 set tooltip(tooltip) { 58 this.heading_.tooltip = tooltip; 59 }, 60 61 get items() { 62 return this.items_; 63 }, 64 65 set items(items) { 66 this.items_ = items; 67 this.invalidateDrawingContainer(); 68 }, 69 70 get height() { 71 return window.getComputedStyle(this).height; 72 }, 73 74 set height(height) { 75 this.style.height = height; 76 }, 77 78 get dumpRadiusView() { 79 return 7 * (window.devicePixelRatio || 1); 80 }, 81 82 draw: function(type, viewLWorld, viewRWorld) { 83 if (this.items_ === undefined) 84 return; 85 switch (type) { 86 case tr.ui.tracks.DrawType.GENERAL_EVENT: 87 this.drawLetterDots_(viewLWorld, viewRWorld); 88 break; 89 } 90 }, 91 92 drawLetterDots_: function(viewLWorld, viewRWorld) { 93 var ctx = this.context(); 94 var pixelRatio = window.devicePixelRatio || 1; 95 96 var bounds = this.getBoundingClientRect(); 97 var height = bounds.height * pixelRatio; 98 var halfHeight = height * 0.5; 99 var twoPi = Math.PI * 2; 100 101 // Culling parameters. 102 var dt = this.viewport.currentDisplayTransform; 103 var dumpRadiusView = this.dumpRadiusView; 104 var itemRadiusWorld = dt.xViewVectorToWorld(height); 105 106 // Draw the memory dumps. 107 var items = this.items_; 108 var loI = tr.b.findLowIndexInSortedArray( 109 items, 110 function(item) { return item.start; }, 111 viewLWorld); 112 113 var oldFont = ctx.font; 114 ctx.font = '400 ' + Math.floor(9 * pixelRatio) + 'px Arial'; 115 ctx.strokeStyle = 'rgb(0,0,0)'; 116 ctx.textBaseline = 'middle'; 117 ctx.textAlign = 'center'; 118 119 var drawItems = function(selected) { 120 for (var i = loI; i < items.length; ++i) { 121 var item = items[i]; 122 var x = item.start; 123 if (x - itemRadiusWorld > viewRWorld) 124 break; 125 if (item.selected !== selected) 126 continue; 127 var xView = dt.xWorldToView(x); 128 129 ctx.fillStyle = EventPresenter.getSelectableItemColorAsString(item); 130 ctx.beginPath(); 131 ctx.arc(xView, halfHeight, dumpRadiusView + 0.5, 0, twoPi); 132 ctx.fill(); 133 if (item.selected) { 134 ctx.lineWidth = 3; 135 ctx.strokeStyle = 'rgb(100,100,0)'; 136 ctx.stroke(); 137 138 ctx.beginPath(); 139 ctx.arc(xView, halfHeight, dumpRadiusView, 0, twoPi); 140 ctx.lineWidth = 1.5; 141 ctx.strokeStyle = 'rgb(255,255,0)'; 142 ctx.stroke(); 143 } else { 144 ctx.lineWidth = 1; 145 ctx.strokeStyle = 'rgb(0,0,0)'; 146 ctx.stroke(); 147 } 148 149 ctx.fillStyle = 'rgb(255, 255, 255)'; 150 ctx.fillText(item.dotLetter, xView, halfHeight); 151 } 152 }; 153 154 // Draw unselected items first to make sure they don't occlude selected 155 // items. 156 drawItems(false); 157 drawItems(true); 158 159 ctx.lineWidth = 1; 160 ctx.font = oldFont; 161 }, 162 163 addEventsToTrackMap: function(eventToTrackMap) { 164 if (this.items_ === undefined) 165 return; 166 167 this.items_.forEach(function(item) { 168 item.addToTrackMap(eventToTrackMap, this); 169 }, this); 170 }, 171 172 addIntersectingEventsInRangeToSelectionInWorldSpace: function( 173 loWX, hiWX, viewPixWidthWorld, selection) { 174 if (this.items_ === undefined) 175 return; 176 177 var itemRadiusWorld = viewPixWidthWorld * this.dumpRadiusView; 178 tr.b.iterateOverIntersectingIntervals( 179 this.items_, 180 function(x) { return x.start - itemRadiusWorld; }, 181 function(x) { return 2 * itemRadiusWorld; }, 182 loWX, hiWX, 183 function(item) { 184 item.addToSelection(selection); 185 }.bind(this)); 186 }, 187 188 /** 189 * Add the item to the left or right of the provided event, if any, to the 190 * selection. 191 * @param {event} The current event item. 192 * @param {Number} offset Number of slices away from the event to look. 193 * @param {Selection} selection The selection to add an event to, 194 * if found. 195 * @return {boolean} Whether an event was found. 196 * @private 197 */ 198 addEventNearToProvidedEventToSelection: function(event, offset, selection) { 199 if (this.items_ === undefined) 200 return; 201 202 var items = this.items_; 203 var index = tr.b.findFirstIndexInArray(items, function(item) { 204 return item.modelItem === event; 205 }); 206 if (index === -1) 207 return false; 208 209 var newIndex = index + offset; 210 if (newIndex >= 0 && newIndex < items.length) { 211 items[newIndex].addToSelection(selection); 212 return true; 213 } 214 return false; 215 }, 216 217 addAllEventsMatchingFilterToSelection: function(filter, selection) { 218 }, 219 220 addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY, 221 selection) { 222 if (this.items_ === undefined) 223 return; 224 225 var item = tr.b.findClosestElementInSortedArray( 226 this.items_, 227 function(x) { return x.start; }, 228 worldX, 229 worldMaxDist); 230 231 if (!item) 232 return; 233 234 item.addToSelection(selection); 235 } 236 }; 237 238 /** 239 * A filled dot with a letter inside it. 240 * 241 * @constructor 242 * @extends {ProxySelectableItem} 243 */ 244 function LetterDot(modelItem, dotLetter, colorId, start) { 245 tr.model.ProxySelectableItem.call(this, modelItem); 246 this.dotLetter = dotLetter; 247 this.colorId = colorId; 248 this.start = start; 249 }; 250 251 LetterDot.prototype = { 252 __proto__: tr.model.ProxySelectableItem.prototype 253 }; 254 255 return { 256 LetterDotTrack: LetterDotTrack, 257 LetterDot: LetterDot 258 }; 259}); 260</script> 261