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 Gennis/** 82da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @fileoverview Interactive visualizaiton of TimelineModel objects 92da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * based loosely on gantt charts. Each thread in the TimelineModel is given a 102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * set of TimelineTracks, one per subrow in the thread. The Timeline class 112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * acts as a controller, creating the individual tracks, while TimelineTracks 122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * do actual drawing. 132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * 142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Visually, the Timeline produces (prettier) visualizations like the following: 152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Thread1: AAAAAAAAAA AAAAA 162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * BBBB BB 172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Thread2: CCCCCC CCCCC 182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * 192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 202da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.requireStylesheet('timeline'); 212da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('event_target'); 222da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('measuring_stick'); 232da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('timeline_filter'); 242da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('timeline_selection'); 252da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('timeline_viewport'); 262da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('tracks.timeline_model_track'); 272da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('tracks.timeline_viewport_track'); 282da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.require('ui'); 292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 302da489cd246702bee5938545b18a6f710ed214bcJamie Gennisbase.exportTo('tracing', function() { 312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var TimelineSelection = tracing.TimelineSelection; 332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var TimelineViewport = tracing.TimelineViewport; 342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis function intersectRect_(r1, r2) { 362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var results = new Object; 372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (r2.left > r1.right || r2.right < r1.left || 382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis r2.top > r1.bottom || r2.bottom < r1.top) { 392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis results.left = Math.max(r1.left, r2.left); 422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis results.top = Math.max(r1.top, r2.top); 432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis results.right = Math.min(r1.right, r2.right); 442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis results.bottom = Math.min(r1.bottom, r2.bottom); 452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis results.width = (results.right - results.left); 462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis results.height = (results.bottom - results.top); 472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return results; 482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Renders a TimelineModel into a div element, making one 522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * TimelineTrack for each subrow in each thread of the model, managing 532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * overall track layout, and handling user interaction with the 542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * viewport. 552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * 562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @constructor 572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @extends {HTMLDivElement} 582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var Timeline = base.ui.define('div'); 602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Timeline.prototype = { 622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis __proto__: HTMLDivElement.prototype, 632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis model_: null, 652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis decorate: function() { 672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.classList.add('timeline'); 682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.categoryFilter_ = new tracing.TimelineCategoryFilter(); 702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_ = new TimelineViewport(this); 722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Add the viewport track. 742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewportTrack_ = new tracks.TimelineViewportTrack(); 752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewportTrack_.viewport = this.viewport_; 762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.appendChild(this.viewportTrack_); 772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrackContainer_ = document.createElement('div'); 792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrackContainer_.className = 'timeline-model-track-container'; 802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.appendChild(this.modelTrackContainer_); 812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrack_ = new tracks.TimelineModelTrack(); 832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrackContainer_.appendChild(this.modelTrack_); 842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_ = this.ownerDocument.createElement('div'); 862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.className = 'timeline-drag-box'; 872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.appendChild(this.dragBox_); 882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.hideDragBox_(); 892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.bindEventListener_(document, 'keypress', this.onKeypress_, this); 912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.bindEventListener_(document, 'keydown', this.onKeydown_, this); 922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.bindEventListener_(document, 'keyup', this.onKeyup_, this); 932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.bindEventListener_(document, 'mousemove', this.onMouseMove_, this); 942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.bindEventListener_(document, 'mouseup', this.onMouseUp_, this); 952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.addEventListener('mousewheel', this.onMouseWheel_); 972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.addEventListener('mousedown', this.onMouseDown_); 982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.addEventListener('dblclick', this.onDblClick_); 992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.lastMouseViewPos_ = {x: 0, y: 0}; 1012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.maxHeadingWidth_ = 0; 1022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.selection_ = new TimelineSelection(); 1042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 1072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Wraps the standard addEventListener but automatically binds the provided 1082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * func to the provided target, tracking the resulting closure. When detach 1092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * is called, these listeners will be automatically removed. 1102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 1112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis bindEventListener_: function(object, event, func, target) { 1122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.boundListeners_) 1132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.boundListeners_ = []; 1142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var boundFunc = func.bind(target); 1152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.boundListeners_.push({object: object, 1162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis event: event, 1172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis boundFunc: boundFunc}); 1182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis object.addEventListener(event, boundFunc); 1192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis detach: function() { 1222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrack_.detach(); 1232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (var i = 0; i < this.boundListeners_.length; i++) { 1252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var binding = this.boundListeners_[i]; 1262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis binding.object.removeEventListener(binding.event, binding.boundFunc); 1272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 1282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.boundListeners_ = undefined; 1292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.detach(); 1302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get viewport() { 1332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.viewport_; 1342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get categoryFilter() { 1372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.categoryFilter_; 1382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis set categoryFilter(filter) { 1412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.categoryFilter_ = filter; 1422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrack_.categoryFilter = filter; 1432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get model() { 1462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.model_; 1472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis set model(model) { 1502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!model) 1512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis throw new Error('Model cannot be null'); 1522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var modelInstanceChanged = this.model_ != model; 1542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.model_ = model; 1552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrack_.model = model; 1562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrack_.viewport = this.viewport_; 1572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrack_.categoryFilter = this.categoryFilter; 1582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewportTrack_.headingWidth = this.modelTrack_.headingWidth; 1592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Set up a reasonable viewport. 1612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (modelInstanceChanged) 1622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.setWhenPossible(this.setInitialViewport_.bind(this)); 1632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get numVisibleTracks() { 1662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.modelTrack_.numVisibleTracks; 1672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis setInitialViewport_: function() { 1702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var w = this.firstCanvas.width; 1712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var boost = 1722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis (this.model_.maxTimestamp - this.model_.minTimestamp) * 0.15; 1732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.xSetWorldRange(this.model_.minTimestamp - boost, 1742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.model_.maxTimestamp + boost, 1752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis w); 1762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 1792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {TimelineFilter} filter The filter to use for finding matches. 1802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {TimelineSelection} selection The selection to add matches to. 1812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @return {Array} An array of objects that match the provided 1822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * TimelineTitleFilter. 1832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 1842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis addAllObjectsMatchingFilterToSelection: function(filter, selection) { 1852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrack_.addAllObjectsMatchingFilterToSelection(filter, 1862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis selection); 1872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 1892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 1902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @return {Element} The element whose focused state determines 1912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * whether to respond to keyboard inputs. 1922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Defaults to the parent element. 1932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 1942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get focusElement() { 1952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.focusElement_) 1962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.focusElement_; 1972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.parentElement; 1982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 1992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 2012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Sets the element whose focus state will determine whether 2022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * to respond to keybaord input. 2032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 2042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis set focusElement(value) { 2052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.focusElement_ = value; 2062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 2072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get listenToKeys_() { 2092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.viewport_.isAttachedToDocument_) 2102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 2112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.activeElement instanceof tracing.TimelineFindControl) 2122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 2132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.focusElement_) 2142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return true; 2152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.focusElement.tabIndex >= 0) 2162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return document.activeElement == this.focusElement; 2172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return true; 2182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 2192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onKeypress_: function(e) { 2212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var vp = this.viewport_; 2222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.firstCanvas) 2232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 2242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.listenToKeys_) 2252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 2262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (document.activeElement.nodeName == 'INPUT') 2272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 2282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var viewWidth = this.firstCanvas.clientWidth; 2292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var curMouseV, curCenterW; 2302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis switch (e.keyCode) { 2312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 119: // w 2322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 44: // , 2332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.zoomBy_(1.5); 2342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 115: // s 2362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 111: // o 2372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.zoomBy_(1 / 1.5); 2382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 103: // g 2402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.onGridToggle_(true); 2412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 71: // G 2432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.onGridToggle_(false); 2442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 87: // W 2462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 60: // < 2472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.zoomBy_(10); 2482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 83: // S 2502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 79: // O 2512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.zoomBy_(1 / 10); 2522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 97: // a 2542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.panX += vp.xViewVectorToWorld(viewWidth * 0.1); 2552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 100: // d 2572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 101: // e 2582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.panX -= vp.xViewVectorToWorld(viewWidth * 0.1); 2592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 65: // A 2612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.panX += vp.xViewVectorToWorld(viewWidth * 0.5); 2622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 68: // D 2642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.panX -= vp.xViewVectorToWorld(viewWidth * 0.5); 2652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 48: // 0 2672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 122: // z 2682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.setInitialViewport_(); 2692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 102: // f 2712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.zoomToSelection_(); 2722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 2732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 2752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onMouseWheel_: function(e) { 2772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (e.altKey) { 2782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var delta = e.wheelDeltaY / 120; 2792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var zoomScale = Math.pow(1.5, delta); 2802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.zoomBy_(zoomScale); 2812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.preventDefault(); 2822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 2832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 2842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 2852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Not all keys send a keypress. 2862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onKeydown_: function(e) { 2872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.listenToKeys_) 2882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 2892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var sel; 2902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var vp = this.viewport_; 2912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var viewWidth = this.firstCanvas.clientWidth; 2922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis switch (e.keyCode) { 2932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 37: // left arrow 2942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sel = this.selection.getShiftedSelection(-1); 2952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (sel) { 2962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.setSelectionAndMakeVisible(sel); 2972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.preventDefault(); 2982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 2992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.firstCanvas) 3002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 3012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.panX += vp.xViewVectorToWorld(viewWidth * 0.1); 3022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 3042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 39: // right arrow 3052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis sel = this.selection.getShiftedSelection(1); 3062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (sel) { 3072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.setSelectionAndMakeVisible(sel); 3082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.preventDefault(); 3092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 3102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.firstCanvas) 3112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 3122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.panX -= vp.xViewVectorToWorld(viewWidth * 0.1); 3132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 3152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis case 9: // TAB 3162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.focusElement.tabIndex == -1) { 3172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (e.shiftKey) 3182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.selectPrevious_(e); 3192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis else 3202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.selectNext_(e); 3212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.preventDefault(); 3222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis break; 3242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (e.shiftKey && this.dragBeginEvent_) { 3262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var vertical = e.shiftKey; 3272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.dragBeginEvent_) { 3282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.setDragBoxPosition_(this.dragBoxXStart_, this.dragBoxYStart_, 3292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBoxXEnd_, this.dragBoxYEnd_, vertical); 3302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 3332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onKeyup_: function(e) { 3352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.listenToKeys_) 3362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 3372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!e.shiftKey) { 3382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.dragBeginEvent_) { 3392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var vertical = e.shiftKey; 3402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.setDragBoxPosition_(this.dragBoxXStart_, this.dragBoxYStart_, 3412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBoxXEnd_, this.dragBoxYEnd_, vertical); 3422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 3442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 3452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 3472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Zoom in or out on the timeline by the given scale factor. 3482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @param {integer} scale The scale factor to apply. If <1, zooms out. 3492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 3502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zoomBy_: function(scale) { 3512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.firstCanvas) 3522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 3532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var vp = this.viewport_; 3542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var viewWidth = this.firstCanvas.clientWidth; 3552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var curMouseV = this.lastMouseViewPos_.x; 3562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var curCenterW = vp.xViewToWorld(curMouseV); 3572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.scaleX = vp.scaleX * scale; 3582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis vp.xPanWorldPosToViewPos(curCenterW, curMouseV, viewWidth); 3592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 3602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 3622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * Zoom into the current selection. 3632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 3642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis zoomToSelection_: function() { 3652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.selection) 3662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 3672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var range = this.selection.range; 3682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var worldCenter = range.min + (range.max - range.min) * 0.5; 3692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var worldRange = (range.max - range.min) * 0.5; 3702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var boost = worldRange * 0.15; 3712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.xSetWorldRange(worldCenter - worldRange - boost, 3722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis worldCenter + worldRange + boost, 3732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.firstCanvas.width); 3742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 3752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get keyHelp() { 3772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var mod = navigator.platform.indexOf('Mac') == 0 ? 'cmd' : 'ctrl'; 3782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var help = 'Qwerty Controls\n' + 3792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' w/s : Zoom in/out (with shift: go faster)\n' + 3802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' a/d : Pan left/right\n\n' + 3812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'Dvorak Controls\n' + 3822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' ,/o : Zoom in/out (with shift: go faster)\n' + 3832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' a/e : Pan left/right\n\n' + 3842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'Mouse Controls\n' + 3852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' drag : Select slices (with ' + mod + 3862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ': zoom to slices)\n' + 3872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' drag + shift : Select all slices vertically\n\n'; 3882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 3892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.focusElement.tabIndex) { 3902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis help += 3912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' <- : Select previous event on current timeline\n' + 3922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' -> : Select next event on current timeline\n'; 3932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 3942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis help += 'General Navigation\n' + 3952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' g/General : Shows grid at the start/end of the selected' + 3962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' task\n' + 3972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' <-,^TAB : Select previous event on current timeline\n' + 3982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis ' ->, TAB : Select next event on current timeline\n'; 3992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis help += 4012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis '\n' + 4022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'Alt + Scroll to zoom in/out\n' + 4032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'Dbl-click to zoom in; Shift dbl-click to zoom out\n' + 4042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'f to zoom into selection\n' + 4052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 'z to reset zoom and pan to initial view\n'; 4062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return help; 4072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 4082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get selection() { 4102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.selection_; 4112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 4122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis set selection(selection) { 4142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!(selection instanceof TimelineSelection)) 4152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis throw new Error('Expected TimelineSelection'); 4162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Clear old selection. 4182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var i; 4192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (i = 0; i < this.selection_.length; i++) 4202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.selection_[i].selected = false; 4212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.selection_ = selection; 4232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis base.dispatchSimpleEvent(this, 'selectionChange'); 4252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis for (i = 0; i < this.selection_.length; i++) 4262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.selection_[i].selected = true; 4272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.dispatchChangeEvent(); // Triggers a redraw. 4282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 4292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis setSelectionAndMakeVisible: function(selection, zoomAllowed) { 4312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!(selection instanceof TimelineSelection)) 4322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis throw new Error('Expected TimelineSelection'); 4332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.selection = selection; 4342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var range = this.selection.range; 4352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var size = this.viewport_.xWorldVectorToView(range.max - range.min); 4362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (zoomAllowed && size < 50) { 4372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var worldCenter = range.min + (range.max - range.min) * 0.5; 4382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var worldRange = (range.max - range.min) * 5; 4392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.xSetWorldRange(worldCenter - worldRange * 0.5, 4402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis worldCenter + worldRange * 0.5, 4412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.firstCanvas.width); 4422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 4432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.xPanWorldRangeIntoView(range.min, range.max, 4462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.firstCanvas.width); 4472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 4482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis get firstCanvas() { 4502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.viewportTrack_) 4512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.viewportTrack_.firstCanvas; 4522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.modelTrack_) 4532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return this.modelTrack_.firstCanvas; 4542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return undefined; 4552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 4562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis hideDragBox_: function() { 4582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.style.left = '-1000px'; 4592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.style.top = '-1000px'; 4602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.style.width = 0; 4612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.style.height = 0; 4622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 4632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis setDragBoxPosition_: function(xStart, yStart, xEnd, yEnd, vertical) { 4652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var loY; 4662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hiY; 4672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var loX = Math.min(xStart, xEnd); 4682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hiX = Math.max(xStart, xEnd); 4692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var modelTrackRect = this.modelTrack_.getBoundingClientRect(); 4702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (vertical) { 4722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis loY = modelTrackRect.top; 4732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis hiY = modelTrackRect.bottom; 4742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 4752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis loY = Math.min(yStart, yEnd); 4762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis hiY = Math.max(yStart, yEnd); 4772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 4782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var dragRect = {left: loX, top: loY, width: hiX - loX, height: hiY - loY}; 4802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis dragRect.right = dragRect.left + dragRect.width; 4812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis dragRect.bottom = dragRect.top + dragRect.height; 4822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var modelTrackContainerRect = 4832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrackContainer_.getBoundingClientRect(); 4842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var clipRect = { 4852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis left: modelTrackContainerRect.left, 4862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis top: modelTrackContainerRect.top, 4872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis right: modelTrackContainerRect.right, 4882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis bottom: modelTrackContainerRect.bottom, 4892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 4902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var trackTitleWidth = parseInt(this.modelTrack_.headingWidth); 4912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis clipRect.left = clipRect.left + trackTitleWidth; 4922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var finalDragBox = intersectRect_(clipRect, dragRect); 4942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 4952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.style.left = finalDragBox.left + 'px'; 4962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.style.width = finalDragBox.width + 'px'; 4972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.style.top = finalDragBox.top + 'px'; 4982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.style.height = finalDragBox.height + 'px'; 4992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canv = this.firstCanvas; 5012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var loWX = this.viewport_.xViewToWorld(loX - canv.offsetLeft); 5022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hiWX = this.viewport_.xViewToWorld(hiX - canv.offsetLeft); 5032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var roundedDuration = Math.round((hiWX - loWX) * 100) / 100; 5052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBox_.textContent = roundedDuration + 'ms'; 5062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var e = new base.Event('selectionChanging'); 5082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.loWX = loWX; 5092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.hiWX = hiWX; 5102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dispatchEvent(e); 5112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 5122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onGridToggle_: function(left) { 5142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var tb; 5152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (left) 5162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tb = this.selection_.range.min; 5172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis else 5182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis tb = this.selection_.range.max; 5192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Shift the timebase left until its just left of minTimestamp. 5212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var numInterfvalsSinceStart = Math.ceil((tb - this.model_.minTimestamp) / 5222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.gridStep_); 5232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.gridTimebase = tb - 5242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis (numInterfvalsSinceStart + 1) * this.viewport_.gridStep_; 5252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewport_.gridEnabled = true; 5262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 5272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis isChildOfThis_: function(el) { 5292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (el == this) 5302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 5312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var isChildOfThis = false; 5332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var cur = el; 5342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis while (cur.parentNode) { 5352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (cur == this) 5362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return true; 5372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis cur = cur.parentNode; 5382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 5392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return false; 5402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 5412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onMouseDown_: function(e) { 5432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (e.button !== 0) 5442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 5452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (e.shiftKey) { 5472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.viewportTrack_.placeAndBeginDraggingMarker(e.clientX); 5482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 5492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 5502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canv = this.firstCanvas; 5522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var rect = this.modelTrack_.getBoundingClientRect(); 5532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canvRect = this.firstCanvas.getBoundingClientRect(); 5542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var inside = rect && 5562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.clientX >= rect.left && 5572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.clientX < rect.right && 5582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.clientY >= rect.top && 5592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.clientY < rect.bottom && 5602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.clientX >= canvRect.left && 5612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.clientX < canvRect.right; 5622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!inside) 5642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 5652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var pos = { 5672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis x: e.clientX - canv.offsetLeft, 5682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis y: e.clientY - canv.offsetTop 5692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 5702da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5712da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var wX = this.viewport_.xViewToWorld(pos.x); 5722da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5732da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBeginEvent_ = e; 5742da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.preventDefault(); 5752da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (document.activeElement) 5762da489cd246702bee5938545b18a6f710ed214bcJamie Gennis document.activeElement.blur(); 5772da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.focusElement.tabIndex >= 0) 5782da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.focusElement.focus(); 5792da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 5802da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5812da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onMouseMove_: function(e) { 5822da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (!this.firstCanvas) 5832da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return; 5842da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canv = this.firstCanvas; 5852da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var pos = { 5862da489cd246702bee5938545b18a6f710ed214bcJamie Gennis x: e.clientX - canv.offsetLeft, 5872da489cd246702bee5938545b18a6f710ed214bcJamie Gennis y: e.clientY - canv.offsetTop 5882da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 5892da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5902da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Remember position. Used during keyboard zooming. 5912da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.lastMouseViewPos_ = pos; 5922da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 5932da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Update the drag box 5942da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.dragBeginEvent_) { 5952da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBoxXStart_ = this.dragBeginEvent_.clientX; 5962da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBoxXEnd_ = e.clientX; 5972da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBoxYStart_ = this.dragBeginEvent_.clientY; 5982da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBoxYEnd_ = e.clientY; 5992da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var vertical = e.shiftKey; 6002da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.setDragBoxPosition_(this.dragBoxXStart_, this.dragBoxYStart_, 6012da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBoxXEnd_, this.dragBoxYEnd_, vertical); 6022da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 6032da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 6042da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6052da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onMouseUp_: function(e) { 6062da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var i; 6072da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (this.dragBeginEvent_) { 6082da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Stop the dragging. 6092da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.hideDragBox_(); 6102da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var eDown = this.dragBeginEvent_; 6112da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.dragBeginEvent_ = null; 6122da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6132da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Figure out extents of the drag. 6142da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var loY; 6152da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hiY; 6162da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var loX = Math.min(eDown.clientX, e.clientX); 6172da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hiX = Math.max(eDown.clientX, e.clientX); 6182da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var tracksContainer = this.modelTrackContainer_.getBoundingClientRect(); 6192da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var topBoundary = tracksContainer.height; 6202da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var vertical = e.shiftKey; 6212da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (vertical) { 6222da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var modelTrackRect = this.modelTrack_.getBoundingClientRect(); 6232da489cd246702bee5938545b18a6f710ed214bcJamie Gennis loY = modelTrackRect.top; 6242da489cd246702bee5938545b18a6f710ed214bcJamie Gennis hiY = modelTrackRect.bottom; 6252da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } else { 6262da489cd246702bee5938545b18a6f710ed214bcJamie Gennis loY = Math.min(eDown.clientY, e.clientY); 6272da489cd246702bee5938545b18a6f710ed214bcJamie Gennis hiY = Math.max(eDown.clientY, e.clientY); 6282da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 6292da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6302da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Convert to worldspace. 6312da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canv = this.firstCanvas; 6322da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var loVX = loX - canv.offsetLeft; 6332da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var hiVX = hiX - canv.offsetLeft; 6342da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6352da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Figure out what has been hit. 6362da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var selection = new TimelineSelection(); 6372da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.modelTrack_.addIntersectingItemsInRangeToSelection( 6382da489cd246702bee5938545b18a6f710ed214bcJamie Gennis loVX, hiVX, loY, hiY, selection); 6392da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6402da489cd246702bee5938545b18a6f710ed214bcJamie Gennis // Activate the new selection, and zoom if ctrl key held down. 6412da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.selection = selection; 6422da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var isMac = navigator.platform.indexOf('Mac') == 0; 6432da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if ((isMac && e.metaKey) || (!isMac && e.ctrlKey)) { 6442da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.zoomToSelection_(); 6452da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 6462da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 6472da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }, 6482da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6492da489cd246702bee5938545b18a6f710ed214bcJamie Gennis onDblClick_: function(e) { 6502da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var canv = this.firstCanvas; 6512da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6522da489cd246702bee5938545b18a6f710ed214bcJamie Gennis var scale = 4; 6532da489cd246702bee5938545b18a6f710ed214bcJamie Gennis if (e.shiftKey) 6542da489cd246702bee5938545b18a6f710ed214bcJamie Gennis scale = 1 / scale; 6552da489cd246702bee5938545b18a6f710ed214bcJamie Gennis this.zoomBy_(scale); 6562da489cd246702bee5938545b18a6f710ed214bcJamie Gennis e.preventDefault(); 6572da489cd246702bee5938545b18a6f710ed214bcJamie Gennis } 6582da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 6592da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6602da489cd246702bee5938545b18a6f710ed214bcJamie Gennis /** 6612da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * The TimelineModel being viewed by the timeline 6622da489cd246702bee5938545b18a6f710ed214bcJamie Gennis * @type {TimelineModel} 6632da489cd246702bee5938545b18a6f710ed214bcJamie Gennis */ 6642da489cd246702bee5938545b18a6f710ed214bcJamie Gennis base.defineProperty(Timeline, 'model', base.PropertyKind.JS); 6652da489cd246702bee5938545b18a6f710ed214bcJamie Gennis 6662da489cd246702bee5938545b18a6f710ed214bcJamie Gennis return { 6672da489cd246702bee5938545b18a6f710ed214bcJamie Gennis Timeline: Timeline 6682da489cd246702bee5938545b18a6f710ed214bcJamie Gennis }; 6692da489cd246702bee5938545b18a6f710ed214bcJamie Gennis}); 670