Home | History | Annotate | Download | only in tracks
      1 <!DOCTYPE html>
      2 <!--
      3 Copyright (c) 2015 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="/tracing/base/range.html">
      9 
     10 <script>
     11 'use strict';
     12 
     13 tr.exportTo('tr.ui.tracks', function() {
     14 
     15   /**
     16    * A vertical axis for a (set of) chart series which maps an arbitrary range
     17    * of values [min, max] to the unit range [0, 1].
     18    *
     19    * @constructor
     20    */
     21   function ChartAxis(opt_min, opt_max) {
     22     this.guid_ = tr.b.GUID.allocate();
     23     this.bounds = new tr.b.Range();
     24     if (opt_min !== undefined)
     25       this.bounds.addValue(opt_min);
     26     if (opt_max !== undefined)
     27       this.bounds.addValue(opt_max);
     28   };
     29 
     30   ChartAxis.prototype = {
     31     get guid() {
     32       return this.guid_;
     33     },
     34 
     35     valueToUnitRange: function(value) {
     36       if (this.bounds.isEmpty)
     37         throw new Error('Chart axis bounds are empty');
     38       var bounds = this.bounds;
     39       if (bounds.range === 0)
     40         return 0;
     41       return (value - bounds.min) / bounds.range;
     42     },
     43 
     44     /**
     45      * Automatically set the axis bounds from the range of values of all series
     46      * in a list.
     47      *
     48      * See the description of autoSetFromRange for the optional configuration
     49      * argument flags.
     50      */
     51     autoSetFromSeries: function(series, opt_config) {
     52       var range = new tr.b.Range();
     53       series.forEach(function(s) {
     54         range.addRange(s.range);
     55       }, this);
     56       this.autoSetFromRange(range, opt_config);
     57     },
     58 
     59     /**
     60      * Automatically set the axis bound from a range of values.
     61      *
     62      * The following four flags, which affect the behavior of this method with
     63      * respect to already defined bounds, can be present in the optional
     64      * configuration (a flag is assumed to be false if it is not provided or if
     65      * the configuration is not provided):
     66      *
     67      *   - expandMin: allow decreasing the min bound (if range.min < this.min)
     68      *   - shrinkMin: allow increasing the min bound (if range.min > this.min)
     69      *   - expandMax: allow increasing the max bound (if range.max > this.max)
     70      *   - shrinkMax: allow decreasing the max bound (if range.max < this.max)
     71      *
     72      * This method will ensure that the resulting bounds are defined and valid
     73      * (i.e. min <= max) provided that they were valid or empty before and the
     74      * value range is non-empty and valid.
     75      *
     76      * Note that unless expanding/shrinking a bound is explicitly enabled in
     77      * the configuration, non-empty bounds will not be changed under any
     78      * circumstances.
     79      *
     80      * Observe that if no configuration is provided (or all flags are set to
     81      * false), this method will only modify the axis bounds if they are empty.
     82      */
     83     autoSetFromRange: function(range, opt_config) {
     84       if (range.isEmpty)
     85         return;
     86 
     87       var bounds = this.bounds;
     88       if (bounds.isEmpty) {
     89         bounds.addRange(range);
     90         return;
     91       }
     92 
     93       if (!opt_config)
     94         return;
     95 
     96       var useRangeMin = (opt_config.expandMin && range.min < bounds.min ||
     97                          opt_config.shrinkMin && range.min > bounds.min);
     98       var useRangeMax = (opt_config.expandMax && range.max > bounds.max ||
     99                          opt_config.shrinkMax && range.max < bounds.max);
    100 
    101       // Neither bound is modified.
    102       if (!useRangeMin && !useRangeMax)
    103         return;
    104 
    105       // Both bounds are modified. Assuming the range argument is a valid
    106       // range, no extra checks are necessary.
    107       if (useRangeMin && useRangeMax) {
    108         bounds.min = range.min;
    109         bounds.max = range.max;
    110         return;
    111       }
    112 
    113       // Only one bound is modified. We must ensure that it doesn't go
    114       // over/under the other (unmodified) bound.
    115       if (useRangeMin) {
    116         bounds.min = Math.min(range.min, bounds.max);
    117       } else {
    118         bounds.max = Math.max(range.max, bounds.min);
    119       }
    120     }
    121   };
    122 
    123   return {
    124     ChartAxis: ChartAxis
    125   };
    126 });
    127 
    128