Home | History | Annotate | Download | only in tracks
      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