1<!DOCTYPE html> 2<!-- 3Copyright (c) 2013 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="stylesheet" href="/tracing/ui/tracks/drawing_container.css"> 9 10<link rel="import" href="/tracing/base/raf.html"> 11<link rel="import" href="/tracing/ui/tracks/track.html"> 12<link rel="import" href="/tracing/ui/base/constants.html"> 13<link rel="import" href="/tracing/ui/base/ui.html"> 14 15<script> 16'use strict'; 17 18tr.exportTo('tr.ui.tracks', function() { 19 var DrawType = { 20 GENERAL_EVENT: 1, 21 INSTANT_EVENT: 2, 22 BACKGROUND: 3, 23 GRID: 4, 24 FLOW_ARROWS: 5, 25 MARKERS: 6, 26 HIGHLIGHTS: 7, 27 ANNOTATIONS: 8 28 }; 29 30 var DrawingContainer = tr.ui.b.define('drawing-container', 31 tr.ui.tracks.Track); 32 33 DrawingContainer.prototype = { 34 __proto__: tr.ui.tracks.Track.prototype, 35 36 decorate: function(viewport) { 37 tr.ui.tracks.Track.prototype.decorate.call(this, viewport); 38 this.classList.add('drawing-container'); 39 40 this.canvas_ = document.createElement('canvas'); 41 this.canvas_.className = 'drawing-container-canvas'; 42 this.canvas_.style.left = tr.ui.b.constants.HEADING_WIDTH + 'px'; 43 this.appendChild(this.canvas_); 44 45 this.ctx_ = this.canvas_.getContext('2d'); 46 47 this.viewportChange_ = this.viewportChange_.bind(this); 48 this.viewport.addEventListener('change', this.viewportChange_); 49 }, 50 51 // Needed to support the calls in TimelineTrackView. 52 get canvas() { 53 return this.canvas_; 54 }, 55 56 context: function() { 57 return this.ctx_; 58 }, 59 60 viewportChange_: function() { 61 this.invalidate(); 62 }, 63 64 invalidate: function() { 65 if (this.rafPending_) 66 return; 67 this.rafPending_ = true; 68 69 tr.b.requestPreAnimationFrame(this.preDraw_, this); 70 }, 71 72 preDraw_: function() { 73 this.rafPending_ = false; 74 this.updateCanvasSizeIfNeeded_(); 75 76 tr.b.requestAnimationFrameInThisFrameIfPossible(this.draw_, this); 77 }, 78 79 draw_: function() { 80 this.ctx_.clearRect(0, 0, this.canvas_.width, this.canvas_.height); 81 82 var typesToDraw = [ 83 DrawType.BACKGROUND, 84 DrawType.HIGHLIGHTS, 85 DrawType.GRID, 86 DrawType.INSTANT_EVENT, 87 DrawType.GENERAL_EVENT, 88 DrawType.MARKERS, 89 DrawType.ANNOTATIONS, 90 DrawType.FLOW_ARROWS 91 ]; 92 93 for (var idx in typesToDraw) { 94 for (var i = 0; i < this.children.length; ++i) { 95 if (!(this.children[i] instanceof tr.ui.tracks.Track)) 96 continue; 97 this.children[i].drawTrack(typesToDraw[idx]); 98 } 99 } 100 101 var pixelRatio = window.devicePixelRatio || 1; 102 var bounds = this.canvas_.getBoundingClientRect(); 103 var dt = this.viewport.currentDisplayTransform; 104 var viewLWorld = dt.xViewToWorld(0); 105 var viewRWorld = dt.xViewToWorld( 106 bounds.width * pixelRatio); 107 108 this.viewport.drawGridLines(this.ctx_, viewLWorld, viewRWorld); 109 }, 110 111 updateCanvasSizeIfNeeded_: function() { 112 var visibleChildTracks = 113 tr.b.asArray(this.children).filter(this.visibleFilter_); 114 115 var thisBounds = this.getBoundingClientRect(); 116 117 var firstChildTrackBounds = visibleChildTracks[0].getBoundingClientRect(); 118 var lastChildTrackBounds = 119 visibleChildTracks[visibleChildTracks.length - 1]. 120 getBoundingClientRect(); 121 122 var innerWidth = firstChildTrackBounds.width - 123 tr.ui.b.constants.HEADING_WIDTH; 124 var innerHeight = lastChildTrackBounds.bottom - firstChildTrackBounds.top; 125 126 var pixelRatio = window.devicePixelRatio || 1; 127 if (this.canvas_.width != innerWidth * pixelRatio) { 128 this.canvas_.width = innerWidth * pixelRatio; 129 this.canvas_.style.width = innerWidth + 'px'; 130 } 131 132 if (this.canvas_.height != innerHeight * pixelRatio) { 133 this.canvas_.height = innerHeight * pixelRatio; 134 this.canvas_.style.height = innerHeight + 'px'; 135 } 136 }, 137 138 visibleFilter_: function(element) { 139 if (!(element instanceof tr.ui.tracks.Track)) 140 return false; 141 return window.getComputedStyle(element).display !== 'none'; 142 }, 143 144 addClosestEventToSelection: function( 145 worldX, worldMaxDist, loY, hiY, selection) { 146 for (var i = 0; i < this.children.length; ++i) { 147 if (!(this.children[i] instanceof tr.ui.tracks.Track)) 148 continue; 149 var trackClientRect = this.children[i].getBoundingClientRect(); 150 var a = Math.max(loY, trackClientRect.top); 151 var b = Math.min(hiY, trackClientRect.bottom); 152 if (a <= b) { 153 this.children[i].addClosestEventToSelection( 154 worldX, worldMaxDist, loY, hiY, selection); 155 } 156 } 157 158 tr.ui.tracks.Track.prototype.addClosestEventToSelection. 159 apply(this, arguments); 160 }, 161 162 addEventsToTrackMap: function(eventToTrackMap) { 163 for (var i = 0; i < this.children.length; ++i) { 164 if (!(this.children[i] instanceof tr.ui.tracks.Track)) 165 continue; 166 this.children[i].addEventsToTrackMap(eventToTrackMap); 167 } 168 } 169 }; 170 171 return { 172 DrawingContainer: DrawingContainer, 173 DrawType: DrawType 174 }; 175}); 176</script> 177