1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 'use strict'; 6 7 base.requireStylesheet('tracks.timeline_canvas_based_track'); 8 base.require('tracks.timeline_track'); 9 base.require('fast_rect_renderer'); 10 base.require('timeline_color_scheme'); 11 base.require('ui'); 12 13 base.exportTo('tracks', function() { 14 15 /** 16 * A canvas-based track constructed. Provides the basic heading and 17 * invalidation-managment infrastructure. Subclasses must implement drawing 18 * and picking code. 19 * @constructor 20 * @extends {HTMLDivElement} 21 */ 22 var TimelineCanvasBasedTrack = base.ui.define(tracks.TimelineTrack); 23 24 TimelineCanvasBasedTrack.prototype = { 25 __proto__: tracks.TimelineTrack.prototype, 26 27 decorate: function() { 28 this.className = 'timeline-canvas-based-track'; 29 this.slices_ = null; 30 31 this.headingDiv_ = document.createElement('div'); 32 this.headingDiv_.className = 'timeline-canvas-based-track-title'; 33 this.appendChild(this.headingDiv_); 34 35 this.canvasContainer_ = document.createElement('div'); 36 this.canvasContainer_.className = 37 'timeline-canvas-based-track-canvas-container'; 38 this.appendChild(this.canvasContainer_); 39 this.canvas_ = document.createElement('canvas'); 40 this.canvas_.className = 'timeline-canvas-based-track-canvas'; 41 this.canvasContainer_.appendChild(this.canvas_); 42 43 this.ctx_ = this.canvas_.getContext('2d'); 44 }, 45 46 detach: function() { 47 if (this.viewport_) { 48 this.viewport_.removeEventListener('change', 49 this.viewportChangeBoundToThis_); 50 this.viewport_.removeEventListener('markersChange', 51 this.viewportMarkersChangeBoundToThis_); 52 } 53 }, 54 55 set headingWidth(width) { 56 this.headingDiv_.style.width = width; 57 }, 58 59 get heading() { 60 return this.headingDiv_.textContent; 61 }, 62 63 set heading(text) { 64 this.headingDiv_.textContent = text; 65 }, 66 67 set tooltip(text) { 68 this.headingDiv_.title = text; 69 }, 70 71 get viewport() { 72 return this.viewport_; 73 }, 74 75 set viewport(v) { 76 this.viewport_ = v; 77 if (this.viewport_) { 78 this.viewport_.removeEventListener('change', 79 this.viewportChangeBoundToThis_); 80 this.viewport_.removeEventListener('markersChange', 81 this.viewportMarkersChangeBoundToThis_); 82 } 83 this.viewport_ = v; 84 if (this.viewport_) { 85 this.viewportChangeBoundToThis_ = this.viewportChange_.bind(this); 86 this.viewport_.addEventListener('change', 87 this.viewportChangeBoundToThis_); 88 this.viewportMarkersChangeBoundToThis_ = 89 this.viewportMarkersChange_.bind(this); 90 this.viewport_.addEventListener('markersChange', 91 this.viewportMarkersChangeBoundToThis_); 92 if (this.isAttachedToDocument_) 93 this.updateCanvasSizeIfNeeded_(); 94 } 95 this.invalidate(); 96 }, 97 98 viewportChange_: function() { 99 this.invalidate(); 100 }, 101 102 viewportMarkersChange_: function() { 103 if (this.viewport_.markers.length < 2) 104 this.classList.remove('timeline-viewport-track-with' + 105 '-distance-measurements'); 106 else 107 this.classList.add('timeline-viewport-track-with' + 108 '-distance-measurements'); 109 }, 110 111 invalidate: function() { 112 if (this.rafPending_) 113 return; 114 webkitRequestAnimationFrame(function() { 115 this.rafPending_ = false; 116 if (!this.viewport_) 117 return; 118 this.updateCanvasSizeIfNeeded_(); 119 this.redraw(); 120 }.bind(this), this); 121 this.rafPending_ = true; 122 }, 123 124 /** 125 * @return {boolean} Whether the current timeline is attached to the 126 * document. 127 */ 128 get isAttachedToDocument_() { 129 var cur = this.parentNode; 130 if (!cur) 131 return; 132 while (cur.parentNode) 133 cur = cur.parentNode; 134 return cur == this.ownerDocument; 135 }, 136 137 138 updateCanvasSizeIfNeeded_: function() { 139 var style = window.getComputedStyle(this.canvasContainer_); 140 var innerWidth = parseInt(style.width) - 141 parseInt(style.paddingLeft) - parseInt(style.paddingRight) - 142 parseInt(style.borderLeftWidth) - parseInt(style.borderRightWidth); 143 var innerHeight = parseInt(style.height) - 144 parseInt(style.paddingTop) - parseInt(style.paddingBottom) - 145 parseInt(style.borderTopWidth) - parseInt(style.borderBottomWidth); 146 var pixelRatio = window.devicePixelRatio || 1; 147 if (this.canvas_.width != innerWidth) { 148 this.canvas_.width = innerWidth * pixelRatio; 149 this.canvas_.style.width = innerWidth + 'px'; 150 } 151 if (this.canvas_.height != innerHeight) { 152 this.canvas_.height = innerHeight * pixelRatio; 153 this.canvas_.style.height = innerHeight + 'px'; 154 } 155 }, 156 get firstCanvas() { 157 return this.canvas_; 158 } 159 }; 160 161 return { 162 TimelineCanvasBasedTrack: TimelineCanvasBasedTrack 163 }; 164 }); 165