slice_track.js revision 88448d9ae4dfff1805045790ef5f32495d62abcc
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 788448d9ae4dfff1805045790ef5f32495d62abccJeff Brownbase.requireStylesheet('tracks.slice_track'); 82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 988448d9ae4dfff1805045790ef5f32495d62abccJeff Brownbase.require('tracks.canvas_based_track'); 102da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('sorted_array_utils'); 112da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('fast_rect_renderer'); 1288448d9ae4dfff1805045790ef5f32495d62abccJeff Brownbase.require('color_scheme'); 132da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('ui'); 142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1588448d9ae4dfff1805045790ef5f32495d62abccJeff Brownbase.exportTo('tracing.tracks', function() { 162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var palette = tracing.getColorPalette(); 182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 2088448d9ae4dfff1805045790ef5f32495d62abccJeff Brown * A track that displays an array of Slice objects. 212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @constructor 222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @extends {CanvasBasedTrack} 232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2588448d9ae4dfff1805045790ef5f32495d62abccJeff Brown var SliceTrack = tracing.ui.define(tracing.tracks.CanvasBasedTrack); 262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown SliceTrack.prototype = { 282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2988448d9ae4dfff1805045790ef5f32495d62abccJeff Brown __proto__: tracing.tracks.CanvasBasedTrack.prototype, 302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Should we elide text on trace labels? 332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Without eliding, text that is too wide isn't drawn at all. 342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Disable if you feel this causes a performance problem. 352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * This is a default value that can be overridden in tracks for testing. 362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @const 372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis SHOULD_ELIDE_TEXT: true, 392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis decorate: function() { 4188448d9ae4dfff1805045790ef5f32495d62abccJeff Brown this.classList.add('slice-track'); 422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.elidedTitleCache = new ElidedTitleCache(); 432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.asyncStyle_ = false; 442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Called by all the addToSelection functions on the created selection 482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * hit objects. Override this function on parent classes to add 492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * context-specific information to the hit. 502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis decorateHit: function(hit) { 522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get asyncStyle() { 552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.asyncStyle_; 562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis set asyncStyle(v) { 592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.asyncStyle_ = !!v; 602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.invalidate(); 612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get slices() { 642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.slices_; 652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis set slices(slices) { 682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.slices_ = slices || []; 692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!slices) 702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.visible = false; 712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.invalidate(); 722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get height() { 752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return window.getComputedStyle(this).height; 762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis set height(height) { 792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.style.height = height; 802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.invalidate(); 812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis labelWidth: function(title) { 842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return quickMeasureText(this.ctx_, title) + 2; 852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis labelWidthWorld: function(title, pixWidth) { 882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.labelWidth(title) * pixWidth; 892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis redraw: function() { 922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var ctx = this.ctx_; 932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canvasW = this.canvas_.width; 942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canvasH = this.canvas_.height; 952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.clearRect(0, 0, canvasW, canvasH); 972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Culling parameters. 992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var vp = this.viewport_; 1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var pixWidth = vp.xViewVectorToWorld(1); 1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var viewLWorld = vp.xViewToWorld(0); 1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var viewRWorld = vp.xViewToWorld(canvasW); 1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Give the viewport a chance to draw onto this canvas. 1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.drawUnderContent(ctx, viewLWorld, viewRWorld, canvasH); 1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Begin rendering in world space. 1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.save(); 1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.applyTransformToCanvas(ctx); 1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Slices. 1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.asyncStyle_) 1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.globalAlpha = 0.25; 1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var tr = new tracing.FastRectRenderer(ctx, 2 * pixWidth, 2 * pixWidth, 1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis palette); 1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tr.setYandH(0, canvasH); 1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var slices = this.slices_; 1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var lowSlice = tracing.findLowIndexInSortedArray(slices, 1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function(slice) { 1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return slice.start + 1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis slice.duration; 1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis viewLWorld); 1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (var i = lowSlice; i < slices.length; ++i) { 1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var slice = slices[i]; 1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var x = slice.start; 1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (x > viewRWorld) { 1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Less than 0.001 causes short events to disappear when zoomed in. 1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var w = Math.max(slice.duration, 0.001); 1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var colorId = slice.selected ? 1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis slice.colorId + highlightIdBoost : 1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis slice.colorId; 1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (w < pixWidth) 1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis w = pixWidth; 1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (slice.duration > 0) { 1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tr.fillRect(x, w, colorId); 1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Instant: draw a triangle. If zoomed too far, collapse 1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // into the FastRectRenderer. 1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (pixWidth > 0.001) { 1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tr.fillRect(x, pixWidth, colorId); 1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fillStyle = palette[colorId]; 1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.beginPath(); 1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.moveTo(x - (4 * pixWidth), canvasH); 1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.lineTo(x, 0); 1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.lineTo(x + (4 * pixWidth), canvasH); 1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.closePath(); 1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fill(); 1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tr.flush(); 1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.restore(); 1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Labels. 1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var pixelRatio = window.devicePixelRatio || 1; 1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (canvasH > 8) { 1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.textAlign = 'center'; 1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.textBaseline = 'top'; 1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.font = (10 * pixelRatio) + 'px sans-serif'; 1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.strokeStyle = 'rgb(0,0,0)'; 1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fillStyle = 'rgb(0,0,0)'; 1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Don't render text until until it is 20px wide 1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var quickDiscardThresshold = pixWidth * 20; 1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var shouldElide = this.SHOULD_ELIDE_TEXT; 1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (var i = lowSlice; i < slices.length; ++i) { 1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var slice = slices[i]; 1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (slice.start > viewRWorld) { 1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (slice.duration > quickDiscardThresshold) { 1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var title = slice.title; 1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (slice.didNotFinish) { 1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis title += ' (Did Not Finish)'; 1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var drawnTitle = title; 1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var drawnWidth = this.labelWidth(drawnTitle); 1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (shouldElide && 1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.labelWidthWorld(drawnTitle, pixWidth) > slice.duration) { 1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var elidedValues = this.elidedTitleCache.get( 1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this, pixWidth, 1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis drawnTitle, drawnWidth, 1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis slice.duration); 1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis drawnTitle = elidedValues.string; 1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis drawnWidth = elidedValues.width; 1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (drawnWidth * pixWidth < slice.duration) { 1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var cX = vp.xWorldToView(slice.start + 0.5 * slice.duration); 1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fillText(drawnTitle, cX, 2.5 * pixelRatio, drawnWidth); 1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Give the viewport a chance to draw over this canvas. 2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.drawOverContent(ctx, viewLWorld, viewRWorld, canvasH); 2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Finds slices intersecting the given interval. 2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} vX X location to search at, in viewspace. 2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} vY Y location to search at, in viewspace. 20788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown * @param {Selection} selection Selection to which to add hits. 2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @return {boolean} true if a slice was found, otherwise false. 2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis addIntersectingItemsToSelection: function(vX, vY, selection) { 2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var clientRect = this.getBoundingClientRect(); 2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (vY < clientRect.top || vY >= clientRect.bottom) 2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var pixelRatio = window.devicePixelRatio || 1; 2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var wX = this.viewport_.xViewVectorToWorld(vX * devicePixelRatio); 2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var x = tracing.findLowIndexInSortedIntervals(this.slices_, 2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function(x) { return x.start; }, 2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function(x) { return x.duration; }, 2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis wX); 2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (x >= 0 && x < this.slices_.length) { 2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hit = selection.addSlice(this, this.slices_[x]); 2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.decorateHit(hit); 2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return true; 2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Adds items intersecting the given range to a selection. 2302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} loVX Lower X bound of the interval to search, in 2312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * viewspace. 2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} hiVX Upper X bound of the interval to search, in 2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * viewspace. 2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} loVY Lower Y bound of the interval to search, in 2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * viewspace. 2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} hiVY Upper Y bound of the interval to search, in 2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * viewspace. 23888448d9ae4dfff1805045790ef5f32495d62abccJeff Brown * @param {Selection} selection Selection to which to add hits. 2392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis addIntersectingItemsInRangeToSelection: function( 2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis loVX, hiVX, loVY, hiVY, selection) { 2422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var pixelRatio = window.devicePixelRatio || 1; 2442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var loWX = this.viewport_.xViewToWorld(loVX * pixelRatio); 2452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hiWX = this.viewport_.xViewToWorld(hiVX * pixelRatio); 2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var clientRect = this.getBoundingClientRect(); 2482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var a = Math.max(loVY, clientRect.top); 2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var b = Math.min(hiVY, clientRect.bottom); 2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (a > b) 2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var that = this; 2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function onPickHit(slice) { 2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hit = selection.addSlice(that, slice); 2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis that.decorateHit(hit); 2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tracing.iterateOverIntersectingIntervals(this.slices_, 2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function(x) { return x.start; }, 2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function(x) { return x.duration; }, 2612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis loWX, hiWX, 2622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onPickHit); 2632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 2642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 2662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Find the index for the given slice. 2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @return {index} Index of the given slice, or undefined. 2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @private 2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis indexOfSlice_: function(slice) { 2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var index = tracing.findLowIndexInSortedArray(this.slices_, 2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function(x) { return x.start; }, 2732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis slice.start); 2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis while (index < this.slices_.length && 2752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis slice.start == this.slices_[index].start && 2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis slice.colorId != this.slices_[index].colorId) { 2772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis index++; 2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return index < this.slices_.length ? index : undefined; 2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 2812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 2832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Add the item to the left or right of the provided hit, if any, to the 2842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * selection. 2852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {slice} The current slice. 2862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {Number} offset Number of slices away from the hit to look. 28788448d9ae4dfff1805045790ef5f32495d62abccJeff Brown * @param {Selection} selection The selection to add a hit to, 2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * if found. 2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @return {boolean} Whether a hit was found. 2902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @private 2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis addItemNearToProvidedHitToSelection: function(hit, offset, selection) { 2932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!hit.slice) 2942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var index = this.indexOfSlice_(hit.slice); 2972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (index === undefined) 2982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 2992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var newIndex = index + offset; 3012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (newIndex < 0 || newIndex >= this.slices_.length) 3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 3032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hit = selection.addSlice(this, this.slices_[newIndex]); 3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.decorateHit(hit); 3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return true; 3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 3082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis addAllObjectsMatchingFilterToSelection: function(filter, selection) { 3102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (var i = 0; i < this.slices_.length; ++i) { 3112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (filter.matchSlice(this.slices_[i])) { 3122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hit = selection.addSlice(this, this.slices_[i]); 3132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.decorateHit(hit); 3142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 3182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var highlightIdBoost = tracing.getColorPaletteHighlightIdBoost(); 3202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // TODO(jrg): possibly obsoleted with the elided string cache. 3222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Consider removing. 3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textWidthMap = { }; 3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function quickMeasureText(ctx, text) { 3252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var w = textWidthMap[text]; 3262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!w) { 3272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis w = ctx.measureText(text).width; 3282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis textWidthMap[text] = w; 3292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return w; 3312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 3342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Cache for elided strings. 3352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Moved from the ElidedTitleCache protoype to a "global" for speed 3362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * (variable reference is 100x faster). 3372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * key: String we wish to elide. 3382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * value: Another dict whose key is width 3392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * and value is an ElidedStringWidthPair. 3402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 3412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var elidedTitleCacheDict = {}; 3422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * A cache for elided strings. 3452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @constructor 3462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 3472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function ElidedTitleCache() { 3482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ElidedTitleCache.prototype = { 3512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 3522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Return elided text. 35388448d9ae4dfff1805045790ef5f32495d62abccJeff Brown * @param {track} A slice track or other object that defines 3542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * functions labelWidth() and labelWidthWorld(). 3552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {pixWidth} Pixel width. 3562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {title} Original title text. 3572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {width} Drawn width in world coords. 3582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {sliceDuration} Where the title must fit (in world coords). 3592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @return {ElidedStringWidthPair} Elided string and width. 3602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 3612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get: function(track, pixWidth, title, width, sliceDuration) { 3622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var elidedDict = elidedTitleCacheDict[title]; 3632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!elidedDict) { 3642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis elidedDict = {}; 3652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis elidedTitleCacheDict[title] = elidedDict; 3662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var elidedDictForPixWidth = elidedDict[pixWidth]; 3682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!elidedDictForPixWidth) { 3692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis elidedDict[pixWidth] = {}; 3702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis elidedDictForPixWidth = elidedDict[pixWidth]; 3712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var stringWidthPair = elidedDictForPixWidth[sliceDuration]; 3732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (stringWidthPair === undefined) { 3742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var newtitle = title; 3752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var elided = false; 3762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis while (track.labelWidthWorld(newtitle, pixWidth) > sliceDuration) { 3772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis newtitle = newtitle.substring(0, newtitle.length * 0.75); 3782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis elided = true; 3792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (elided && newtitle.length > 3) 3812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis newtitle = newtitle.substring(0, newtitle.length - 3) + '...'; 3822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis stringWidthPair = new ElidedStringWidthPair( 3832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis newtitle, 3842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis track.labelWidth(newtitle)); 3852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis elidedDictForPixWidth[sliceDuration] = stringWidthPair; 3862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return stringWidthPair; 3882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 3902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 3922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * A pair representing an elided string and world-coordinate width 3932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * to draw it. 3942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @constructor 3952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 3962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function ElidedStringWidthPair(string, width) { 3972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.string = string; 3982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.width = width; 3992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return { 40288448d9ae4dfff1805045790ef5f32495d62abccJeff Brown SliceTrack: SliceTrack 4032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 4042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis}); 405