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 7base.requireStylesheet('tracks.canvas_based_track'); 8base.require('tracks.track'); 9base.require('fast_rect_renderer'); 10base.require('color_scheme'); 11base.require('ui'); 12 13base.exportTo('tracing.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 CanvasBasedTrack = 23 tracing.ui.define(tracing.tracks.Track); 24 25 CanvasBasedTrack.prototype = { 26 __proto__: tracing.tracks.Track.prototype, 27 28 decorate: function() { 29 this.className = 'canvas-based-track'; 30 this.slices_ = null; 31 32 this.headingDiv_ = document.createElement('div'); 33 this.headingDiv_.className = 'canvas-based-track-title'; 34 this.appendChild(this.headingDiv_); 35 36 this.canvasContainer_ = document.createElement('div'); 37 this.canvasContainer_.className = 38 'canvas-based-track-canvas-container'; 39 this.appendChild(this.canvasContainer_); 40 this.canvas_ = document.createElement('canvas'); 41 this.canvas_.className = 'canvas-based-track-canvas'; 42 this.canvasContainer_.appendChild(this.canvas_); 43 44 this.ctx_ = this.canvas_.getContext('2d'); 45 }, 46 47 detach: function() { 48 if (this.viewport_) { 49 this.viewport_.removeEventListener('change', 50 this.viewportChangeBoundToThis_); 51 this.viewport_.removeEventListener('markersChange', 52 this.viewportMarkersChangeBoundToThis_); 53 } 54 }, 55 56 set headingWidth(width) { 57 this.headingDiv_.style.width = width; 58 }, 59 60 get heading() { 61 return this.headingDiv_.textContent; 62 }, 63 64 set heading(text) { 65 this.headingDiv_.textContent = text; 66 }, 67 68 set tooltip(text) { 69 this.headingDiv_.title = text; 70 }, 71 72 get viewport() { 73 return this.viewport_; 74 }, 75 76 set viewport(v) { 77 this.viewport_ = v; 78 if (this.viewport_) { 79 this.viewport_.removeEventListener('change', 80 this.viewportChangeBoundToThis_); 81 this.viewport_.removeEventListener('markersChange', 82 this.viewportMarkersChangeBoundToThis_); 83 } 84 this.viewport_ = v; 85 if (this.viewport_) { 86 this.viewportChangeBoundToThis_ = this.viewportChange_.bind(this); 87 this.viewport_.addEventListener('change', 88 this.viewportChangeBoundToThis_); 89 this.viewportMarkersChangeBoundToThis_ = 90 this.viewportMarkersChange_.bind(this); 91 this.viewport_.addEventListener('markersChange', 92 this.viewportMarkersChangeBoundToThis_); 93 if (this.isAttachedToDocument_) 94 this.updateCanvasSizeIfNeeded_(); 95 } 96 this.invalidate(); 97 }, 98 99 viewportChange_: function() { 100 this.invalidate(); 101 }, 102 103 viewportMarkersChange_: function() { 104 if (this.viewport_.markers.length < 2) 105 this.classList.remove('ruler-track-with-distance-measurements'); 106 else 107 this.classList.add('ruler-track-with-distance-measurements'); 108 }, 109 110 invalidate: function() { 111 if (this.rafPending_) 112 return; 113 webkitRequestAnimationFrame(function() { 114 this.rafPending_ = false; 115 if (!this.viewport_) 116 return; 117 this.updateCanvasSizeIfNeeded_(); 118 this.redraw(); 119 }.bind(this), this); 120 this.rafPending_ = true; 121 }, 122 123 /** 124 * @return {boolean} Whether the current timeline is attached to the 125 * document. 126 */ 127 get isAttachedToDocument_() { 128 var cur = this.parentNode; 129 if (!cur) 130 return; 131 while (cur.parentNode) 132 cur = cur.parentNode; 133 return cur == this.ownerDocument; 134 }, 135 136 137 updateCanvasSizeIfNeeded_: function() { 138 var style = window.getComputedStyle(this.canvasContainer_); 139 var innerWidth = parseInt(style.width) - 140 parseInt(style.paddingLeft) - parseInt(style.paddingRight) - 141 parseInt(style.borderLeftWidth) - parseInt(style.borderRightWidth); 142 var innerHeight = parseInt(style.height) - 143 parseInt(style.paddingTop) - parseInt(style.paddingBottom) - 144 parseInt(style.borderTopWidth) - parseInt(style.borderBottomWidth); 145 var pixelRatio = window.devicePixelRatio || 1; 146 if (this.canvas_.width != innerWidth) { 147 this.canvas_.width = innerWidth * pixelRatio; 148 this.canvas_.style.width = innerWidth + 'px'; 149 } 150 if (this.canvas_.height != innerHeight) { 151 this.canvas_.height = innerHeight * pixelRatio; 152 this.canvas_.style.height = innerHeight + 'px'; 153 } 154 }, 155 get firstCanvas() { 156 return this.canvas_; 157 } 158 }; 159 160 return { 161 CanvasBasedTrack: CanvasBasedTrack 162 }; 163}); 164