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 72da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.requireStylesheet('tracks.timeline_viewport_track'); 82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 92da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('tracks.timeline_track'); 102da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('tracks.timeline_canvas_based_track'); 112da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('ui'); 122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 132da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.exportTo('tracks', function() { 142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * A track that displays the viewport size and scale. 172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @constructor 182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @extends {CanvasBasedTrack} 192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var TimelineViewportTrack = base.ui.define(tracks.TimelineCanvasBasedTrack); 222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var logOf10 = Math.log(10); 242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function log10(x) { 252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return Math.log(x) / logOf10; 262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis TimelineViewportTrack.prototype = { 292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis __proto__: tracks.TimelineCanvasBasedTrack.prototype, 312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis decorate: function() { 332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.classList.add('timeline-viewport-track'); 342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.strings_secs_ = []; 352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.strings_msecs_ = []; 362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.addEventListener('mousedown', this.onMouseDown); 372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onMouseDown: function(e) { 402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (e.button != 0) 412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.placeAndBeginDraggingMarker(e.clientX); 432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis placeAndBeginDraggingMarker: function(clientX) { 472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var viewX = clientX - this.canvasContainer_.offsetLeft; 482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var worldX = this.viewport_.xViewToWorld(viewX); 492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var marker = this.viewport_.findMarkerNear(worldX, 6); 502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var createdMarker = false; 512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var movedMarker = false; 522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!marker) { 532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis marker = this.viewport_.addMarker(worldX); 542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis createdMarker = true; 552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis marker.selected = true; 572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var that = this; 592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var onMouseMove = function(e) { 602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var viewX = e.clientX - that.canvasContainer_.offsetLeft; 612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var worldX = that.viewport_.xViewToWorld(viewX); 622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis marker.positionWorld = worldX; 632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis movedMarker = true; 642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var onMouseUp = function(e) { 672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis marker.selected = false; 682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!movedMarker && !createdMarker) 692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis that.viewport_.removeMarker(marker); 702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis document.removeEventListener('mouseup', onMouseUp); 712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis document.removeEventListener('mousemove', onMouseMove); 722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis document.addEventListener('mouseup', onMouseUp); 752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis document.addEventListener('mousemove', onMouseMove); 762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis drawLine_: function(ctx, x1, y1, x2, y2, color) { 792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.beginPath(); 802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.moveTo(x1, y1); 812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.lineTo(x2, y2); 822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.closePath(); 832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.strokeStyle = color; 842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.stroke(); 852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis drawArrow_: function(ctx, x1, y1, x2, y2, arrowWidth, color) { 882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.drawLine_(ctx, x1, y1, x2, y2, color); 902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var dx = x2 - x1; 922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var dy = y2 - y1; 932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var len = Math.sqrt(dx * dx + dy * dy); 942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var perc = (len - 10) / len; 952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var bx = x1 + perc * dx; 962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var by = y1 + perc * dy; 972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var ux = dx / len; 982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var uy = dy / len; 992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var ax = uy * arrowWidth; 1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var ay = -ux * arrowWidth; 1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.beginPath(); 1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fillStyle = color; 1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.moveTo(bx + ax, by + ay); 1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.lineTo(x2, y2); 1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.lineTo(bx - ax, by - ay); 1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.lineTo(bx + ax, by + ay); 1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.closePath(); 1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fill(); 1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis redraw: function() { 1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var ctx = this.ctx_; 1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canvasW = this.canvas_.width; 1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canvasH = this.canvas_.height; 1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.clearRect(0, 0, canvasW, canvasH); 1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Culling parametrs. 1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var vp = this.viewport_; 1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var pixWidth = vp.xViewVectorToWorld(1); 1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var viewLWorld = vp.xViewToWorld(0); 1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var viewRWorld = vp.xViewToWorld(canvasW); 1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var measurements = this.classList.contains('timeline-viewport' + 1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '-track-with-distance-measurements'); 1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var rulerHeight = measurements ? canvasH / 2 : canvasH; 1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (var i = 0; i < vp.markers.length; ++i) { 1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.markers[i].drawTriangle_(ctx, viewLWorld, viewRWorld, 1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis canvasH, rulerHeight, vp); 1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var idealMajorMarkDistancePix = 150; 1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var idealMajorMarkDistanceWorld = 1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.xViewVectorToWorld(idealMajorMarkDistancePix); 1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var majorMarkDistanceWorld; 1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var unit; 1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var unitDivisor; 1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var tickLabels; 1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // The conservative guess is the nearest enclosing 0.1, 1, 10, 100, etc. 1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var conservativeGuess = 1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Math.pow(10, Math.ceil(log10(idealMajorMarkDistanceWorld))); 1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Once we have a conservative guess, consider things that evenly add up 1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // to the conservative guess, e.g. 0.5, 0.2, 0.1 Pick the one that still 1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // exceeds the ideal mark distance. 1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var divisors = [10, 5, 2, 1]; 1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (var i = 0; i < divisors.length; ++i) { 1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var tightenedGuess = conservativeGuess / divisors[i]; 1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (vp.xWorldVectorToView(tightenedGuess) < idealMajorMarkDistancePix) 1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis continue; 1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis majorMarkDistanceWorld = conservativeGuess / divisors[i - 1]; 1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var tickLabels = undefined; 1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (majorMarkDistanceWorld < 100) { 1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis unit = 'ms'; 1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis unitDivisor = 1; 1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tickLabels = this.strings_msecs_; 1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis unit = 's'; 1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis unitDivisor = 1000; 1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tickLabels = this.strings_secs_; 1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var numTicksPerMajor = 5; 1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var minorMarkDistanceWorld = majorMarkDistanceWorld / numTicksPerMajor; 1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var minorMarkDistancePx = vp.xWorldVectorToView(minorMarkDistanceWorld); 1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var firstMajorMark = 1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Math.floor(viewLWorld / majorMarkDistanceWorld) * 1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis majorMarkDistanceWorld; 1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var minorTickH = Math.floor(canvasH * 0.25); 1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fillStyle = 'rgb(0, 0, 0)'; 1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.strokeStyle = 'rgb(0, 0, 0)'; 1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.textAlign = 'left'; 1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.textBaseline = 'top'; 1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var pixelRatio = window.devicePixelRatio || 1; 1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.font = (9 * pixelRatio) + 'px sans-serif'; 1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Each iteration of this loop draws one major mark 1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // and numTicksPerMajor minor ticks. 1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // 1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Rendering can't be done in world space because canvas transforms 1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // affect line width. So, do the conversions manually. 1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (var curX = firstMajorMark; 1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis curX < viewRWorld; 1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis curX += majorMarkDistanceWorld) { 1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var curXView = Math.floor(vp.xWorldToView(curX)); 1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var unitValue = curX / unitDivisor; 2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var roundedUnitValue = Math.floor(unitValue * 100000) / 100000; 2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!tickLabels[roundedUnitValue]) 2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tickLabels[roundedUnitValue] = roundedUnitValue + ' ' + unit; 2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fillText(tickLabels[roundedUnitValue], 2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis curXView + 2 * pixelRatio, 0); 2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.beginPath(); 2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Major mark 2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.moveTo(curXView, 0); 2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.lineTo(curXView, rulerHeight); 2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Minor marks 2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (var i = 1; i < numTicksPerMajor; ++i) { 2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var xView = Math.floor(curXView + minorMarkDistancePx * i); 2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.moveTo(xView, rulerHeight - minorTickH); 2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.lineTo(xView, rulerHeight); 2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.stroke(); 2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Give distance between directly adjacent markers. 2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (measurements) { 2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Divide canvas horizontally between ruler and measurements. 2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.moveTo(0, rulerHeight); 2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.lineTo(canvasW, rulerHeight); 2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.stroke(); 2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Obtain a sorted array of markers 2312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var sortedMarkers = vp.markers.slice(); 2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sortedMarkers.sort(function(a, b) { 2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return a.positionWorld_ - b.positionWorld_; 2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }); 2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Distance Variables. 2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var displayDistance; 2382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var unitDivisor; 2392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var displayTextColor = 'rgb(0,0,0)'; 2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var measurementsPosY = rulerHeight + 2; 2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Arrow Variables. 2432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var arrowSpacing = 10; 2442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var arrowColor = 'rgb(128,121,121)'; 2452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var arrowPosY = measurementsPosY + 4; 2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var arrowWidthView = 3; 2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var spaceForArrowsView = 2 * (arrowWidthView + arrowSpacing); 2482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (i = 0; i < sortedMarkers.length - 1; i++) { 2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var rightMarker = sortedMarkers[i + 1]; 2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var leftMarker = sortedMarkers[i]; 2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var distanceBetweenMarkers = 2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis rightMarker.positionWorld - leftMarker.positionWorld; 2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var distanceBetweenMarkersView = 2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.xWorldVectorToView(distanceBetweenMarkers); 2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var positionInMiddleOfMarkers = leftMarker.positionWorld + 2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis distanceBetweenMarkers / 2; 2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var positionInMiddleOfMarkersView = 2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.xWorldToView(positionInMiddleOfMarkers); 2612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Determine units. 2632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (distanceBetweenMarkers < 100) { 2642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis unit = 'ms'; 2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis unitDivisor = 1; 2662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis unit = 's'; 2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis unitDivisor = 1000; 2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Calculate display value to print. 2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis displayDistance = distanceBetweenMarkers / unitDivisor; 2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var roundedDisplayDistance = 2732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Math.abs((Math.floor(displayDistance * 1000) / 1000)); 2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textToDraw = roundedDisplayDistance + ' ' + unit; 2752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textWidthView = ctx.measureText(textToDraw).width; 2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textWidthWorld = vp.xViewVectorToWorld(textWidthView); 2772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var spaceForArrowsAndTextView = textWidthView + 2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis spaceForArrowsView + arrowSpacing; 2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Set text positions. 2812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textLeft = leftMarker.positionWorld + 2822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis (distanceBetweenMarkers / 2) - (textWidthWorld / 2); 2832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textRight = textLeft + textWidthWorld; 2842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textPosY = measurementsPosY; 2852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textLeftView = vp.xWorldToView(textLeft); 2862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textRightView = vp.xWorldToView(textRight); 2872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var leftMarkerView = vp.xWorldToView(leftMarker.positionWorld); 2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var rightMarkerView = vp.xWorldToView(rightMarker.positionWorld); 2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var textDrawn = false; 2902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (spaceForArrowsAndTextView <= distanceBetweenMarkersView) { 2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Print the display distance text. 2932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fillStyle = displayTextColor; 2942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ctx.fillText(textToDraw, textLeftView, textPosY); 2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis textDrawn = true; 2962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (spaceForArrowsView <= distanceBetweenMarkersView) { 2992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var leftArrowStart; 3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var rightArrowStart; 3012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (textDrawn) { 3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis leftArrowStart = textLeftView - arrowSpacing; 3032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis rightArrowStart = textRightView + arrowSpacing; 3042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis leftArrowStart = positionInMiddleOfMarkersView; 3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis rightArrowStart = positionInMiddleOfMarkersView; 3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Draw left arrow. 3092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.drawArrow_(ctx, leftArrowStart, arrowPosY, 3102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis leftMarkerView, arrowPosY, arrowWidthView, arrowColor); 3112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Draw right arrow. 3122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.drawArrow_(ctx, rightArrowStart, arrowPosY, 3132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis rightMarkerView, arrowPosY, arrowWidthView, arrowColor); 3142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 3182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 3202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Adds items intersecting a point to a selection. 3212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} vX X location to search at, in viewspace. 3222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} vY Y location to search at, in viewspace. 3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {TimelineSelection} selection Selection to which to add hits. 3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @return {boolean} true if a slice was found, otherwise false. 3252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 3262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis addIntersectingItemsToSelection: function(vX, vY, selection) { 3272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Does nothing. There's nothing interesting to pick on the viewport 3282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // track. 3292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 3302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 3322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Adds items intersecting the given range to a selection. 3332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} loVX Lower X bound of the interval to search, in 3342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * viewspace. 3352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} hiVX Upper X bound of the interval to search, in 3362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * viewspace. 3372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} loVY Lower Y bound of the interval to search, in 3382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * viewspace. 3392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {number} hiVY Upper Y bound of the interval to search, in 3402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * viewspace. 3412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {TimelineSelection} selection Selection to which to add hits. 3422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 3432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis addIntersectingItemsInRangeToSelection: function( 3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis loVX, hiVX, loY, hiY, selection) { 3452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Does nothing. There's nothing interesting to pick on the viewport 3462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // track. 3472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 3482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis addAllObjectsMatchingFilterToSelection: function(filter, selection) { 3502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 3522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return { 3542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis TimelineViewportTrack: TimelineViewportTrack 3552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 3562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis}); 357