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