Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / power.js
blob7e8d4787a8ead850700bf2a1d5b9a66041a17de0
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5  /**
6   * Plot a line graph of data versus time on a HTML canvas element.
7   *
8   * @param {HTMLCanvasElement} canvas The canvas on which the line graph is
9   *     drawn.
10   * @param {Array.<number>} tData The time (in seconds) in the past when the
11   *     corresponding data in plots was sampled.
12   * @param {Array.<Object>} plots An array of objects with fields 'data' and
13   *     'color'. The field 'data' is an array of samples to be plotted as a
14   *     line graph with 'color'. The elements in the 'data' array are ordered
15   *     corresponding to their sampling time in the argument 'tData'. Also,
16   *     the number of elements in the data array should be the same as in the
17   *     time array 'tData' above.
18   * @param {number} yMin Minimum bound of y-axis
19   * @param {number} yMax Maximum bound of y-axis.
20   * @param {integer} yPrecision An integer value representing the number of
21   *     digits of precision the y-axis data should be printed with.
22   */
23 function plotLineGraph(canvas, tData, plots, yMin, yMax, yPrecision) {
24   var textFont = '12px Arial';
25   var textHeight = 12;
26   var padding = 5;  // Pixels
27   var errorOffsetPixels = 15;
28   var gridColor = '#ccc';
29   var ctx = canvas.getContext('2d');
30   var size = tData.length;
32   function drawText(text, x, y) {
33     ctx.font = textFont;
34     ctx.fillStyle = '#000';
35     ctx.fillText(text, x, y);
36   }
38   function printErrorText(text) {
39     ctx.clearRect(0, 0, canvas.width, canvas.height);
40     drawText(text, errorOffsetPixels, errorOffsetPixels);
41   }
43   if (size < 2) {
44     printErrorText(loadTimeData.getString('notEnoughDataAvailableYet'));
45     return;
46   }
48   for (var count = 0; count < plots.length; count++) {
49     if (plots[count].data.length != size) {
50       printErrorText(loadTimeData.getString('timeAndPlotDataMismatch'));
51       return;
52     }
53   }
55   function valueToString(value) {
56     return Number(value).toPrecision(yPrecision);
57   }
59   function getTextWidth(text) {
60     ctx.font = textFont;
61     // For now, all text is drawn to the left of vertical lines, or centered.
62     // Add a 2 pixel padding so that there is some spacing between the text
63     // and the vertical line.
64     return Math.round(ctx.measureText(text).width) + 2;
65   }
67   function drawHighlightText(text, x, y, color) {
68     ctx.strokeStyle = '#000';
69     ctx.strokeRect(x, y - textHeight, getTextWidth(text), textHeight);
70     ctx.fillStyle = color;
71     ctx.fillRect(x, y - textHeight, getTextWidth(text), textHeight);
72     ctx.fillStyle = '#fff';
73     ctx.fillText(text, x, y);
74   }
76   function drawLine(x1, y1, x2, y2, color) {
77     ctx.save();
78     ctx.beginPath();
79     ctx.moveTo(x1, y1);
80     ctx.lineTo(x2, y2);
81     ctx.strokeStyle = color;
82     ctx.stroke();
83     ctx.restore();
84   }
86   // The strokeRect method of the 2d context of a canvas draws a bounding
87   // rectangle with an offset origin and greater dimensions. Hence, use this
88   // function to draw a rect at the desired location with desired dimensions.
89   function drawRect(x, y, width, height, color) {
90     drawLine(x, y, x + width - 1, y, color);
91     drawLine(x, y, x, y + height - 1, color);
92     drawLine(x, y + height - 1, x + width - 1, y + height - 1, color);
93     drawLine(x + width - 1, y, x + width - 1, y + height - 1, color);
94   }
96   var yMinStr = valueToString(yMin);
97   var yMaxStr = valueToString(yMax);
98   var yHalfStr = valueToString((yMax + yMin) / 2);
99   var yMinWidth = getTextWidth(yMinStr);
100   var yMaxWidth = getTextWidth(yMaxStr);
101   var yHalfWidth = getTextWidth(yHalfStr);
103   var xMinStr = tData[0];
104   var xMaxStr = tData[size - 1];
105   var xMinWidth = getTextWidth(xMinStr);
106   var xMaxWidth = getTextWidth(xMaxStr);
108   var xOrigin = padding + Math.max(yMinWidth,
109                                    yMaxWidth,
110                                    Math.round(xMinWidth / 2));
111   var yOrigin = padding + textHeight;
112   var width = canvas.width - xOrigin - Math.floor(xMaxWidth / 2) - padding;
113   if (width < size) {
114     canvas.width += size - width;
115     width = size;
116   }
117   var height = canvas.height - yOrigin - textHeight - padding;
119   function drawPlots() {
120     // Start fresh.
121     ctx.clearRect(0, 0, canvas.width, canvas.height);
123     // Draw the bounding rectangle.
124     drawRect(xOrigin, yOrigin, width, height, gridColor);
126     // Draw the x and y bound values.
127     drawText(yMaxStr, xOrigin - yMaxWidth, yOrigin + textHeight);
128     drawText(yMinStr, xOrigin - yMinWidth, yOrigin + height);
129     drawText(xMinStr, xOrigin - xMinWidth / 2, yOrigin + height + textHeight);
130     drawText(xMaxStr,
131              xOrigin + width - xMaxWidth / 2,
132              yOrigin + height + textHeight);
134     // Draw y-level (horizontal) lines.
135     drawLine(xOrigin, yOrigin + height / 4,
136              xOrigin + width - 1, yOrigin + height / 4,
137              gridColor);
138     drawLine(xOrigin, yOrigin + height / 2,
139              xOrigin + width - 1, yOrigin + height / 2, gridColor);
140     drawLine(xOrigin, yOrigin + 3 * height / 4,
141              xOrigin + width - 1, yOrigin + 3 * height / 4,
142              gridColor);
144     // Draw half-level value.
145     drawText(yHalfStr,
146              xOrigin - yHalfWidth,
147              yOrigin + height / 2 + textHeight / 2);
149     // Draw the plots.
150     var yValRange = yMax - yMin;
151     for (var count = 0; count < plots.length; count++) {
152       var plot = plots[count];
153       var yData = plot.data;
154       ctx.strokeStyle = plot.color;
155       ctx.beginPath();
156       for (var i = 0; i < size; i++) {
157         var xPos = xOrigin + Math.floor(i / (size - 1) * (width - 1));
158         var val = yData[i];
159         var yPos = yOrigin + height - 1 -
160                    Math.round((val - yMin) / yValRange * (height - 1));
161         if (i == 0) {
162           ctx.moveTo(xPos, yPos);
163         } else {
164           ctx.lineTo(xPos, yPos);
165         }
166       }
167       ctx.stroke();
168     }
169   }
171   function drawTimeGuide(tDataIndex) {
172     var x = xOrigin + tDataIndex / (size - 1) * (width - 1);
173     drawLine(x, yOrigin, x, yOrigin + height - 1, '#000');
174     drawText(tData[tDataIndex],
175              x - getTextWidth(tData[tDataIndex]) / 2,
176              yOrigin - 2);
178     for (var count = 0; count < plots.length; count++) {
179       var yData = plots[count].data;
181       // Draw small black square on the plot where the time guide intersects
182       // it.
183       var val = yData[tDataIndex];
184       var yPos = yOrigin + height - 1 -
185                  Math.round((val - yMin) / (yMax - yMin) * (height - 1));
186       ctx.fillStyle = '#000';
187       ctx.fillRect(x - 2, yPos - 2, 4, 4);
189       // Draw the val to right of the intersection.
190       var valStr = valueToString(val);
191       var yLoc;
192       if (yPos - textHeight / 2 < yOrigin) {
193         yLoc = yOrigin + textHeight;
194       } else if (yPos + textHeight / 2 >= yPos + height) {
195         yLoc = yOrigin + height - 1;
196       } else {
197         yLoc = yPos + textHeight / 2;
198       }
199       drawHighlightText(valStr, x + 5, yLoc, plots[count].color);
200     }
201   }
203   function onMouseOverOrMove(event) {
204     drawPlots();
206     var boundingRect = canvas.getBoundingClientRect();
207     var x = event.clientX - boundingRect.left;
208     var y = event.clientY - boundingRect.top;
209     if (x < xOrigin || x >= xOrigin + width ||
210         y < yOrigin || y >= yOrigin + height) {
211       return;
212     }
214     if (width == size) {
215       drawTimeGuide(x - xOrigin);
216     } else {
217       drawTimeGuide(Math.round((x - xOrigin) / (width - 1) * (size - 1)));
218     }
219   }
221   function onMouseOut(event) {
222     drawPlots();
223   }
225   drawPlots();
226   canvas.addEventListener('mouseover', onMouseOverOrMove);
227   canvas.addEventListener('mousemove', onMouseOverOrMove);
228   canvas.addEventListener('mouseout', onMouseOut);
232  * Display the battery charge vs time on a line graph.
234  * @param {Array.<Object>} powerSupplyArray An array of objects with fields
235  *     representing the battery charge, time when the charge measurement was
236  *     taken, and whether there was external power connected at that time.
237  */
238 function showBatteryChargeData(powerSupplyArray) {
239   var tData = [];
240   var chargePlot = [
241     {
242       color: '#0000FF',
243       data: []
244     }
245   ];
246   var dischargeRatePlot = [
247     {
248       color: '#FF0000',
249       data: []
250     }
251   ];
252   var minDischargeRate = 1000;  // A high unrealistic number to begin with.
253   var maxDischargeRate = -1000; // A low unrealistic number to begin with.
254   for (var i = 0; i < powerSupplyArray.length; i++) {
255     var time = new Date(powerSupplyArray[i].time);
256     tData[i] = time.toLocaleTimeString();
258     chargePlot[0].data[i] = powerSupplyArray[i].battery_percent;
260     var dischargeRate = powerSupplyArray[i].battery_discharge_rate;
261     dischargeRatePlot[0].data[i] = dischargeRate;
262     minDischargeRate = Math.min(dischargeRate, minDischargeRate);
263     maxDischargeRate = Math.max(dischargeRate, maxDischargeRate);
264   }
265   if (minDischargeRate == maxDischargeRate) {
266     // This means that all the samples had the same value. Hence, offset the
267     // extremes by a bit so that the plot looks good.
268     minDischargeRate -= 1;
269     maxDischargeRate += 1;
270   }
272   var chargeCanvas = $('battery-charge-percentage-canvas');
273   var dischargeRateCanvas = $('battery-discharge-rate-canvas');
274   plotLineGraph(chargeCanvas, tData, chargePlot, 0.00, 100.00, 3);
275   plotLineGraph(dischargeRateCanvas,
276                 tData,
277                 dischargeRatePlot,
278                 minDischargeRate,
279                 maxDischargeRate,
280                 3);
283 function requestBatteryChargeData() {
284   chrome.send('requestBatteryChargeData');
287 var powerUI = {
288   showBatteryChargeData: showBatteryChargeData
291 document.addEventListener('DOMContentLoaded', function() {
292   requestBatteryChargeData();
293   $('battery-charge-reload-button').onclick = requestBatteryChargeData;