Home | History | Annotate | Download | only in ui
      1 <!DOCTYPE html>
      2 <!--
      3 Copyright (c) 2014 The Chromium Authors. All rights reserved.
      4 Use of this source code is governed by a BSD-style license that can be
      5 found in the LICENSE file.
      6 -->
      7 
      8 <link rel="import" href="/base/range.html">
      9 
     10 <script>
     11 'use strict';
     12 
     13 tr.exportTo('tr.ui', function() {
     14   /**
     15    * @constructor
     16    */
     17   function SnapIndicator(y, height) {
     18     this.y = y;
     19     this.height = height;
     20   }
     21 
     22   /**
     23    * The interesting part of the world.
     24    *
     25    * @constructor
     26    */
     27   function TimelineInterestRange(vp) {
     28     this.viewport_ = vp;
     29 
     30     this.range_ = new tr.b.Range();
     31 
     32     this.leftSelected_ = false;
     33     this.rightSelected_ = false;
     34 
     35     this.leftSnapIndicator_ = undefined;
     36     this.rightSnapIndicator_ = undefined;
     37   }
     38 
     39   TimelineInterestRange.prototype = {
     40     get isEmpty() {
     41       return this.range_.isEmpty;
     42     },
     43 
     44     reset: function() {
     45       this.range_.reset();
     46       this.leftSelected_ = false;
     47       this.rightSelected_ = false;
     48       this.leftSnapIndicator_ = undefined;
     49       this.rightSnapIndicator_ = undefined;
     50       this.viewport_.dispatchChangeEvent();
     51     },
     52 
     53     get min() {
     54       return this.range_.min;
     55     },
     56 
     57     set min(min) {
     58       this.range_.min = min;
     59       this.viewport_.dispatchChangeEvent();
     60     },
     61 
     62     get max() {
     63       return this.range_.max;
     64     },
     65 
     66     set max(max) {
     67       this.range_.max = max;
     68       this.viewport_.dispatchChangeEvent();
     69     },
     70 
     71     set: function(range) {
     72       this.range_.reset();
     73       this.range_.addRange(range);
     74       this.viewport_.dispatchChangeEvent();
     75     },
     76 
     77     setMinAndMax: function(min, max) {
     78       this.range_.min = min;
     79       this.range_.max = max;
     80       this.viewport_.dispatchChangeEvent();
     81     },
     82 
     83     get range() {
     84       return this.range_.range;
     85     },
     86 
     87     asRangeObject: function() {
     88       var range = new tr.b.Range();
     89       range.addRange(this.range_);
     90       return range;
     91     },
     92 
     93     get leftSelected() {
     94       return this.leftSelected_;
     95     },
     96 
     97     set leftSelected(leftSelected) {
     98       if (this.leftSelected_ == leftSelected)
     99         return;
    100       this.leftSelected_ = leftSelected;
    101       this.viewport_.dispatchChangeEvent();
    102     },
    103 
    104     get rightSelected() {
    105       return this.rightSelected_;
    106     },
    107 
    108     set rightSelected(rightSelected) {
    109       if (this.rightSelected_ == rightSelected)
    110         return;
    111       this.rightSelected_ = rightSelected;
    112       this.viewport_.dispatchChangeEvent();
    113     },
    114 
    115     get leftSnapIndicator() {
    116       return this.leftSnapIndicator_;
    117     },
    118 
    119     set leftSnapIndicator(leftSnapIndicator) {
    120       this.leftSnapIndicator_ = leftSnapIndicator;
    121       this.viewport_.dispatchChangeEvent();
    122     },
    123 
    124     get rightSnapIndicator() {
    125       return this.rightSnapIndicator_;
    126     },
    127 
    128     set rightSnapIndicator(rightSnapIndicator) {
    129       this.rightSnapIndicator_ = rightSnapIndicator;
    130       this.viewport_.dispatchChangeEvent();
    131     },
    132 
    133     draw: function(ctx, viewLWorld, viewRWorld) {
    134       if (this.range_.isEmpty)
    135         return;
    136       var dt = this.viewport_.currentDisplayTransform;
    137 
    138       var markerLWorld = this.min;
    139       var markerRWorld = this.max;
    140 
    141       var markerLView = Math.round(dt.xWorldToView(markerLWorld));
    142       var markerRView = Math.round(dt.xWorldToView(markerRWorld));
    143 
    144       ctx.fillStyle = 'rgba(0, 0, 0, 0.2)';
    145       if (markerLWorld > viewLWorld) {
    146         ctx.fillRect(dt.xWorldToView(viewLWorld), 0,
    147             markerLView, ctx.canvas.height);
    148       }
    149 
    150       if (markerRWorld < viewRWorld) {
    151         ctx.fillRect(markerRView, 0,
    152             dt.xWorldToView(viewRWorld), ctx.canvas.height);
    153       }
    154 
    155       var pixelRatio = window.devicePixelRatio || 1;
    156       ctx.lineWidth = Math.round(pixelRatio);
    157       if (this.range_.range > 0) {
    158         this.drawLine_(ctx, viewLWorld, viewRWorld,
    159                        ctx.canvas.height, this.min, this.leftSelected_);
    160         this.drawLine_(ctx, viewLWorld, viewRWorld,
    161                        ctx.canvas.height, this.max, this.rightSelected_);
    162       } else {
    163         this.drawLine_(ctx, viewLWorld, viewRWorld,
    164                        ctx.canvas.height, this.min,
    165                        this.leftSelected_ || this.rightSelected_);
    166       }
    167       ctx.lineWidth = 1;
    168     },
    169 
    170     drawLine_: function(ctx, viewLWorld, viewRWorld, height, ts, selected) {
    171       if (ts < viewLWorld || ts >= viewRWorld)
    172         return;
    173 
    174       var dt = this.viewport_.currentDisplayTransform;
    175       var viewX = Math.round(dt.xWorldToView(ts));
    176 
    177       // Apply subpixel translate to get crisp lines.
    178       // http://www.mobtowers.com/html5-canvas-crisp-lines-every-time/
    179       ctx.save();
    180       ctx.translate((Math.round(ctx.lineWidth) % 2) / 2, 0);
    181 
    182       ctx.beginPath();
    183       tr.ui.b.drawLine(ctx, viewX, 0, viewX, height);
    184       if (selected)
    185         ctx.strokeStyle = 'rgb(255, 0, 0)';
    186       else
    187         ctx.strokeStyle = 'rgb(0, 0, 0)';
    188       ctx.stroke();
    189 
    190       ctx.restore();
    191     },
    192 
    193     drawIndicators: function(ctx, viewLWorld, viewRWorld) {
    194       if (this.leftSnapIndicator_) {
    195         this.drawIndicator_(ctx, viewLWorld, viewRWorld,
    196                             this.range_.min,
    197                             this.leftSnapIndicator_,
    198                             this.leftSelected_);
    199       }
    200       if (this.rightSnapIndicator_) {
    201         this.drawIndicator_(ctx, viewLWorld, viewRWorld,
    202                             this.range_.max,
    203                             this.rightSnapIndicator_,
    204                             this.rightSelected_);
    205       }
    206     },
    207 
    208     drawIndicator_: function(ctx, viewLWorld, viewRWorld,
    209                              xWorld, si, selected) {
    210       var dt = this.viewport_.currentDisplayTransform;
    211 
    212       var viewX = Math.round(dt.xWorldToView(xWorld));
    213 
    214       // Apply subpixel translate to get crisp lines.
    215       // http://www.mobtowers.com/html5-canvas-crisp-lines-every-time/
    216       ctx.save();
    217       ctx.translate((Math.round(ctx.lineWidth) % 2) / 2, 0);
    218 
    219       var pixelRatio = window.devicePixelRatio || 1;
    220       var viewY = si.y * devicePixelRatio;
    221       var viewHeight = si.height * devicePixelRatio;
    222       var arrowSize = 4 * pixelRatio;
    223 
    224       if (selected)
    225         ctx.fillStyle = 'rgb(255, 0, 0)';
    226       else
    227         ctx.fillStyle = 'rgb(0, 0, 0)';
    228       tr.ui.b.drawTriangle(ctx,
    229           viewX - arrowSize * 0.75, viewY,
    230           viewX + arrowSize * 0.75, viewY,
    231           viewX, viewY + arrowSize);
    232       ctx.fill();
    233       tr.ui.b.drawTriangle(ctx,
    234           viewX - arrowSize * 0.75, viewY + viewHeight,
    235           viewX + arrowSize * 0.75, viewY + viewHeight,
    236           viewX, viewY + viewHeight - arrowSize);
    237       ctx.fill();
    238 
    239       ctx.restore();
    240     }
    241   };
    242 
    243   return {
    244     SnapIndicator: SnapIndicator,
    245     TimelineInterestRange: TimelineInterestRange
    246   };
    247 });
    248 </script>
    249