blob: d21ac3c007cd5bd3020e175a0d22278587311cc8 [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="/tracing/base/statistics.html">
<link rel="import" href="/tracing/ui/base/column_chart.html">
<link rel="import" href="/tracing/value/ui/diagnostic_map_table.html">
<link rel="import" href="/tracing/value/ui/diagnostic_span.html">
<link rel="import" href="/tracing/value/ui/numeric_stats_span.html">
<link rel="import" href="/tracing/value/ui/scalar_span.html">
<dom-module id='tr-v-ui-histogram-span'>
<template>
<style>
#container {
display: flex;
flex-direction: row;
}
</style>
<div id="container">
<div id="chart"></div>
<tr-v-ui-numeric-stats-span id="stats"></tr-v-ui-numeric-stats-span>
</div>
<tr-v-ui-diagnostic-map-table id="diagnostic_map_table"></tr-v-ui-diagnostic-map-table>
</template>
</dom-module>
<script>
'use strict';
Polymer({
is: 'tr-v-ui-histogram-span',
created: function() {
this.histogram_ = undefined;
this.chart_ = new tr.ui.b.ColumnChart();
this.chart_.width = 400;
this.chart_.height = 200;
this.chart_.margin.right = 2;
this.mouseDownBin_ = undefined;
this.brushedBins_ = [];
this.chart_.addEventListener('item-mousedown',
this.onMouseDown_.bind(this));
this.chart_.addEventListener('item-mousemove',
this.onMouseMove_.bind(this));
this.chart_.addEventListener('item-mouseup',
this.onMouseUp_.bind(this));
this.chart_.hideLegend = true;
this.chart_.margin.right = 0;
},
ready: function() {
Polymer.dom(this.$.chart).appendChild(this.chart_);
},
get brushedBins() {
return this.brushedBins_;
},
updateBrushedRange_: function(currentX) {
this.brushedBins_ = [this.histogram_.getBinForValue(currentX)];
var r = new tr.b.Range();
r.addValue(this.mouseDownX_);
r.addValue(currentX);
// Collect bins:
var centralMin = Number.MAX_VALUE;
var centralMax = -Number.MAX_VALUE;
this.histogram_.centralBins.forEach(function(bin) {
centralMin = Math.min(centralMin, bin.range.min);
centralMax = Math.max(centralMax, bin.range.max);
if ((bin.range.max > r.min) &&
(bin.range.min < r.max) &&
(this.brushedBins_.indexOf(bin) < 0))
this.brushedBins_.push(bin);
}, this);
if ((this.histogram_.underflowBin.range.max > r.min) &&
(this.brushedBins_.indexOf(this.histogram_.underflowBin) < 0)) {
this.brushedBins_.push(this.histogram_.underflowBin);
}
if ((this.histogram_.overflowBin.range.min < r.max) &&
(this.brushedBins_.indexOf(this.histogram_.overflowBin) < 0)) {
this.brushedBins_.push(this.histogram_.overflowBin);
}
this.brushedBins_.sort(function(a, b) {
return a.range.min - b.range.min;
});
// Prevent Infinity:
var minBin = this.histogram_.getBinForValue(r.min);
var maxBin = this.histogram_.getBinForValue(r.max);
var binWidth = this.histogram_.centralBins[0].range.range;
r.min = minBin ? Math.max(centralMin - binWidth, minBin.range.min) :
centralMin - binWidth;
r.max = maxBin ? Math.min(centralMax + binWidth, maxBin.range.max) :
centralMax + binWidth;
this.chart_.brushedRange = r;
},
onMouseDown_: function(chartEvent) {
chartEvent.stopPropagation();
if (!this.histogram_)
return;
this.mouseDownX_ = chartEvent.x;
this.updateBrushedRange_(chartEvent.x);
},
onMouseMove_: function(chartEvent) {
chartEvent.stopPropagation();
if (!this.histogram_)
return;
this.updateBrushedRange_(chartEvent.x);
},
onMouseUp_: function(chartEvent) {
chartEvent.stopPropagation();
if (!this.histogram_)
return;
this.updateBrushedRange_(chartEvent.x);
this.updateDiagnostics_(this.brushedBins);
this.mouseDownX_ = undefined;
},
updateDiagnostics_: function(bins) {
var maps = [];
for (var bin of bins)
for (var map of bin.diagnosticMaps)
maps.push(map);
if (maps.length === 0) {
this.$.diagnostic_map_table.style.display = 'none';
return;
}
this.$.diagnostic_map_table.diagnosticMaps = maps;
this.$.diagnostic_map_table.style.display = 'block';
},
get histogram() {
return this.histogram_;
},
set histogram(histogram) {
this.histogram_ = histogram;
this.updateContents_();
},
set isYLogScale(logScale) {
this.chart_.isYLogScale = logScale;
},
updateContents_: function() {
this.$.chart.style.display = this.histogram_ ? '' : 'none';
this.$.diagnostic_map_table.style.display = 'none';
this.$.stats.numeric = this.histogram_;
this.brushedBins_ = [];
if (!this.histogram_)
return;
if (this.histogram_.numValues <= 1) {
this.$.container.style.display = 'none';
// Don't return! Still do the updateDiagnostics_(occupiedBins) below!
} else {
this.$.container.style.display = '';
var maximumBinValue = tr.b.Statistics.max(
this.histogram_.allBins, (bin) => bin.count);
var chartData = [];
var binWidth = this.histogram_.centralBins[0].range.range;
this.histogram_.allBins.forEach(function(bin) {
var x = bin.range.min;
if (x === -Number.MAX_VALUE) {
if (!bin.count)
return;
x = bin.range.max - binWidth;
}
chartData.push({x: x, y: bin.count});
});
chartData.sort((x, y) => x.x - y.x);
this.chart_.data = chartData;
this.chart_.brushedRange = new tr.b.Range();
}
var occupiedBins = [];
for (var bin of this.histogram.allBins) {
if (bin.count > 0)
occupiedBins.push(bin);
}
if (occupiedBins.length === 1)
this.updateDiagnostics_(occupiedBins);
}
});
</script>