blob: cec5e882d03f046801be5b165d2d267124a9dd78 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2015 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/base/range.html">
<script>
'use strict';
tr.exportTo('tr.c.tracks', function() {
/**
* A vertical axis for a (set of) chart series which maps an arbitrary range
* of values [min, max] to the unit range [0, 1].
*
* @constructor
*/
function ChartAxis(opt_min, opt_max) {
this.guid_ = tr.b.GUID.allocate();
this.bounds = new tr.b.Range();
if (opt_min !== undefined)
this.bounds.addValue(opt_min);
if (opt_max !== undefined)
this.bounds.addValue(opt_max);
};
ChartAxis.prototype = {
get guid() {
return this.guid_;
},
valueToUnitRange: function(value) {
if (this.bounds.isEmpty)
throw new Error('Chart axis bounds are empty');
var bounds = this.bounds;
if (bounds.range === 0)
return 0;
return (value - bounds.min) / bounds.range;
},
/**
* Automatically set the axis bounds from the range of values of all series
* in a list.
*
* See the description of autoSetFromRange for the optional configuration
* argument flags.
*/
autoSetFromSeries: function(series, opt_config) {
var range = new tr.b.Range();
series.forEach(function(s) {
range.addRange(s.range);
}, this);
this.autoSetFromRange(range, opt_config);
},
/**
* Automatically set the axis bound from a range of values.
*
* The following four flags, which affect the behavior of this method with
* respect to already defined bounds, can be present in the optional
* configuration (a flag is assumed to be false if it is not provided or if
* the configuration is not provided):
*
* - expandMin: allow decreasing the min bound (if range.min < this.min)
* - shrinkMin: allow increasing the min bound (if range.min > this.min)
* - expandMax: allow increasing the max bound (if range.max > this.max)
* - shrinkMax: allow decreasing the max bound (if range.max < this.max)
*
* This method will ensure that the resulting bounds are defined and valid
* (i.e. min <= max) provided that they were valid or empty before and the
* value range is non-empty and valid.
*
* Note that unless expanding/shrinking a bound is explicitly enabled in
* the configuration, non-empty bounds will not be changed under any
* circumstances.
*
* Observe that if no configuration is provided (or all flags are set to
* false), this method will only modify the axis bounds if they are empty.
*/
autoSetFromRange: function(range, opt_config) {
if (range.isEmpty)
return;
var bounds = this.bounds;
if (bounds.isEmpty) {
bounds.addRange(range);
return;
}
if (!opt_config)
return;
var useRangeMin = (opt_config.expandMin && range.min < bounds.min ||
opt_config.shrinkMin && range.min > bounds.min);
var useRangeMax = (opt_config.expandMax && range.max > bounds.max ||
opt_config.shrinkMax && range.max < bounds.max);
// Neither bound is modified.
if (!useRangeMin && !useRangeMax)
return;
// Both bounds are modified. Assuming the range argument is a valid
// range, no extra checks are necessary.
if (useRangeMin && useRangeMax) {
bounds.min = range.min;
bounds.max = range.max;
return;
}
// Only one bound is modified. We must ensure that it doesn't go
// over/under the other (unmodified) bound.
if (useRangeMin) {
bounds.min = Math.min(range.min, bounds.max);
} else {
bounds.max = Math.max(range.max, bounds.min);
}
}
};
return {
ChartAxis: ChartAxis
};
});
</script>