| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * Plot a line graph of data versus time on a HTML canvas element. | 6 * Plot a line graph of data versus time on a HTML canvas element. |
| 7 * | 7 * |
| 8 * @param {HTMLCanvasElement} plotCanvas The canvas on which the line graph is | 8 * @param {HTMLCanvasElement} plotCanvas The canvas on which the line graph is |
| 9 * drawn. | 9 * drawn. |
| 10 * @param {HTMLCanvasElement} legendCanvas The canvas on which the legend for | 10 * @param {HTMLCanvasElement} legendCanvas The canvas on which the legend for |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 ctx.fillStyle = '#000'; | 38 ctx.fillStyle = '#000'; |
| 39 ctx.fillText(text, x, y); | 39 ctx.fillText(text, x, y); |
| 40 } | 40 } |
| 41 | 41 |
| 42 function printErrorText(ctx, text) { | 42 function printErrorText(ctx, text) { |
| 43 ctx.clearRect(0, 0, plotCanvas.width, plotCanvas.height); | 43 ctx.clearRect(0, 0, plotCanvas.width, plotCanvas.height); |
| 44 drawText(ctx, text, errorOffsetPixels, errorOffsetPixels); | 44 drawText(ctx, text, errorOffsetPixels, errorOffsetPixels); |
| 45 } | 45 } |
| 46 | 46 |
| 47 if (size < 2) { | 47 if (size < 2) { |
| 48 printErrorText(plotCtx, | 48 printErrorText( |
| 49 loadTimeData.getString('notEnoughDataAvailableYet')); | 49 plotCtx, loadTimeData.getString('notEnoughDataAvailableYet')); |
| 50 return; | 50 return; |
| 51 } | 51 } |
| 52 | 52 |
| 53 for (var count = 0; count < plots.length; count++) { | 53 for (var count = 0; count < plots.length; count++) { |
| 54 if (plots[count].data.length != size) { | 54 if (plots[count].data.length != size) { |
| 55 throw new Error('Mismatch in time and plot data.'); | 55 throw new Error('Mismatch in time and plot data.'); |
| 56 } | 56 } |
| 57 } | 57 } |
| 58 | 58 |
| 59 function valueToString(value) { | 59 function valueToString(value) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 ctx.restore(); | 96 ctx.restore(); |
| 97 } | 97 } |
| 98 | 98 |
| 99 // The strokeRect method of the 2d context of a plotCanvas draws a bounding | 99 // The strokeRect method of the 2d context of a plotCanvas draws a bounding |
| 100 // rectangle with an offset origin and greater dimensions. Hence, use this | 100 // rectangle with an offset origin and greater dimensions. Hence, use this |
| 101 // function to draw a rect at the desired location with desired dimensions. | 101 // function to draw a rect at the desired location with desired dimensions. |
| 102 function drawRect(ctx, x, y, width, height, color) { | 102 function drawRect(ctx, x, y, width, height, color) { |
| 103 var offset = 1 * devicePixelRatio; | 103 var offset = 1 * devicePixelRatio; |
| 104 drawLine(ctx, x, y, x + width - offset, y, color); | 104 drawLine(ctx, x, y, x + width - offset, y, color); |
| 105 drawLine(ctx, x, y, x, y + height - offset, color); | 105 drawLine(ctx, x, y, x, y + height - offset, color); |
| 106 drawLine(ctx, x, y + height - offset, x + width - offset, | 106 drawLine( |
| 107 y + height - offset, color); | 107 ctx, x, y + height - offset, x + width - offset, y + height - offset, |
| 108 drawLine(ctx, x + width - offset, y, x + width - offset, | 108 color); |
| 109 y + height - offset, color); | 109 drawLine( |
| 110 ctx, x + width - offset, y, x + width - offset, y + height - offset, |
| 111 color); |
| 110 } | 112 } |
| 111 | 113 |
| 112 function drawLegend() { | 114 function drawLegend() { |
| 113 // Show a legend only if at least one individual plot has a name. | 115 // Show a legend only if at least one individual plot has a name. |
| 114 var valid = false; | 116 var valid = false; |
| 115 for (var i = 0; i < plots.length; i++) { | 117 for (var i = 0; i < plots.length; i++) { |
| 116 if (plots[i].name != null) { | 118 if (plots[i].name != null) { |
| 117 valid = true; | 119 valid = true; |
| 118 break; | 120 break; |
| 119 } | 121 } |
| 120 } | 122 } |
| 121 if (!valid) { | 123 if (!valid) { |
| 122 legendCanvas.hidden = true; | 124 legendCanvas.hidden = true; |
| 123 return; | 125 return; |
| 124 } | 126 } |
| 125 | 127 |
| 126 | 128 |
| 127 var padding = 2 * devicePixelRatio; | 129 var padding = 2 * devicePixelRatio; |
| 128 var legendSquareSide = 12 * devicePixelRatio; | 130 var legendSquareSide = 12 * devicePixelRatio; |
| 129 var legendCtx = legendCanvas.getContext('2d'); | 131 var legendCtx = legendCanvas.getContext('2d'); |
| 130 var xLoc = padding; | 132 var xLoc = padding; |
| 131 var yLoc = padding; | 133 var yLoc = padding; |
| 132 // Adjust the height of the canvas before drawing on it. | 134 // Adjust the height of the canvas before drawing on it. |
| 133 for (var i = 0; i < plots.length; i++) { | 135 for (var i = 0; i < plots.length; i++) { |
| 134 if (plots[i].name == null) { | 136 if (plots[i].name == null) { |
| 135 continue; | 137 continue; |
| 136 } | 138 } |
| 137 var legendText = getLegend(plots[i].name); | 139 var legendText = getLegend(plots[i].name); |
| 138 xLoc += legendSquareSide + getTextWidth(legendCtx, legendText) + | 140 xLoc += |
| 139 2 * padding; | 141 legendSquareSide + getTextWidth(legendCtx, legendText) + 2 * padding; |
| 140 if (i < plots.length - 1) { | 142 if (i < plots.length - 1) { |
| 141 var xLocNext = xLoc + | 143 var xLocNext = xLoc + |
| 142 getTextWidth(legendCtx, getLegend(plots[i + 1].name)) + | 144 getTextWidth(legendCtx, getLegend(plots[i + 1].name)) + |
| 143 legendSquareSide; | 145 legendSquareSide; |
| 144 if (xLocNext >= legendCanvas.width) { | 146 if (xLocNext >= legendCanvas.width) { |
| 145 xLoc = padding; | 147 xLoc = padding; |
| 146 yLoc = yLoc + 2 * padding + textHeight; | 148 yLoc = yLoc + 2 * padding + textHeight; |
| 147 } | 149 } |
| 148 } | 150 } |
| 149 } | 151 } |
| 150 | 152 |
| 151 legendCanvas.height = yLoc + textHeight + padding; | 153 legendCanvas.height = yLoc + textHeight + padding; |
| 152 legendCanvas.style.height = | 154 legendCanvas.style.height = legendCanvas.height / devicePixelRatio + 'px'; |
| 153 legendCanvas.height / devicePixelRatio + 'px'; | |
| 154 | 155 |
| 155 xLoc = padding; | 156 xLoc = padding; |
| 156 yLoc = padding; | 157 yLoc = padding; |
| 157 // Go over the plots again, this time drawing the legends. | 158 // Go over the plots again, this time drawing the legends. |
| 158 for (var i = 0; i < plots.length; i++) { | 159 for (var i = 0; i < plots.length; i++) { |
| 159 legendCtx.fillStyle = plots[i].color; | 160 legendCtx.fillStyle = plots[i].color; |
| 160 legendCtx.fillRect(xLoc, yLoc, legendSquareSide, legendSquareSide); | 161 legendCtx.fillRect(xLoc, yLoc, legendSquareSide, legendSquareSide); |
| 161 xLoc += legendSquareSide; | 162 xLoc += legendSquareSide; |
| 162 | 163 |
| 163 var legendText = getLegend(plots[i].name); | 164 var legendText = getLegend(plots[i].name); |
| 164 drawText(legendCtx, legendText, xLoc, yLoc + textHeight - 1); | 165 drawText(legendCtx, legendText, xLoc, yLoc + textHeight - 1); |
| 165 xLoc += getTextWidth(legendCtx, legendText) + 2 * padding; | 166 xLoc += getTextWidth(legendCtx, legendText) + 2 * padding; |
| 166 | 167 |
| 167 if (i < plots.length - 1) { | 168 if (i < plots.length - 1) { |
| 168 var xLocNext = xLoc + | 169 var xLocNext = xLoc + |
| 169 getTextWidth(legendCtx, getLegend(plots[i + 1].name)) + | 170 getTextWidth(legendCtx, getLegend(plots[i + 1].name)) + |
| 170 legendSquareSide; | 171 legendSquareSide; |
| 171 if (xLocNext >= legendCanvas.width) { | 172 if (xLocNext >= legendCanvas.width) { |
| 172 xLoc = padding; | 173 xLoc = padding; |
| 173 yLoc = yLoc + 2 * padding + textHeight; | 174 yLoc = yLoc + 2 * padding + textHeight; |
| 174 } | 175 } |
| 175 } | 176 } |
| 176 } | 177 } |
| 177 } | 178 } |
| 178 | 179 |
| 179 var yMinStr = valueToString(yMin); | 180 var yMinStr = valueToString(yMin); |
| 180 var yMaxStr = valueToString(yMax); | 181 var yMaxStr = valueToString(yMax); |
| 181 var yHalfStr = valueToString((yMax + yMin) / 2); | 182 var yHalfStr = valueToString((yMax + yMin) / 2); |
| 182 var yMinWidth = getTextWidth(plotCtx, yMinStr); | 183 var yMinWidth = getTextWidth(plotCtx, yMinStr); |
| 183 var yMaxWidth = getTextWidth(plotCtx, yMaxStr); | 184 var yMaxWidth = getTextWidth(plotCtx, yMaxStr); |
| 184 var yHalfWidth = getTextWidth(plotCtx, yHalfStr); | 185 var yHalfWidth = getTextWidth(plotCtx, yHalfStr); |
| 185 | 186 |
| 186 var xMinStr = tData[0]; | 187 var xMinStr = tData[0]; |
| 187 var xMaxStr = tData[size - 1]; | 188 var xMaxStr = tData[size - 1]; |
| 188 var xMinWidth = getTextWidth(plotCtx, xMinStr); | 189 var xMinWidth = getTextWidth(plotCtx, xMinStr); |
| 189 var xMaxWidth = getTextWidth(plotCtx, xMaxStr); | 190 var xMaxWidth = getTextWidth(plotCtx, xMaxStr); |
| 190 | 191 |
| 191 var xOrigin = padding + Math.max(yMinWidth, | 192 var xOrigin = |
| 192 yMaxWidth, | 193 padding + Math.max(yMinWidth, yMaxWidth, Math.round(xMinWidth / 2)); |
| 193 Math.round(xMinWidth / 2)); | |
| 194 var yOrigin = padding + textHeight; | 194 var yOrigin = padding + textHeight; |
| 195 var width = plotCanvas.width - xOrigin - Math.floor(xMaxWidth / 2) - padding; | 195 var width = plotCanvas.width - xOrigin - Math.floor(xMaxWidth / 2) - padding; |
| 196 if (width < size) { | 196 if (width < size) { |
| 197 plotCanvas.width += size - width; | 197 plotCanvas.width += size - width; |
| 198 width = size; | 198 width = size; |
| 199 } | 199 } |
| 200 var height = plotCanvas.height - yOrigin - textHeight - padding; | 200 var height = plotCanvas.height - yOrigin - textHeight - padding; |
| 201 var linePlotEndMarkerWidth = 3; | 201 var linePlotEndMarkerWidth = 3; |
| 202 | 202 |
| 203 function drawPlots() { | 203 function drawPlots() { |
| 204 // Start fresh. | 204 // Start fresh. |
| 205 plotCtx.clearRect(0, 0, plotCanvas.width, plotCanvas.height); | 205 plotCtx.clearRect(0, 0, plotCanvas.width, plotCanvas.height); |
| 206 | 206 |
| 207 // Draw the bounding rectangle. | 207 // Draw the bounding rectangle. |
| 208 drawRect(plotCtx, xOrigin, yOrigin, width, height, gridColor); | 208 drawRect(plotCtx, xOrigin, yOrigin, width, height, gridColor); |
| 209 | 209 |
| 210 // Draw the x and y bound values. | 210 // Draw the x and y bound values. |
| 211 drawText(plotCtx, yMaxStr, xOrigin - yMaxWidth, yOrigin + textHeight); | 211 drawText(plotCtx, yMaxStr, xOrigin - yMaxWidth, yOrigin + textHeight); |
| 212 drawText(plotCtx, yMinStr, xOrigin - yMinWidth, yOrigin + height); | 212 drawText(plotCtx, yMinStr, xOrigin - yMinWidth, yOrigin + height); |
| 213 drawText(plotCtx, | 213 drawText( |
| 214 xMinStr, | 214 plotCtx, xMinStr, xOrigin - xMinWidth / 2, |
| 215 xOrigin - xMinWidth / 2, | 215 yOrigin + height + textHeight); |
| 216 yOrigin + height + textHeight); | 216 drawText( |
| 217 drawText(plotCtx, | 217 plotCtx, xMaxStr, xOrigin + width - xMaxWidth / 2, |
| 218 xMaxStr, | 218 yOrigin + height + textHeight); |
| 219 xOrigin + width - xMaxWidth / 2, | |
| 220 yOrigin + height + textHeight); | |
| 221 | 219 |
| 222 // Draw y-level (horizontal) lines. | 220 // Draw y-level (horizontal) lines. |
| 223 drawLine(plotCtx, | 221 drawLine( |
| 224 xOrigin + 1, yOrigin + height / 4, | 222 plotCtx, xOrigin + 1, yOrigin + height / 4, xOrigin + width - 2, |
| 225 xOrigin + width - 2, yOrigin + height / 4, | 223 yOrigin + height / 4, gridColor); |
| 226 gridColor); | 224 drawLine( |
| 227 drawLine(plotCtx, | 225 plotCtx, xOrigin + 1, yOrigin + height / 2, xOrigin + width - 2, |
| 228 xOrigin + 1, yOrigin + height / 2, | 226 yOrigin + height / 2, gridColor); |
| 229 xOrigin + width - 2, yOrigin + height / 2, gridColor); | 227 drawLine( |
| 230 drawLine(plotCtx, | 228 plotCtx, xOrigin + 1, yOrigin + 3 * height / 4, xOrigin + width - 2, |
| 231 xOrigin + 1, yOrigin + 3 * height / 4, | 229 yOrigin + 3 * height / 4, gridColor); |
| 232 xOrigin + width - 2, yOrigin + 3 * height / 4, | |
| 233 gridColor); | |
| 234 | 230 |
| 235 // Draw half-level value. | 231 // Draw half-level value. |
| 236 drawText(plotCtx, | 232 drawText( |
| 237 yHalfStr, | 233 plotCtx, yHalfStr, xOrigin - yHalfWidth, |
| 238 xOrigin - yHalfWidth, | 234 yOrigin + height / 2 + textHeight / 2); |
| 239 yOrigin + height / 2 + textHeight / 2); | |
| 240 | 235 |
| 241 // Draw the plots. | 236 // Draw the plots. |
| 242 var yValRange = yMax - yMin; | 237 var yValRange = yMax - yMin; |
| 243 for (var count = 0; count < plots.length; count++) { | 238 for (var count = 0; count < plots.length; count++) { |
| 244 var plot = plots[count]; | 239 var plot = plots[count]; |
| 245 var yData = plot.data; | 240 var yData = plot.data; |
| 246 plotCtx.strokeStyle = plot.color; | 241 plotCtx.strokeStyle = plot.color; |
| 247 plotCtx.lineWidth = 2; | 242 plotCtx.lineWidth = 2; |
| 248 plotCtx.beginPath(); | 243 plotCtx.beginPath(); |
| 249 var beginPath = true; | 244 var beginPath = true; |
| 250 for (var i = 0; i < size; i++) { | 245 for (var i = 0; i < size; i++) { |
| 251 var val = yData[i]; | 246 var val = yData[i]; |
| 252 if (typeof val === 'string') { | 247 if (typeof val === 'string') { |
| 253 // Stroke the plot drawn so far and begin a fresh plot. | 248 // Stroke the plot drawn so far and begin a fresh plot. |
| 254 plotCtx.stroke(); | 249 plotCtx.stroke(); |
| 255 plotCtx.beginPath(); | 250 plotCtx.beginPath(); |
| 256 beginPath = true; | 251 beginPath = true; |
| 257 continue; | 252 continue; |
| 258 } | 253 } |
| 259 var xPos = xOrigin + Math.floor(i / (size - 1) * (width - 1)); | 254 var xPos = xOrigin + Math.floor(i / (size - 1) * (width - 1)); |
| 260 var yPos = yOrigin + height - 1 - | 255 var yPos = yOrigin + height - 1 - |
| 261 Math.round((val - yMin) / yValRange * (height - 1)); | 256 Math.round((val - yMin) / yValRange * (height - 1)); |
| 262 if (beginPath) { | 257 if (beginPath) { |
| 263 plotCtx.moveTo(xPos, yPos); | 258 plotCtx.moveTo(xPos, yPos); |
| 264 // A simple move to does not print anything. Hence, draw a little | 259 // A simple move to does not print anything. Hence, draw a little |
| 265 // square here to mark a beginning. | 260 // square here to mark a beginning. |
| 266 plotCtx.fillStyle = '#000'; | 261 plotCtx.fillStyle = '#000'; |
| 267 plotCtx.fillRect(xPos - linePlotEndMarkerWidth, | 262 plotCtx.fillRect( |
| 268 yPos - linePlotEndMarkerWidth, | 263 xPos - linePlotEndMarkerWidth, yPos - linePlotEndMarkerWidth, |
| 269 linePlotEndMarkerWidth * devicePixelRatio, | 264 linePlotEndMarkerWidth * devicePixelRatio, |
| 270 linePlotEndMarkerWidth * devicePixelRatio); | 265 linePlotEndMarkerWidth * devicePixelRatio); |
| 271 beginPath = false; | 266 beginPath = false; |
| 272 } else { | 267 } else { |
| 273 plotCtx.lineTo(xPos, yPos); | 268 plotCtx.lineTo(xPos, yPos); |
| 274 if (i === size - 1 || typeof yData[i + 1] === 'string') { | 269 if (i === size - 1 || typeof yData[i + 1] === 'string') { |
| 275 // Draw a little square to mark an end to go with the start | 270 // Draw a little square to mark an end to go with the start |
| 276 // markers from above. | 271 // markers from above. |
| 277 plotCtx.fillStyle = '#000'; | 272 plotCtx.fillStyle = '#000'; |
| 278 plotCtx.fillRect(xPos - linePlotEndMarkerWidth, | 273 plotCtx.fillRect( |
| 279 yPos - linePlotEndMarkerWidth, | 274 xPos - linePlotEndMarkerWidth, yPos - linePlotEndMarkerWidth, |
| 280 linePlotEndMarkerWidth * devicePixelRatio, | 275 linePlotEndMarkerWidth * devicePixelRatio, |
| 281 linePlotEndMarkerWidth * devicePixelRatio); | 276 linePlotEndMarkerWidth * devicePixelRatio); |
| 282 } | 277 } |
| 283 } | 278 } |
| 284 } | 279 } |
| 285 plotCtx.stroke(); | 280 plotCtx.stroke(); |
| 286 } | 281 } |
| 287 | 282 |
| 288 // Paint the missing time intervals with |gridColor|. | 283 // Paint the missing time intervals with |gridColor|. |
| 289 // Pick one of the plots to look for missing time intervals. | 284 // Pick one of the plots to look for missing time intervals. |
| 290 function drawMissingRect(start, end) { | 285 function drawMissingRect(start, end) { |
| 291 var xLeft = xOrigin + Math.floor(start / (size - 1) * (width - 1)); | 286 var xLeft = xOrigin + Math.floor(start / (size - 1) * (width - 1)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 313 } else if (inMissingInterval) { | 308 } else if (inMissingInterval) { |
| 314 inMissingInterval = false; | 309 inMissingInterval = false; |
| 315 drawMissingRect(intervalStart, i); | 310 drawMissingRect(intervalStart, i); |
| 316 } | 311 } |
| 317 } | 312 } |
| 318 } | 313 } |
| 319 | 314 |
| 320 function drawTimeGuide(tDataIndex) { | 315 function drawTimeGuide(tDataIndex) { |
| 321 var x = xOrigin + tDataIndex / (size - 1) * (width - 1); | 316 var x = xOrigin + tDataIndex / (size - 1) * (width - 1); |
| 322 drawLine(plotCtx, x, yOrigin, x, yOrigin + height - 1, '#000'); | 317 drawLine(plotCtx, x, yOrigin, x, yOrigin + height - 1, '#000'); |
| 323 drawText(plotCtx, | 318 drawText( |
| 324 tData[tDataIndex], | 319 plotCtx, tData[tDataIndex], |
| 325 x - getTextWidth(plotCtx, tData[tDataIndex]) / 2, | 320 x - getTextWidth(plotCtx, tData[tDataIndex]) / 2, yOrigin - 2); |
| 326 yOrigin - 2); | |
| 327 | 321 |
| 328 for (var count = 0; count < plots.length; count++) { | 322 for (var count = 0; count < plots.length; count++) { |
| 329 var yData = plots[count].data; | 323 var yData = plots[count].data; |
| 330 | 324 |
| 331 // Draw small black square on the plot where the time guide intersects | 325 // Draw small black square on the plot where the time guide intersects |
| 332 // it. | 326 // it. |
| 333 var val = yData[tDataIndex]; | 327 var val = yData[tDataIndex]; |
| 334 var yPos, valStr; | 328 var yPos, valStr; |
| 335 if (typeof val === 'string') { | 329 if (typeof val === 'string') { |
| 336 yPos = yOrigin + Math.round(height / 2); | 330 yPos = yOrigin + Math.round(height / 2); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 355 drawHighlightText(plotCtx, valStr, x + 5, yLoc, plots[count].color); | 349 drawHighlightText(plotCtx, valStr, x + 5, yLoc, plots[count].color); |
| 356 } | 350 } |
| 357 } | 351 } |
| 358 | 352 |
| 359 function onMouseOverOrMove(event) { | 353 function onMouseOverOrMove(event) { |
| 360 drawPlots(); | 354 drawPlots(); |
| 361 | 355 |
| 362 var boundingRect = plotCanvas.getBoundingClientRect(); | 356 var boundingRect = plotCanvas.getBoundingClientRect(); |
| 363 var x = Math.round((event.clientX - boundingRect.left) * devicePixelRatio); | 357 var x = Math.round((event.clientX - boundingRect.left) * devicePixelRatio); |
| 364 var y = Math.round((event.clientY - boundingRect.top) * devicePixelRatio); | 358 var y = Math.round((event.clientY - boundingRect.top) * devicePixelRatio); |
| 365 if (x < xOrigin || x >= xOrigin + width || | 359 if (x < xOrigin || x >= xOrigin + width || y < yOrigin || |
| 366 y < yOrigin || y >= yOrigin + height) { | 360 y >= yOrigin + height) { |
| 367 return; | 361 return; |
| 368 } | 362 } |
| 369 | 363 |
| 370 if (width == size) { | 364 if (width == size) { |
| 371 drawTimeGuide(x - xOrigin); | 365 drawTimeGuide(x - xOrigin); |
| 372 } else { | 366 } else { |
| 373 drawTimeGuide(Math.round((x - xOrigin) / (width - 1) * (size - 1))); | 367 drawTimeGuide(Math.round((x - xOrigin) / (width - 1) * (size - 1))); |
| 374 } | 368 } |
| 375 } | 369 } |
| 376 | 370 |
| 377 function onMouseOut(event) { | 371 function onMouseOut(event) { |
| 378 drawPlots(); | 372 drawPlots(); |
| 379 } | 373 } |
| 380 | 374 |
| 381 drawLegend(); | 375 drawLegend(); |
| 382 drawPlots(); | 376 drawPlots(); |
| 383 plotCanvas.addEventListener('mouseover', onMouseOverOrMove); | 377 plotCanvas.addEventListener('mouseover', onMouseOverOrMove); |
| 384 plotCanvas.addEventListener('mousemove', onMouseOverOrMove); | 378 plotCanvas.addEventListener('mousemove', onMouseOverOrMove); |
| 385 plotCanvas.addEventListener('mouseout', onMouseOut); | 379 plotCanvas.addEventListener('mouseout', onMouseOut); |
| 386 } | 380 } |
| 387 | 381 |
| 388 var sleepSampleInterval = 30 * 1000; // in milliseconds. | 382 var sleepSampleInterval = 30 * 1000; // in milliseconds. |
| 389 var sleepText = loadTimeData.getString('systemSuspended'); | 383 var sleepText = loadTimeData.getString('systemSuspended'); |
| 390 var invalidDataText = loadTimeData.getString('invalidData'); | 384 var invalidDataText = loadTimeData.getString('invalidData'); |
| 391 var offlineText = loadTimeData.getString('offlineText'); | 385 var offlineText = loadTimeData.getString('offlineText'); |
| 392 | 386 |
| 393 var plotColors = ['Red', 'Blue', 'Green', 'Gold', 'CadetBlue', 'LightCoral', | 387 var plotColors = [ |
| 394 'LightSlateGray', 'Peru', 'DarkRed', 'LawnGreen', 'Tan']; | 388 'Red', 'Blue', 'Green', 'Gold', 'CadetBlue', 'LightCoral', 'LightSlateGray', |
| 389 'Peru', 'DarkRed', 'LawnGreen', 'Tan' |
| 390 ]; |
| 395 | 391 |
| 396 /** | 392 /** |
| 397 * Add canvases for plotting to |plotsDiv|. For every header in |headerArray|, | 393 * Add canvases for plotting to |plotsDiv|. For every header in |headerArray|, |
| 398 * one canvas for the plot and one for its legend are added. | 394 * one canvas for the plot and one for its legend are added. |
| 399 * | 395 * |
| 400 * @param {Array<string>} headerArray Headers for the different plots to be | 396 * @param {Array<string>} headerArray Headers for the different plots to be |
| 401 * added to |plotsDiv|. | 397 * added to |plotsDiv|. |
| 402 * @param {HTMLDivElement} plotsDiv The div element into which the canvases | 398 * @param {HTMLDivElement} plotsDiv The div element into which the canvases |
| 403 * are added. | 399 * are added. |
| 404 * @return {<string>: {plotCanvas: <HTMLCanvasElement>, | 400 * @return {<string>: {plotCanvas: <HTMLCanvasElement>, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 * @param {number} sampleTime Time in milliseconds since the epoch when the | 454 * @param {number} sampleTime Time in milliseconds since the epoch when the |
| 459 * samples in |sampleArray| were captured. | 455 * samples in |sampleArray| were captured. |
| 460 * @param {number} previousSampleTime Time in milliseconds since the epoch | 456 * @param {number} previousSampleTime Time in milliseconds since the epoch |
| 461 * when the sample prior to the current sample was captured. | 457 * when the sample prior to the current sample was captured. |
| 462 * @param {Array<{time: number, sleepDuration: number}>} systemResumedArray An | 458 * @param {Array<{time: number, sleepDuration: number}>} systemResumedArray An |
| 463 * array objects corresponding to system resume events. The 'time' field is | 459 * array objects corresponding to system resume events. The 'time' field is |
| 464 * for the time in milliseconds since the epoch when the system resumed. The | 460 * for the time in milliseconds since the epoch when the system resumed. The |
| 465 * 'sleepDuration' field is for the time in milliseconds the system spent | 461 * 'sleepDuration' field is for the time in milliseconds the system spent |
| 466 * in sleep/suspend state. | 462 * in sleep/suspend state. |
| 467 */ | 463 */ |
| 468 function addTimeDataSample(plots, tData, absTime, sampleArray, | 464 function addTimeDataSample( |
| 469 sampleTime, previousSampleTime, | 465 plots, tData, absTime, sampleArray, sampleTime, previousSampleTime, |
| 470 systemResumedArray) { | 466 systemResumedArray) { |
| 471 for (var i = 0; i < plots.length; i++) { | 467 for (var i = 0; i < plots.length; i++) { |
| 472 if (plots[i].data.length != tData.length) { | 468 if (plots[i].data.length != tData.length) { |
| 473 throw new Error('Mismatch in time and plot data.'); | 469 throw new Error('Mismatch in time and plot data.'); |
| 474 } | 470 } |
| 475 } | 471 } |
| 476 | 472 |
| 477 var time; | 473 var time; |
| 478 if (tData.length == 0) { | 474 if (tData.length == 0) { |
| 479 time = new Date(sampleTime); | 475 time = new Date(sampleTime); |
| 480 absTime[0] = sampleTime; | 476 absTime[0] = sampleTime; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 * @param {Array<{time: ?, sleepDuration: ?}>} systemResumedArray An array | 526 * @param {Array<{time: ?, sleepDuration: ?}>} systemResumedArray An array |
| 531 * objects with fields 'time' and 'sleepDuration'. Each object corresponds | 527 * objects with fields 'time' and 'sleepDuration'. Each object corresponds |
| 532 * to a system resume event. The 'time' field is for the time in | 528 * to a system resume event. The 'time' field is for the time in |
| 533 * milliseconds since the epoch when the system resumed. The 'sleepDuration' | 529 * milliseconds since the epoch when the system resumed. The 'sleepDuration' |
| 534 * field is for the time in milliseconds the system spent in sleep/suspend | 530 * field is for the time in milliseconds the system spent in sleep/suspend |
| 535 * state. | 531 * state. |
| 536 */ | 532 */ |
| 537 function showBatteryChargeData(powerSupplyArray, systemResumedArray) { | 533 function showBatteryChargeData(powerSupplyArray, systemResumedArray) { |
| 538 var chargeTimeData = []; | 534 var chargeTimeData = []; |
| 539 var chargeAbsTime = []; | 535 var chargeAbsTime = []; |
| 540 var chargePlot = [ | 536 var chargePlot = [{ |
| 541 { | 537 name: loadTimeData.getString('batteryChargePercentageHeader'), |
| 542 name: loadTimeData.getString('batteryChargePercentageHeader'), | 538 color: 'Blue', |
| 543 color: 'Blue', | 539 data: [] |
| 544 data: [] | 540 }]; |
| 545 } | |
| 546 ]; | |
| 547 var dischargeRateTimeData = []; | 541 var dischargeRateTimeData = []; |
| 548 var dischargeRateAbsTime = []; | 542 var dischargeRateAbsTime = []; |
| 549 var dischargeRatePlot = [ | 543 var dischargeRatePlot = [ |
| 550 { | 544 { |
| 551 name: loadTimeData.getString('dischargeRateLegendText'), | 545 name: loadTimeData.getString('dischargeRateLegendText'), |
| 552 color: 'Red', | 546 color: 'Red', |
| 553 data: [] | 547 data: [] |
| 554 }, | 548 }, |
| 555 { | 549 { |
| 556 name: loadTimeData.getString('movingAverageLegendText'), | 550 name: loadTimeData.getString('movingAverageLegendText'), |
| 557 color: 'Green', | 551 color: 'Green', |
| 558 data: [] | 552 data: [] |
| 559 }, | 553 }, |
| 560 { | 554 { |
| 561 name: loadTimeData.getString('binnedAverageLegendText'), | 555 name: loadTimeData.getString('binnedAverageLegendText'), |
| 562 color: 'Blue', | 556 color: 'Blue', |
| 563 data: [] | 557 data: [] |
| 564 } | 558 } |
| 565 ]; | 559 ]; |
| 566 var minDischargeRate = 1000; // A high unrealistic number to begin with. | 560 var minDischargeRate = 1000; // A high unrealistic number to begin with. |
| 567 var maxDischargeRate = -1000; // A low unrealistic number to begin with. | 561 var maxDischargeRate = -1000; // A low unrealistic number to begin with. |
| 568 for (var i = 0; i < powerSupplyArray.length; i++) { | 562 for (var i = 0; i < powerSupplyArray.length; i++) { |
| 569 var j = Math.max(i - 1, 0); | 563 var j = Math.max(i - 1, 0); |
| 570 | 564 |
| 571 addTimeDataSample(chargePlot, | 565 addTimeDataSample( |
| 572 chargeTimeData, | 566 chargePlot, chargeTimeData, chargeAbsTime, |
| 573 chargeAbsTime, | 567 [powerSupplyArray[i].batteryPercent], powerSupplyArray[i].time, |
| 574 [powerSupplyArray[i].batteryPercent], | 568 powerSupplyArray[j].time, systemResumedArray); |
| 575 powerSupplyArray[i].time, | |
| 576 powerSupplyArray[j].time, | |
| 577 systemResumedArray); | |
| 578 | 569 |
| 579 var dischargeRate = powerSupplyArray[i].batteryDischargeRate; | 570 var dischargeRate = powerSupplyArray[i].batteryDischargeRate; |
| 580 var inputSampleCount = $('sample-count-input').value; | 571 var inputSampleCount = $('sample-count-input').value; |
| 581 | 572 |
| 582 var movingAverage = 0; | 573 var movingAverage = 0; |
| 583 var k = 0; | 574 var k = 0; |
| 584 for (k = 0; k < inputSampleCount && i - k >= 0; k++) { | 575 for (k = 0; k < inputSampleCount && i - k >= 0; k++) { |
| 585 movingAverage += powerSupplyArray[i - k].batteryDischargeRate; | 576 movingAverage += powerSupplyArray[i - k].batteryDischargeRate; |
| 586 } | 577 } |
| 587 // |k| will be atleast 1 because the 'min' value of the input field is 1. | 578 // |k| will be atleast 1 because the 'min' value of the input field is 1. |
| 588 movingAverage /= k; | 579 movingAverage /= k; |
| 589 | 580 |
| 590 var binnedAverage = 0; | 581 var binnedAverage = 0; |
| 591 for (k = 0; k < inputSampleCount; k++) { | 582 for (k = 0; k < inputSampleCount; k++) { |
| 592 var currentSampleIndex = i - i % inputSampleCount + k; | 583 var currentSampleIndex = i - i % inputSampleCount + k; |
| 593 if (currentSampleIndex >= powerSupplyArray.length) { | 584 if (currentSampleIndex >= powerSupplyArray.length) { |
| 594 break; | 585 break; |
| 595 } | 586 } |
| 596 | 587 |
| 597 binnedAverage += | 588 binnedAverage += |
| 598 powerSupplyArray[currentSampleIndex].batteryDischargeRate; | 589 powerSupplyArray[currentSampleIndex].batteryDischargeRate; |
| 599 } | 590 } |
| 600 binnedAverage /= k; | 591 binnedAverage /= k; |
| 601 | 592 |
| 602 minDischargeRate = Math.min(dischargeRate, minDischargeRate); | 593 minDischargeRate = Math.min(dischargeRate, minDischargeRate); |
| 603 maxDischargeRate = Math.max(dischargeRate, maxDischargeRate); | 594 maxDischargeRate = Math.max(dischargeRate, maxDischargeRate); |
| 604 addTimeDataSample(dischargeRatePlot, | 595 addTimeDataSample( |
| 605 dischargeRateTimeData, | 596 dischargeRatePlot, dischargeRateTimeData, dischargeRateAbsTime, |
| 606 dischargeRateAbsTime, | 597 [dischargeRate, movingAverage, binnedAverage], powerSupplyArray[i].time, |
| 607 [dischargeRate, movingAverage, binnedAverage], | 598 powerSupplyArray[j].time, systemResumedArray); |
| 608 powerSupplyArray[i].time, | |
| 609 powerSupplyArray[j].time, | |
| 610 systemResumedArray); | |
| 611 } | 599 } |
| 612 if (minDischargeRate == maxDischargeRate) { | 600 if (minDischargeRate == maxDischargeRate) { |
| 613 // This means that all the samples had the same value. Hence, offset the | 601 // This means that all the samples had the same value. Hence, offset the |
| 614 // extremes by a bit so that the plot looks good. | 602 // extremes by a bit so that the plot looks good. |
| 615 minDischargeRate -= 1; | 603 minDischargeRate -= 1; |
| 616 maxDischargeRate += 1; | 604 maxDischargeRate += 1; |
| 617 } | 605 } |
| 618 | 606 |
| 619 plotsDiv = $('battery-charge-plots-div'); | 607 plotsDiv = $('battery-charge-plots-div'); |
| 620 | 608 |
| 621 canvases = addCanvases( | 609 canvases = addCanvases( |
| 622 [loadTimeData.getString('batteryChargePercentageHeader'), | 610 [ |
| 623 loadTimeData.getString('batteryDischargeRateHeader')], | 611 loadTimeData.getString('batteryChargePercentageHeader'), |
| 612 loadTimeData.getString('batteryDischargeRateHeader') |
| 613 ], |
| 624 plotsDiv); | 614 plotsDiv); |
| 625 | 615 |
| 626 batteryChargeCanvases = canvases[ | 616 batteryChargeCanvases = |
| 627 loadTimeData.getString('batteryChargePercentageHeader')]; | 617 canvases[loadTimeData.getString('batteryChargePercentageHeader')]; |
| 628 plotLineGraph( | 618 plotLineGraph( |
| 629 batteryChargeCanvases['plot'], | 619 batteryChargeCanvases['plot'], batteryChargeCanvases['legend'], |
| 630 batteryChargeCanvases['legend'], | 620 chargeTimeData, chargePlot, 0.00, 100.00, 3); |
| 631 chargeTimeData, | |
| 632 chargePlot, | |
| 633 0.00, | |
| 634 100.00, | |
| 635 3); | |
| 636 | 621 |
| 637 dischargeRateCanvases = canvases[ | 622 dischargeRateCanvases = |
| 638 loadTimeData.getString('batteryDischargeRateHeader')]; | 623 canvases[loadTimeData.getString('batteryDischargeRateHeader')]; |
| 639 plotLineGraph( | 624 plotLineGraph( |
| 640 dischargeRateCanvases['plot'], | 625 dischargeRateCanvases['plot'], dischargeRateCanvases['legend'], |
| 641 dischargeRateCanvases['legend'], | 626 dischargeRateTimeData, dischargeRatePlot, minDischargeRate, |
| 642 dischargeRateTimeData, | 627 maxDischargeRate, 3); |
| 643 dischargeRatePlot, | |
| 644 minDischargeRate, | |
| 645 maxDischargeRate, | |
| 646 3); | |
| 647 } | 628 } |
| 648 | 629 |
| 649 /** | 630 /** |
| 650 * Shows state occupancy data (CPU idle or CPU freq state occupancy) on a set of | 631 * Shows state occupancy data (CPU idle or CPU freq state occupancy) on a set of |
| 651 * plots on the about:power UI. | 632 * plots on the about:power UI. |
| 652 * | 633 * |
| 653 * @param {Array<Array<{ | 634 * @param {Array<Array<{ |
| 654 * time: number, | 635 * time: number, |
| 655 * cpuOnline: boolean, | 636 * cpuOnline: boolean, |
| 656 * timeInState: Object<number>}>} timeInStateData Array of arrays | 637 * timeInState: Object<number>}>} timeInStateData Array of arrays |
| 657 * where each array corresponds to a CPU on the system. The elements of the | 638 * where each array corresponds to a CPU on the system. The elements of the |
| 658 * individual arrays contain state occupancy samples. | 639 * individual arrays contain state occupancy samples. |
| 659 * @param {Array<{time: ?, sleepDuration: ?}>} systemResumedArray An array | 640 * @param {Array<{time: ?, sleepDuration: ?}>} systemResumedArray An array |
| 660 * objects with fields 'time' and 'sleepDuration'. Each object corresponds | 641 * objects with fields 'time' and 'sleepDuration'. Each object corresponds |
| 661 * to a system resume event. The 'time' field is for the time in | 642 * to a system resume event. The 'time' field is for the time in |
| 662 * milliseconds since the epoch when the system resumed. The 'sleepDuration' | 643 * milliseconds since the epoch when the system resumed. The 'sleepDuration' |
| 663 * field is for the time in milliseconds the system spent in sleep/suspend | 644 * field is for the time in milliseconds the system spent in sleep/suspend |
| 664 * state. | 645 * state. |
| 665 * @param {string} i18nHeaderString The header string to be displayed with each | 646 * @param {string} i18nHeaderString The header string to be displayed with each |
| 666 * plot. For example, CPU idle data will have its own header format, and CPU | 647 * plot. For example, CPU idle data will have its own header format, and CPU |
| 667 * freq data will have its header format. | 648 * freq data will have its header format. |
| 668 * @param {string} unitString This is the string capturing the unit, if any, | 649 * @param {string} unitString This is the string capturing the unit, if any, |
| 669 * for the different states. Note that this is not the unit of the data | 650 * for the different states. Note that this is not the unit of the data |
| 670 * being plotted. | 651 * being plotted. |
| 671 * @param {HTMLDivElement} plotsDivId The div element in which the plots should | 652 * @param {HTMLDivElement} plotsDivId The div element in which the plots should |
| 672 * be added. | 653 * be added. |
| 673 */ | 654 */ |
| 674 function showStateOccupancyData(timeInStateData, | 655 function showStateOccupancyData( |
| 675 systemResumedArray, | 656 timeInStateData, systemResumedArray, i18nHeaderString, unitString, |
| 676 i18nHeaderString, | 657 plotsDivId) { |
| 677 unitString, | |
| 678 plotsDivId) { | |
| 679 var cpuPlots = []; | 658 var cpuPlots = []; |
| 680 for (var cpu = 0; cpu < timeInStateData.length; cpu++) { | 659 for (var cpu = 0; cpu < timeInStateData.length; cpu++) { |
| 681 var cpuData = timeInStateData[cpu]; | 660 var cpuData = timeInStateData[cpu]; |
| 682 if (cpuData.length == 0) { | 661 if (cpuData.length == 0) { |
| 683 cpuPlots[cpu] = {plots: [], tData: []}; | 662 cpuPlots[cpu] = {plots: [], tData: []}; |
| 684 continue; | 663 continue; |
| 685 } | 664 } |
| 686 tData = []; | 665 tData = []; |
| 687 absTime = []; | 666 absTime = []; |
| 688 // Each element of |plots| is an array of samples, one for each of the CPU | 667 // Each element of |plots| is an array of samples, one for each of the CPU |
| 689 // states. The number of states is dicovered by looking at the first | 668 // states. The number of states is dicovered by looking at the first |
| 690 // sample for which the CPU is online. | 669 // sample for which the CPU is online. |
| 691 var plots = []; | 670 var plots = []; |
| 692 var stateIndexMap = []; | 671 var stateIndexMap = []; |
| 693 var stateCount = 0; | 672 var stateCount = 0; |
| 694 for (var i = 0; i < cpuData.length; i++) { | 673 for (var i = 0; i < cpuData.length; i++) { |
| 695 if (cpuData[i].cpuOnline) { | 674 if (cpuData[i].cpuOnline) { |
| 696 for (var state in cpuData[i].timeInState) { | 675 for (var state in cpuData[i].timeInState) { |
| 697 var stateName = state; | 676 var stateName = state; |
| 698 if (unitString != null) { | 677 if (unitString != null) { |
| 699 stateName += ' ' + unitString; | 678 stateName += ' ' + unitString; |
| 700 } | 679 } |
| 701 plots.push({ | 680 plots.push( |
| 702 name: stateName, | 681 {name: stateName, data: [], color: plotColors[stateCount]}); |
| 703 data: [], | |
| 704 color: plotColors[stateCount] | |
| 705 }); | |
| 706 stateIndexMap.push(state); | 682 stateIndexMap.push(state); |
| 707 stateCount += 1; | 683 stateCount += 1; |
| 708 } | 684 } |
| 709 break; | 685 break; |
| 710 } | 686 } |
| 711 } | 687 } |
| 712 // If stateCount is 0, then it means the CPU has been offline | 688 // If stateCount is 0, then it means the CPU has been offline |
| 713 // throughout. Just add a single plot for such a case. | 689 // throughout. Just add a single plot for such a case. |
| 714 if (stateCount == 0) { | 690 if (stateCount == 0) { |
| 715 plots.push({ | 691 plots.push({name: null, data: [], color: null}); |
| 716 name: null, | 692 stateCount = 1; // Some invalid state! |
| 717 data: [], | |
| 718 color: null | |
| 719 }); | |
| 720 stateCount = 1; // Some invalid state! | |
| 721 } | 693 } |
| 722 | 694 |
| 723 // Pass the samples through the function addTimeDataSample to add 'sleep' | 695 // Pass the samples through the function addTimeDataSample to add 'sleep' |
| 724 // samples. | 696 // samples. |
| 725 for (var i = 0; i < cpuData.length; i++) { | 697 for (var i = 0; i < cpuData.length; i++) { |
| 726 var sample = cpuData[i]; | 698 var sample = cpuData[i]; |
| 727 var valArray = []; | 699 var valArray = []; |
| 728 for (var j = 0; j < stateCount; j++) { | 700 for (var j = 0; j < stateCount; j++) { |
| 729 if (sample.cpuOnline) { | 701 if (sample.cpuOnline) { |
| 730 valArray[j] = sample.timeInState[stateIndexMap[j]]; | 702 valArray[j] = sample.timeInState[stateIndexMap[j]]; |
| 731 } else { | 703 } else { |
| 732 valArray[j] = offlineText; | 704 valArray[j] = offlineText; |
| 733 } | 705 } |
| 734 } | 706 } |
| 735 | 707 |
| 736 var k = Math.max(i - 1, 0); | 708 var k = Math.max(i - 1, 0); |
| 737 addTimeDataSample(plots, | 709 addTimeDataSample( |
| 738 tData, | 710 plots, tData, absTime, valArray, sample.time, cpuData[k].time, |
| 739 absTime, | 711 systemResumedArray); |
| 740 valArray, | |
| 741 sample.time, | |
| 742 cpuData[k].time, | |
| 743 systemResumedArray); | |
| 744 } | 712 } |
| 745 | 713 |
| 746 // Calculate the percentage occupancy of each state. A valid number is | 714 // Calculate the percentage occupancy of each state. A valid number is |
| 747 // possible only if two consecutive samples are valid/numbers. | 715 // possible only if two consecutive samples are valid/numbers. |
| 748 for (var k = 0; k < stateCount; k++) { | 716 for (var k = 0; k < stateCount; k++) { |
| 749 var stateData = plots[k].data; | 717 var stateData = plots[k].data; |
| 750 // Skip the first sample as there is no previous sample. | 718 // Skip the first sample as there is no previous sample. |
| 751 for (var i = stateData.length - 1; i > 0; i--) { | 719 for (var i = stateData.length - 1; i > 0; i--) { |
| 752 if (typeof stateData[i] === 'number') { | 720 if (typeof stateData[i] === 'number') { |
| 753 if (typeof stateData[i - 1] === 'number') { | 721 if (typeof stateData[i - 1] === 'number') { |
| 754 stateData[i] = (stateData[i] - stateData[i - 1]) / | 722 stateData[i] = (stateData[i] - stateData[i - 1]) / |
| 755 (absTime[i] - absTime[i - 1]) * 100; | 723 (absTime[i] - absTime[i - 1]) * 100; |
| 756 } else { | 724 } else { |
| 757 stateData[i] = invalidDataText; | 725 stateData[i] = invalidDataText; |
| 758 } | 726 } |
| 759 } | 727 } |
| 760 } | 728 } |
| 761 } | 729 } |
| 762 | 730 |
| 763 // Remove the first sample from the time and data arrays. | 731 // Remove the first sample from the time and data arrays. |
| 764 tData.shift(); | 732 tData.shift(); |
| 765 for (var k = 0; k < stateCount; k++) { | 733 for (var k = 0; k < stateCount; k++) { |
| 766 plots[k].data.shift(); | 734 plots[k].data.shift(); |
| 767 } | 735 } |
| 768 cpuPlots[cpu] = {plots: plots, tData: tData}; | 736 cpuPlots[cpu] = {plots: plots, tData: tData}; |
| 769 } | 737 } |
| 770 | 738 |
| 771 headers = []; | 739 headers = []; |
| 772 for (var cpu = 0; cpu < timeInStateData.length; cpu++) { | 740 for (var cpu = 0; cpu < timeInStateData.length; cpu++) { |
| 773 headers[cpu] = | 741 headers[cpu] = |
| 774 'CPU ' + cpu + ' ' + loadTimeData.getString(i18nHeaderString); | 742 'CPU ' + cpu + ' ' + loadTimeData.getString(i18nHeaderString); |
| 775 } | 743 } |
| 776 | 744 |
| 777 canvases = addCanvases(headers, $(plotsDivId)); | 745 canvases = addCanvases(headers, $(plotsDivId)); |
| 778 for (var cpu = 0; cpu < timeInStateData.length; cpu++) { | 746 for (var cpu = 0; cpu < timeInStateData.length; cpu++) { |
| 779 cpuCanvases = canvases[headers[cpu]]; | 747 cpuCanvases = canvases[headers[cpu]]; |
| 780 plotLineGraph(cpuCanvases['plot'], | 748 plotLineGraph( |
| 781 cpuCanvases['legend'], | 749 cpuCanvases['plot'], cpuCanvases['legend'], cpuPlots[cpu]['tData'], |
| 782 cpuPlots[cpu]['tData'], | 750 cpuPlots[cpu]['plots'], 0, 100, 3); |
| 783 cpuPlots[cpu]['plots'], | |
| 784 0, | |
| 785 100, | |
| 786 3); | |
| 787 } | 751 } |
| 788 } | 752 } |
| 789 | 753 |
| 790 function showCpuIdleData(idleStateData, systemResumedArray) { | 754 function showCpuIdleData(idleStateData, systemResumedArray) { |
| 791 showStateOccupancyData(idleStateData, | 755 showStateOccupancyData( |
| 792 systemResumedArray, | 756 idleStateData, systemResumedArray, 'idleStateOccupancyPercentageHeader', |
| 793 'idleStateOccupancyPercentageHeader', | 757 null, 'cpu-idle-plots-div'); |
| 794 null, | |
| 795 'cpu-idle-plots-div'); | |
| 796 } | 758 } |
| 797 | 759 |
| 798 function showCpuFreqData(freqStateData, systemResumedArray) { | 760 function showCpuFreqData(freqStateData, systemResumedArray) { |
| 799 showStateOccupancyData(freqStateData, | 761 showStateOccupancyData( |
| 800 systemResumedArray, | 762 freqStateData, systemResumedArray, |
| 801 'frequencyStateOccupancyPercentageHeader', | 763 'frequencyStateOccupancyPercentageHeader', 'MHz', 'cpu-freq-plots-div'); |
| 802 'MHz', | |
| 803 'cpu-freq-plots-div'); | |
| 804 } | 764 } |
| 805 | 765 |
| 806 function requestBatteryChargeData() { | 766 function requestBatteryChargeData() { |
| 807 chrome.send('requestBatteryChargeData'); | 767 chrome.send('requestBatteryChargeData'); |
| 808 } | 768 } |
| 809 | 769 |
| 810 function requestCpuIdleData() { | 770 function requestCpuIdleData() { |
| 811 chrome.send('requestCpuIdleData'); | 771 chrome.send('requestCpuIdleData'); |
| 812 } | 772 } |
| 813 | 773 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 841 | 801 |
| 842 var powerUI = { | 802 var powerUI = { |
| 843 showBatteryChargeData: showBatteryChargeData, | 803 showBatteryChargeData: showBatteryChargeData, |
| 844 showCpuIdleData: showCpuIdleData, | 804 showCpuIdleData: showCpuIdleData, |
| 845 showCpuFreqData: showCpuFreqData | 805 showCpuFreqData: showCpuFreqData |
| 846 }; | 806 }; |
| 847 | 807 |
| 848 document.addEventListener('DOMContentLoaded', function() { | 808 document.addEventListener('DOMContentLoaded', function() { |
| 849 $('battery-charge-section').hidden = true; | 809 $('battery-charge-section').hidden = true; |
| 850 $('battery-charge-show-button').onclick = showHideCallback( | 810 $('battery-charge-show-button').onclick = showHideCallback( |
| 851 'battery-charge-section', | 811 'battery-charge-section', 'battery-charge-show-button', |
| 852 'battery-charge-show-button', | |
| 853 requestBatteryChargeData); | 812 requestBatteryChargeData); |
| 854 $('battery-charge-reload-button').onclick = requestBatteryChargeData; | 813 $('battery-charge-reload-button').onclick = requestBatteryChargeData; |
| 855 $('sample-count-input').onclick = requestBatteryChargeData; | 814 $('sample-count-input').onclick = requestBatteryChargeData; |
| 856 | 815 |
| 857 $('cpu-idle-section').hidden = true; | 816 $('cpu-idle-section').hidden = true; |
| 858 $('cpu-idle-show-button').onclick = showHideCallback( | 817 $('cpu-idle-show-button').onclick = showHideCallback( |
| 859 'cpu-idle-section', 'cpu-idle-show-button', requestCpuIdleData); | 818 'cpu-idle-section', 'cpu-idle-show-button', requestCpuIdleData); |
| 860 $('cpu-idle-reload-button').onclick = requestCpuIdleData; | 819 $('cpu-idle-reload-button').onclick = requestCpuIdleData; |
| 861 | 820 |
| 862 $('cpu-freq-section').hidden = true; | 821 $('cpu-freq-section').hidden = true; |
| 863 $('cpu-freq-show-button').onclick = showHideCallback( | 822 $('cpu-freq-show-button').onclick = showHideCallback( |
| 864 'cpu-freq-section', 'cpu-freq-show-button', requestCpuFreqData); | 823 'cpu-freq-section', 'cpu-freq-show-button', requestCpuFreqData); |
| 865 $('cpu-freq-reload-button').onclick = requestCpuFreqData; | 824 $('cpu-freq-reload-button').onclick = requestCpuFreqData; |
| 866 }); | 825 }); |
| OLD | NEW |