1// Copyright (c) 2013 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('tracing.tracks.drawing_container'); 8 9base.require('base.raf'); 10base.require('tracing.tracks.track'); 11base.require('ui'); 12 13base.exportTo('tracing.tracks', function() { 14 var DrawType = { 15 SLICE: 1, 16 INSTANT_EVENT: 2 17 }; 18 19 var DrawingContainer = ui.define('drawing-container', tracing.tracks.Track); 20 21 DrawingContainer.prototype = { 22 __proto__: tracing.tracks.Track.prototype, 23 24 decorate: function(viewport) { 25 tracing.tracks.Track.prototype.decorate.call(this, viewport); 26 this.classList.add('drawing-container'); 27 28 this.canvas_ = document.createElement('canvas'); 29 this.canvas_.className = 'drawing-container-canvas'; 30 this.canvas_.style.left = tracing.constants.HEADING_WIDTH + 'px'; 31 this.appendChild(this.canvas_); 32 33 this.ctx_ = this.canvas_.getContext('2d'); 34 35 this.viewportChange_ = this.viewportChange_.bind(this); 36 this.viewport.addEventListener('change', this.viewportChange_); 37 }, 38 39 // Needed to support the calls in TimelineTrackView. 40 get canvas() { 41 return this.canvas_; 42 }, 43 44 context: function() { 45 return this.ctx_; 46 }, 47 48 viewportChange_: function() { 49 this.invalidate(); 50 }, 51 52 invalidate: function() { 53 if (this.rafPending_) 54 return; 55 this.rafPending_ = true; 56 57 base.requestPreAnimationFrame(function() { 58 this.rafPending_ = false; 59 this.ctx_.clearRect(0, 0, this.canvas_.width, this.canvas_.height); 60 this.updateCanvasSizeIfNeeded_(); 61 62 base.requestAnimationFrameInThisFrameIfPossible(function() { 63 for (var i = 0; i < this.children.length; ++i) { 64 if (!(this.children[i] instanceof tracing.tracks.Track)) 65 continue; 66 this.children[i].drawTrack(DrawType.INSTANT_EVENT); 67 } 68 69 for (var i = 0; i < this.children.length; ++i) { 70 if (!(this.children[i] instanceof tracing.tracks.Track)) 71 continue; 72 this.children[i].drawTrack(DrawType.SLICE); 73 } 74 75 var pixelRatio = window.devicePixelRatio || 1; 76 var bounds = this.canvas_.getBoundingClientRect(); 77 var viewLWorld = this.viewport.xViewToWorld(0); 78 var viewRWorld = this.viewport.xViewToWorld( 79 bounds.width * pixelRatio); 80 81 this.viewport.drawGridLines(this.ctx_, viewLWorld, viewRWorld); 82 this.viewport.drawMarkerLines(this.ctx_, viewLWorld, viewRWorld); 83 }, this); 84 }, this); 85 }, 86 87 updateCanvasSizeIfNeeded_: function() { 88 var visibleChildTracks = 89 base.asArray(this.children).filter(this.visibleFilter_); 90 91 var thisBounds = this.getBoundingClientRect(); 92 93 var firstChildTrackBounds = visibleChildTracks[0].getBoundingClientRect(); 94 var lastChildTrackBounds = 95 visibleChildTracks[visibleChildTracks.length - 1]. 96 getBoundingClientRect(); 97 98 var innerWidth = firstChildTrackBounds.width - 99 tracing.constants.HEADING_WIDTH; 100 var innerHeight = lastChildTrackBounds.bottom - firstChildTrackBounds.top; 101 102 var pixelRatio = window.devicePixelRatio || 1; 103 if (this.canvas_.width != innerWidth * pixelRatio) { 104 this.canvas_.width = innerWidth * pixelRatio; 105 this.canvas_.style.width = innerWidth + 'px'; 106 } 107 108 if (this.canvas_.height != innerHeight * pixelRatio) { 109 this.canvas_.height = innerHeight * pixelRatio; 110 this.canvas_.style.height = innerHeight + 'px'; 111 } 112 113 var canvasTop = 114 firstChildTrackBounds.top - thisBounds.top + this.scrollTop; 115 if (this.canvas_.style.top + 'px' !== canvasTop) 116 this.canvas_.style.top = canvasTop + 'px'; 117 }, 118 119 visibleFilter_: function(element) { 120 if (!(element instanceof tracing.tracks.Track)) 121 return false; 122 return window.getComputedStyle(element).display !== 'none'; 123 } 124 }; 125 126 return { 127 DrawingContainer: DrawingContainer, 128 DrawType: DrawType 129 }; 130}); 131