Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / third_party / tvcm / src / tvcm / ui / chart_base.html
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 <link rel="import" href="/tvcm/ui.html">
8 <link rel="import" href="/tvcm/ui/color_scheme.html">
9 <link rel="import" href="/tvcm/ui/d3.html">
10
11 <style>
12   .chart-base #title {
13     font-size: 16pt;
14   }
15
16   .chart-base {
17     font-size: 12pt;
18     -webkit-user-select: none;
19     cursor: default;
20   }
21
22   .chart-base .axis path,
23   .chart-base .axis line {
24     fill: none;
25     shape-rendering: crispEdges;
26     stroke: #000;
27   }
28 </style>
29
30 <template id="chart-base-template">
31   <svg> <!-- svg tag is dropped by ChartBase.decorate. -->
32     <g xmlns="http://www.w3.org/2000/svg" id="chart-area">
33       <g class="x axis"></g>
34       <g class="y axis"></g>
35       <text id="title"></text>
36     </g>
37   </svg>
38 </template>
39
40 <script>
41 'use strict';
42
43 tvcm.exportTo('tvcm.ui', function() {
44   var THIS_DOC = document.currentScript.ownerDocument;
45
46   var svgNS = 'http://www.w3.org/2000/svg';
47   var highlightIdBoost = tvcm.ui.getColorPaletteHighlightIdBoost();
48
49   function getColorOfKey(key, selected) {
50     var id = tvcm.ui.getStringColorId(key);
51     if (selected)
52       id += highlightIdBoost;
53     return tvcm.ui.getColorPalette()[id];
54   }
55
56   /**
57    * A virtual base class for basic charts that provides X and Y axes, if
58    * needed, a title, and legend.
59    *
60    * @constructor
61    */
62   var ChartBase = tvcm.ui.define('svg', undefined, svgNS);
63
64   ChartBase.prototype = {
65     __proto__: HTMLUnknownElement.prototype,
66
67     decorate: function() {
68       this.classList.add('chart-base');
69       this.chartTitle_ = undefined;
70       this.data_ = undefined;
71       this.seriesKeys_ = undefined;
72       this.width_ = 400;
73       this.height_ = 300;
74
75       // This should use tvcm.instantiateTemplate. However, creating
76       // svg-namespaced elements inside a template isn't possible. Thus, this
77       // hack.
78       var template = THIS_DOC.querySelector('#chart-base-template');
79       var svgEl = template.content.querySelector('svg');
80       for (var i = 0; i < svgEl.children.length; i++)
81         this.appendChild(svgEl.children[i].cloneNode(true));
82
83       // svg likes to take over width & height properties for some reason. This
84       // works around it.
85       Object.defineProperty(
86           this, 'width', {
87             get: function() {
88               return this.width_;
89             },
90             set: function(width) {
91               this.width_ = width;
92               this.updateContents_();
93             }
94           });
95       Object.defineProperty(
96           this, 'height', {
97             get: function() {
98               return this.height_;
99             },
100             set: function(height) {
101               this.height_ = height;
102               this.updateContents_();
103             }
104           });
105     },
106
107     get chartTitle() {
108       return chartTitle_;
109     },
110
111     set chartTitle(chartTitle) {
112       this.chartTitle_ = chartTitle;
113       this.updateContents_();
114     },
115
116     get chartAreaElement() {
117       return this.querySelector('#chart-area');
118     },
119
120     get data() {
121       return this.data_;
122     },
123
124     setSize: function(size) {
125       this.width_ = size.width;
126       this.height_ = size.height;
127       this.updateContents_();
128     },
129
130     get margin() {
131       var margin = {top: 20, right: 20, bottom: 30, left: 50};
132       if (this.chartTitle_)
133         margin.top += 20;
134       return margin;
135     },
136
137     get chartAreaSize() {
138       var margin = this.margin;
139       return {
140         width: this.width_ - margin.left - margin.right,
141         height: this.height_ - margin.top - margin.bottom
142       };
143     },
144
145     getLegendKeys_: function() {
146       throw new Error('Not implemented');
147     },
148
149     updateScales_: function(width, height) {
150       throw new Error('Not implemented');
151     },
152
153     updateContents_: function() {
154       var margin = this.margin;
155       var width = this.chartAreaSize.width;
156       var height = this.chartAreaSize.height;
157
158       var thisSel = d3.select(this);
159       thisSel.attr('width', this.width_);
160       thisSel.attr('height', this.height_);
161
162       var chartAreaSel = d3.select(this.chartAreaElement);
163       chartAreaSel.attr(
164           'transform',
165           'translate(' + margin.left + ',' + margin.top + ')');
166
167       this.updateScales_(width, height);
168
169       // Axes.
170       if (this.xScale_ && this.yScale_) {
171         var xAxisRenderer = d3.svg.axis()
172             .scale(this.xScale_)
173             .orient('bottom');
174
175         var yAxisRenderer = d3.svg.axis()
176             .scale(this.yScale_)
177             .orient('left');
178
179         chartAreaSel.select('.x.axis')
180             .attr('transform', 'translate(0,' + height + ')')
181             .call(xAxisRenderer);
182
183         chartAreaSel.select('.y.axis')
184             .call(yAxisRenderer);
185       }
186
187       // Title.
188       var titleSel = chartAreaSel.select('#title');
189       if (this.chartTitle_) {
190         titleSel.attr('transform', 'translate(' + width * 0.5 + ',-5)')
191             .style('display', undefined)
192             .style('text-anchor', 'middle')
193             .attr('class', 'title')
194             .attr('width', width)
195             .text(this.chartTitle_);
196       } else {
197         titleSel.style('display', 'none');
198       }
199
200       // Basics
201       this.updateLegend_();
202     },
203
204     updateLegend_: function() {
205       var keys = this.getLegendKeys_();
206       if (keys === undefined)
207         return;
208
209       var chartAreaSel = d3.select(this.chartAreaElement);
210       var chartAreaSize = this.chartAreaSize;
211
212       var legendEntriesSel = chartAreaSel.selectAll('.legend')
213           .data(keys.slice().reverse());
214
215       legendEntriesSel.enter()
216           .append('g')
217           .attr('class', 'legend')
218           .attr('transform', function(d, i) {
219             return 'translate(0,' + i * 20 + ')';
220           }).append('text').text(function(key) {
221             return key;
222           });
223       legendEntriesSel.exit().remove();
224
225       legendEntriesSel.attr('x', chartAreaSize.width - 18)
226           .attr('width', 18)
227           .attr('height', 18)
228           .style('fill', function(key) {
229             var selected = this.currentHighlightedLegendKey === key;
230             return getColorOfKey(key, selected);
231           }.bind(this));
232
233       legendEntriesSel.selectAll('text')
234         .attr('x', chartAreaSize.width - 24)
235         .attr('y', 9)
236         .attr('dy', '.35em')
237         .style('text-anchor', 'end')
238         .text(function(d) { return d; });
239     },
240
241     get highlightedLegendKey() {
242       return this.highlightedLegendKey_;
243     },
244
245     set highlightedLegendKey(highlightedLegendKey) {
246       this.highlightedLegendKey_ = highlightedLegendKey;
247       this.updateHighlight_();
248     },
249
250     get currentHighlightedLegendKey() {
251       if (this.tempHighlightedLegendKey_)
252         return this.tempHighlightedLegendKey_;
253       return this.highlightedLegendKey_;
254     },
255
256     pushTempHighlightedLegendKey: function(key) {
257       if (this.tempHighlightedLegendKey_)
258         throw new Error('push cannot nest');
259       this.tempHighlightedLegendKey_ = key;
260       this.updateHighlight_();
261     },
262
263     popTempHighlightedLegendKey: function(key) {
264       if (this.tempHighlightedLegendKey_ != key)
265         throw new Error('pop cannot happen');
266       this.tempHighlightedLegendKey_ = undefined;
267       this.updateHighlight_();
268     },
269
270     updateHighlight_: function() {
271       // Update label colors.
272       var chartAreaSel = d3.select(this.chartAreaElement);
273       var legendEntriesSel = chartAreaSel.selectAll('.legend');
274
275       var that = this;
276       legendEntriesSel.each(function(key) {
277         var highlighted = key == that.currentHighlightedLegendKey;
278         var color = getColorOfKey(key, highlighted);
279         this.style.fill = color;
280         if (highlighted)
281           this.style.fontWeight = 'bold';
282         else
283           this.style.fontWeight = '';
284       });
285     }
286   };
287
288   return {
289     getColorOfKey: getColorOfKey,
290     ChartBase: ChartBase
291   };
292 });
293 </script>