• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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