Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 * @constructor | 32 * @constructor |
| 33 * @extends {WebInspector.View} | 33 * @extends {WebInspector.View} |
| 34 * @param {WebInspector.TimelineModel} model | 34 * @param {WebInspector.TimelineModel} model |
| 35 */ | 35 */ |
| 36 WebInspector.TimelineOverviewPane = function(model) | 36 WebInspector.TimelineOverviewPane = function(model) |
| 37 { | 37 { |
| 38 WebInspector.View.call(this); | 38 WebInspector.View.call(this); |
| 39 this.element.id = "timeline-overview-panel"; | 39 this.element.id = "timeline-overview-panel"; |
| 40 this.element.addStyleClass("hbox"); | 40 this.element.addStyleClass("hbox"); |
| 41 | 41 |
| 42 this._powerProfileEnabled = WebInspector.experimentsSettings.powerProfile.is Enabled(); | |
| 43 if (this._powerProfileEnabled) | |
| 44 this.element.addStyleClass("with-power"); | |
| 45 | |
| 42 this._windowStartTime = 0; | 46 this._windowStartTime = 0; |
| 43 this._windowEndTime = Infinity; | 47 this._windowEndTime = Infinity; |
| 44 this._eventDividers = []; | 48 this._eventDividers = []; |
| 45 | 49 |
| 46 this._model = model; | 50 this._model = model; |
| 47 | 51 |
| 48 this._topPaneSidebarElement = document.createElement("div"); | 52 this._topPaneSidebarElement = document.createElement("div"); |
| 49 this._topPaneSidebarElement.id = "timeline-overview-sidebar"; | 53 this._topPaneSidebarElement.id = "timeline-overview-sidebar"; |
| 50 | 54 |
| 51 var overviewTreeElement = document.createElement("ol"); | 55 var overviewTreeElement = document.createElement("ol"); |
| 52 overviewTreeElement.className = "sidebar-tree vbox"; | 56 overviewTreeElement.className = "sidebar-tree vbox"; |
| 53 this._topPaneSidebarElement.appendChild(overviewTreeElement); | 57 this._topPaneSidebarElement.appendChild(overviewTreeElement); |
| 54 this.element.appendChild(this._topPaneSidebarElement); | 58 this.element.appendChild(this._topPaneSidebarElement); |
| 55 | 59 |
| 56 var topPaneSidebarTree = new TreeOutline(overviewTreeElement); | 60 var topPaneSidebarTree = new TreeOutline(overviewTreeElement); |
| 57 | 61 |
| 58 this._overviewItems = {}; | 62 this._overviewItems = {}; |
| 59 this._overviewItems[WebInspector.TimelineOverviewPane.Mode.Events] = new Web Inspector.SidebarTreeElement("timeline-overview-sidebar-events", | 63 this._overviewItems[WebInspector.TimelineOverviewPane.Mode.Events] = new Web Inspector.SidebarTreeElement("timeline-overview-sidebar-events", |
| 60 WebInspector.UIString("Events")); | 64 WebInspector.UIString("Events")); |
| 61 this._overviewItems[WebInspector.TimelineOverviewPane.Mode.Frames] = new Web Inspector.SidebarTreeElement("timeline-overview-sidebar-frames", | 65 this._overviewItems[WebInspector.TimelineOverviewPane.Mode.Frames] = new Web Inspector.SidebarTreeElement("timeline-overview-sidebar-frames", |
| 62 WebInspector.UIString("Frames")); | 66 WebInspector.UIString("Frames")); |
| 63 this._overviewItems[WebInspector.TimelineOverviewPane.Mode.Memory] = new Web Inspector.SidebarTreeElement("timeline-overview-sidebar-memory", | 67 this._overviewItems[WebInspector.TimelineOverviewPane.Mode.Memory] = new Web Inspector.SidebarTreeElement("timeline-overview-sidebar-memory", |
| 64 WebInspector.UIString("Memory")); | 68 WebInspector.UIString("Memory")); |
| 65 | 69 |
| 70 if (this._powerProfileEnabled) | |
| 71 this._overviewItems[WebInspector.TimelineOverviewPane.Mode.Power] = new WebInspector.SidebarTreeElement("timeline-overview-sidebar-power", | |
| 72 WebInspector.UIString("Power")) | |
| 73 | |
| 66 for (var mode in this._overviewItems) { | 74 for (var mode in this._overviewItems) { |
| 67 var item = this._overviewItems[mode]; | 75 var item = this._overviewItems[mode]; |
| 68 item.onselect = this.setMode.bind(this, mode); | 76 item.onselect = this.setMode.bind(this, mode); |
| 69 topPaneSidebarTree.appendChild(item); | 77 topPaneSidebarTree.appendChild(item); |
| 70 } | 78 } |
| 71 | 79 |
| 72 this._overviewGrid = new WebInspector.OverviewGrid("timeline"); | 80 this._overviewGrid = new WebInspector.OverviewGrid("timeline"); |
| 73 | 81 |
| 74 this.element.appendChild(this._overviewGrid.element); | 82 this.element.appendChild(this._overviewGrid.element); |
| 75 | 83 |
| 76 this._innerSetMode(WebInspector.TimelineOverviewPane.Mode.Events); | 84 this._innerSetMode(WebInspector.TimelineOverviewPane.Mode.Events); |
| 77 | 85 |
| 78 var categories = WebInspector.TimelinePresentationModel.categories(); | 86 var categories = WebInspector.TimelinePresentationModel.categories(); |
| 79 for (var category in categories) | 87 for (var category in categories) |
| 80 categories[category].addEventListener(WebInspector.TimelineCategory.Even ts.VisibilityChanged, this._onCategoryVisibilityChanged, this); | 88 categories[category].addEventListener(WebInspector.TimelineCategory.Even ts.VisibilityChanged, this._onCategoryVisibilityChanged, this); |
| 81 | 89 |
| 82 this._overviewCalculator = new WebInspector.TimelineOverviewCalculator(); | 90 this._overviewCalculator = new WebInspector.TimelineOverviewCalculator(); |
| 83 | 91 |
| 84 model.addEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._ onRecordAdded, this); | 92 model.addEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._ onRecordAdded, this); |
| 85 model.addEventListener(WebInspector.TimelineModel.Events.RecordsCleared, thi s._reset, this); | 93 model.addEventListener(WebInspector.TimelineModel.Events.RecordsCleared, thi s._reset, this); |
| 86 this._overviewGrid.addEventListener(WebInspector.OverviewGrid.Events.WindowC hanged, this._onWindowChanged, this); | 94 this._overviewGrid.addEventListener(WebInspector.OverviewGrid.Events.WindowC hanged, this._onWindowChanged, this); |
| 87 } | 95 } |
| 88 | 96 |
| 89 WebInspector.TimelineOverviewPane.Mode = { | 97 WebInspector.TimelineOverviewPane.Mode = { |
| 90 Events: "Events", | 98 Events: "Events", |
| 91 Frames: "Frames", | 99 Frames: "Frames", |
| 92 Memory: "Memory" | 100 Memory: "Memory", |
| 101 Power: "Power" | |
| 93 }; | 102 }; |
| 94 | 103 |
| 95 WebInspector.TimelineOverviewPane.Events = { | 104 WebInspector.TimelineOverviewPane.Events = { |
| 96 ModeChanged: "ModeChanged", | 105 ModeChanged: "ModeChanged", |
| 97 WindowChanged: "WindowChanged" | 106 WindowChanged: "WindowChanged" |
| 98 }; | 107 }; |
| 99 | 108 |
| 100 WebInspector.TimelineOverviewPane.prototype = { | 109 WebInspector.TimelineOverviewPane.prototype = { |
| 101 wasShown: function() | 110 wasShown: function() |
| 102 { | 111 { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 138 */ | 147 */ |
| 139 _createOverviewControl: function() | 148 _createOverviewControl: function() |
| 140 { | 149 { |
| 141 switch (this._currentMode) { | 150 switch (this._currentMode) { |
| 142 case WebInspector.TimelineOverviewPane.Mode.Events: | 151 case WebInspector.TimelineOverviewPane.Mode.Events: |
| 143 return new WebInspector.TimelineEventOverview(this._model); | 152 return new WebInspector.TimelineEventOverview(this._model); |
| 144 case WebInspector.TimelineOverviewPane.Mode.Frames: | 153 case WebInspector.TimelineOverviewPane.Mode.Frames: |
| 145 return new WebInspector.TimelineFrameOverview(this._model); | 154 return new WebInspector.TimelineFrameOverview(this._model); |
| 146 case WebInspector.TimelineOverviewPane.Mode.Memory: | 155 case WebInspector.TimelineOverviewPane.Mode.Memory: |
| 147 return new WebInspector.TimelineMemoryOverview(this._model); | 156 return new WebInspector.TimelineMemoryOverview(this._model); |
| 157 case WebInspector.TimelineOverviewPane.Mode.Power: | |
| 158 if (this._powerProfileEnabled) { | |
| 159 return new WebInspector.TimelinePowerOverview(this._model, this. _windowStartTime, this._windowEndTime); | |
| 160 } else { | |
| 161 this._currentMode = WebInspector.TimelineOverviewPane.Mode.Event s; | |
| 162 return new WebInspector.TimelineEventOverview(this._model); | |
| 163 } | |
| 148 } | 164 } |
| 149 throw new Error("Invalid overview mode: " + this._currentMode); | 165 throw new Error("Invalid overview mode: " + this._currentMode); |
| 150 }, | 166 }, |
| 151 | 167 |
| 152 _onCategoryVisibilityChanged: function(event) | 168 _onCategoryVisibilityChanged: function(event) |
| 153 { | 169 { |
| 154 this._overviewControl.categoryVisibilityChanged(); | 170 this._overviewControl.categoryVisibilityChanged(); |
| 155 }, | 171 }, |
| 156 | 172 |
| 157 _update: function() | 173 _update: function() |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 251 windowLeft: function() | 267 windowLeft: function() |
| 252 { | 268 { |
| 253 return this._overviewGrid.windowLeft(); | 269 return this._overviewGrid.windowLeft(); |
| 254 }, | 270 }, |
| 255 | 271 |
| 256 windowRight: function() | 272 windowRight: function() |
| 257 { | 273 { |
| 258 return this._overviewGrid.windowRight(); | 274 return this._overviewGrid.windowRight(); |
| 259 }, | 275 }, |
| 260 | 276 |
| 261 _onWindowChanged: function() | 277 _onWindowChanged: function(timeLeft, timeRight) |
| 262 { | 278 { |
| 263 if (this._ignoreWindowChangedEvent) | 279 if (this._ignoreWindowChangedEvent) |
| 264 return; | 280 return; |
| 265 var times = this._overviewControl.windowTimes(this.windowLeft(), this.wi ndowRight()); | 281 var times = this._overviewControl.windowTimes(this.windowLeft(), this.wi ndowRight()); |
| 282 this._overviewControl.windowChanged(times.startTime, times.endTime); | |
| 266 this._windowStartTime = times.startTime; | 283 this._windowStartTime = times.startTime; |
| 267 this._windowEndTime = times.endTime; | 284 this._windowEndTime = times.endTime; |
| 268 this.dispatchEventToListeners(WebInspector.TimelineOverviewPane.Events.W indowChanged); | 285 this.dispatchEventToListeners(WebInspector.TimelineOverviewPane.Events.W indowChanged); |
| 269 }, | 286 }, |
| 270 | 287 |
| 271 /** | 288 /** |
| 272 * @param {Number} startTime | 289 * @param {Number} startTime |
| 273 * @param {Number} endTime | 290 * @param {Number} endTime |
| 274 */ | 291 */ |
| 275 setWindowTimes: function(startTime, endTime) | 292 setWindowTimes: function(startTime, endTime) |
| 276 { | 293 { |
| 277 this._windowStartTime = startTime; | 294 this._windowStartTime = startTime; |
| 278 this._windowEndTime = endTime; | 295 this._windowEndTime = endTime; |
| 279 this._updateWindow(); | 296 this._updateWindow(); |
| 280 }, | 297 }, |
| 281 | 298 |
| 282 _updateWindow: function() | 299 _updateWindow: function() |
| 283 { | 300 { |
| 284 var windowBoundaries = this._overviewControl.windowBoundaries(this._wind owStartTime, this._windowEndTime); | 301 var windowBoundaries = this._overviewControl.windowBoundaries(this._wind owStartTime, this._windowEndTime); |
| 285 this._ignoreWindowChangedEvent = true; | 302 this._ignoreWindowChangedEvent = true; |
| 286 this._overviewGrid.setWindow(windowBoundaries.left, windowBoundaries.rig ht); | 303 // frame overview will return zero windowBoundaries when no frame bar we re covered, we should avoid this. |
| 304 if (!(this._windowStartTime < this._windowEndTime && windowBoundaries.le ft === 0 && windowBoundaries.right === 0)) | |
| 305 this._overviewGrid.setWindow(windowBoundaries.left, windowBoundaries.r ight); | |
| 287 this._overviewGrid.setResizeEnabled(this._model.records.length); | 306 this._overviewGrid.setResizeEnabled(this._model.records.length); |
| 288 this._ignoreWindowChangedEvent = false; | 307 this._ignoreWindowChangedEvent = false; |
| 289 }, | 308 }, |
| 290 | 309 |
| 291 _scheduleRefresh: function() | 310 _scheduleRefresh: function() |
| 292 { | 311 { |
| 293 if (this._refreshTimeout) | 312 if (this._refreshTimeout) |
| 294 return; | 313 return; |
| 295 if (!this.isShowing()) | 314 if (!this.isShowing()) |
| 296 return; | 315 return; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 392 | 411 |
| 393 this._model = model; | 412 this._model = model; |
| 394 this._canvas = this.element.createChild("canvas", "fill"); | 413 this._canvas = this.element.createChild("canvas", "fill"); |
| 395 this._context = this._canvas.getContext("2d"); | 414 this._context = this._canvas.getContext("2d"); |
| 396 } | 415 } |
| 397 | 416 |
| 398 WebInspector.TimelineOverviewBase.prototype = { | 417 WebInspector.TimelineOverviewBase.prototype = { |
| 399 update: function() { }, | 418 update: function() { }, |
| 400 reset: function() { }, | 419 reset: function() { }, |
| 401 | 420 |
| 421 windowChanged: function(timeLeft, timeRight) { }, | |
| 422 | |
| 402 categoryVisibilityChanged: function() { }, | 423 categoryVisibilityChanged: function() { }, |
| 403 | 424 |
| 404 /** | 425 /** |
| 405 * @param {WebInspector.TimelineFrame} frame | 426 * @param {WebInspector.TimelineFrame} frame |
| 406 */ | 427 */ |
| 407 addFrame: function(frame) { }, | 428 addFrame: function(frame) { }, |
| 408 | 429 |
| 409 /** | 430 /** |
| 410 * @param {number} windowLeft | 431 * @param {number} windowLeft |
| 411 * @param {number} windowRight | 432 * @param {number} windowRight |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1018 */ | 1039 */ |
| 1019 _firstBarAfter: function(time, comparator) | 1040 _firstBarAfter: function(time, comparator) |
| 1020 { | 1041 { |
| 1021 return insertionIndexForObjectInListSortedByFunction(time, this._barTime s, comparator); | 1042 return insertionIndexForObjectInListSortedByFunction(time, this._barTime s, comparator); |
| 1022 }, | 1043 }, |
| 1023 | 1044 |
| 1024 __proto__: WebInspector.TimelineOverviewBase.prototype | 1045 __proto__: WebInspector.TimelineOverviewBase.prototype |
| 1025 } | 1046 } |
| 1026 | 1047 |
| 1027 /** | 1048 /** |
| 1049 * @constructor | |
| 1050 * @extends {WebInspector.TimelineOverviewBase} | |
| 1051 * @param {WebInspector.TimelineModel} model | |
| 1052 */ | |
| 1053 WebInspector.TimelinePowerOverview = function(model, windowStartTime, windowEndT ime) | |
|
pfeldman
2014/01/09 11:38:52
This change probably needs merging. Could you reba
Pan
2014/02/24 09:49:47
rebased, thanks!
| |
| 1054 { | |
| 1055 WebInspector.TimelineOverviewBase.call(this, model); | |
| 1056 this.element.id = "timeline-overview-power"; | |
| 1057 this._canvas.addEventListener("mousemove", this._onMouseMove.bind(this)); | |
| 1058 this._powerEventsHistogram = []; | |
| 1059 this._maxPower = 0; | |
| 1060 this._minPower = 0; | |
| 1061 this._yFactor = 0; | |
| 1062 this._powerDrawHeight = 0; | |
| 1063 this._windowStartTime = windowStartTime; | |
| 1064 this._windowEndTime = windowEndTime; | |
| 1065 } | |
| 1066 | |
| 1067 WebInspector.TimelinePowerOverview.prototype = { | |
| 1068 windowChanged: function(startTime, endTime) | |
| 1069 { | |
| 1070 this._windowStartTime = startTime; | |
| 1071 this._windowEndTime = endTime; | |
| 1072 this._drawEnergy(startTime, endTime); | |
| 1073 }, | |
| 1074 | |
| 1075 _calculateEnergyInSelectedRegion: function(startX, endX) { | |
| 1076 | |
| 1077 // if pos is on the power event, just the prev and next will be similer to pos | |
| 1078 function findAdjacents(pos, histograms) { | |
| 1079 var prevPowerEventIndex; | |
| 1080 var nextPowerEventIndex; | |
| 1081 // find previous power Event | |
| 1082 for(var i = pos; i >= 0; i--) { | |
| 1083 if (histograms[i]) { | |
| 1084 prevPowerEventIndex = i; | |
| 1085 break; | |
| 1086 } | |
| 1087 } | |
| 1088 // find next Event | |
| 1089 for(var i = pos; i < histograms.length; i++) { | |
| 1090 if (histograms[i]) { | |
| 1091 nextPowerEventIndex= i; | |
| 1092 break; | |
| 1093 } | |
| 1094 } | |
| 1095 // as pos may fall into a blank region, which only have next or prev . in this case we will return 0 timespance | |
| 1096 return { | |
| 1097 prev : prevPowerEventIndex, | |
| 1098 next : nextPowerEventIndex, | |
| 1099 timeSpan : (!prevPowerEventIndex || !nextPowerEventIndex) ? 0 : (histograms[nextPowerEventIndex].startTime - histograms[prevPowerEventIndex].sta rtTime) / 1000, // in seconds | |
| 1100 xSpan : (!prevPowerEventIndex || !nextPowerEventIndex) ? 0 : (ne xtPowerEventIndex - prevPowerEventIndex), | |
| 1101 power : (!nextPowerEventIndex) ? 0 : histograms[nextPowerEventIn dex].value | |
| 1102 }; | |
| 1103 } | |
| 1104 | |
| 1105 var energy = 0; | |
| 1106 var startAdjancents = findAdjacents(startX, this._powerEventsHistogram); | |
| 1107 var endAdjancents = findAdjacents(endX, this._powerEventsHistogram); | |
| 1108 | |
| 1109 // cross a power event | |
| 1110 if (startAdjancents.prev !== endAdjancents.prev) { | |
| 1111 | |
| 1112 if (startAdjancents.timeSpan) | |
| 1113 energy += (startAdjancents.next - startX) / startAdjancents.xSpan * startAdjancents.timeSpan * startAdjancents.power; | |
| 1114 | |
| 1115 if (endAdjancents.timeSpan) | |
| 1116 energy += (endX- endAdjancents.prev) / endAdjancents.xSpan * endAdja ncents.timeSpan * endAdjancents.power; | |
| 1117 | |
| 1118 } else { //start and end are in the same power event duration. | |
| 1119 energy += (endX - startX) / startAdjancents.xSpan * startAdjancents. timeSpan * endAdjancents.power; | |
| 1120 } | |
| 1121 | |
| 1122 var prevX = -1; | |
| 1123 for(var i = startX; i <= endX; i++) { | |
| 1124 if (!this._powerEventsHistogram[i]) | |
| 1125 continue; | |
| 1126 if (prevX !== -1) { | |
| 1127 var timeSpan = (this._powerEventsHistogram[i].startTime- this._p owerEventsHistogram[prevX].startTime) / 1000; | |
| 1128 energy += timeSpan * this._powerEventsHistogram[i].value; | |
| 1129 } | |
| 1130 prevX = i; | |
| 1131 } | |
| 1132 return energy; | |
| 1133 | |
| 1134 }, | |
| 1135 | |
| 1136 _drawEnergy: function(startTime, endTime) { | |
| 1137 // clear power value firstly | |
| 1138 this._restorePowerMarker(); | |
| 1139 | |
| 1140 var startX = Math.round(this._xFactor * (startTime - this._model.minimum RecordTime())); | |
| 1141 var endX = Math.round(this._xFactor * (endTime- this._model.minimumRecor dTime())); | |
| 1142 | |
| 1143 var energy = this._calculateEnergyInSelectedRegion(startX, endX); | |
| 1144 | |
| 1145 this._restoreImageUnderMarker(this._energyTextSaver); | |
| 1146 if (energy) | |
| 1147 this._drawEnergyText(startX, endX, energy); | |
| 1148 }, | |
| 1149 | |
| 1150 _createTextLabel: function(labelName) | |
| 1151 { | |
| 1152 const labelPadding = 4 * window.devicePixelRatio; | |
| 1153 var labelWidth = this._context.measureText(labelName).width + 2 * labelP adding; | |
| 1154 var contextFont = this._context.font; | |
| 1155 var labelHeight = contextFont.substr(0, contextFont.indexOf("px ")) - 0; | |
| 1156 return { name : labelName, | |
| 1157 width : labelWidth, | |
| 1158 height : labelHeight | |
| 1159 }; | |
| 1160 }, | |
| 1161 | |
| 1162 _drawEnergyText: function(startX, endX, energyValue) | |
| 1163 { | |
| 1164 var label = this._createTextLabel(WebInspector.UIString("%.2f\u2009joule ", energyValue)); | |
| 1165 var textXPos = (startX + endX) > label.width ? Math.round((startX + endX - label.width) / 2) : Math.round((startX + endX) / 2); | |
| 1166 var textYPos = Math.round(this._powerDrawHeight / 2); | |
| 1167 this._context.beginPath(); | |
| 1168 this._energyTextSaver = this._saveRectImageUnderMarker(textXPos, textYPo s - label.height, label.width, label.height + 2); | |
| 1169 this._context.strokeStyle = "black"; | |
| 1170 this._context.fillStyle = "black"; | |
| 1171 this._context.fillText(label.name, textXPos, textYPos); | |
| 1172 this._context.stroke(); | |
| 1173 }, | |
| 1174 | |
| 1175 _resetPowerBoundaries: function(allRecords) | |
| 1176 { | |
| 1177 var maxPower = 0; | |
| 1178 var minPower = 100000000000; | |
| 1179 var minTime = this._model.minimumRecordTime(); | |
| 1180 WebInspector.TimelinePresentationModel.forAllRecords(allRecords, functio n(r) { | |
| 1181 if (r.type !== WebInspector.TimelineModel.RecordType.SoC_Package || WebInspector.TimelineModel.endTimeInSeconds(r) < minTime) | |
| 1182 return; | |
| 1183 maxPower = Math.max(maxPower, r.value); | |
| 1184 minPower = Math.min(minPower, r.value); | |
| 1185 }); | |
| 1186 minPower = Math.min(minPower, maxPower); | |
| 1187 this._maxPower = maxPower; | |
| 1188 this._minPower = minPower; | |
| 1189 }, | |
| 1190 | |
| 1191 _prepareHistograms: function(allRecords) | |
| 1192 { | |
| 1193 const lowerOffset = 3; | |
| 1194 var width = this._canvas.width; | |
| 1195 var height = this._canvas.height - lowerOffset; | |
| 1196 var minTime = this._model.minimumRecordTime(); | |
| 1197 var maxTime = this._model.maximumRecordTime(); | |
| 1198 var xFactor = width / (maxTime - minTime); | |
| 1199 var yFactor = height / (this._maxPower - this._minPower); | |
| 1200 this._xFactor = xFactor; | |
| 1201 this._yFactor = yFactor; | |
| 1202 | |
| 1203 var histogram = new Array(width); | |
| 1204 var powerEventsHistogram = new Array(width); | |
| 1205 var minPower = this._minPower; | |
| 1206 WebInspector.TimelinePresentationModel.forAllRecords(allRecords, functio n(r) { | |
| 1207 if (r.type !== WebInspector.TimelineModel.RecordType.SoC_Package || WebInspector.TimelineModel.endTimeInSeconds(r) < minTime) | |
| 1208 return; | |
| 1209 var x = Math.round((WebInspector.TimelineModel.endTimeInSeconds(r) - minTime) * xFactor); | |
| 1210 var y = Math.round((r.value- minPower ) * yFactor); | |
| 1211 histogram[x] = Math.max(histogram[x] || 0, y); | |
| 1212 powerEventsHistogram[x] = r; | |
| 1213 }); | |
| 1214 | |
| 1215 this._powerEventsHistogram = powerEventsHistogram; | |
| 1216 | |
| 1217 // +1 so that the border always fit into the canvas area. | |
| 1218 this._powerDrawHeight = height + 1; | |
| 1219 | |
| 1220 return histogram; | |
| 1221 }, | |
| 1222 | |
| 1223 update: function() | |
| 1224 { | |
| 1225 this._resetCanvas(); | |
| 1226 delete this._pointSaver; | |
| 1227 delete this._powerTextSaver; | |
| 1228 delete this._energyTextSaver; | |
| 1229 | |
| 1230 this._powerEventsHistogram = []; | |
| 1231 this._yFactor = 0; | |
| 1232 | |
| 1233 var records = this._model.records; | |
| 1234 if (!records.length) | |
| 1235 return; | |
| 1236 | |
| 1237 this._resetPowerBoundaries(records); | |
| 1238 | |
| 1239 var histogram = this._prepareHistograms(records); | |
| 1240 | |
| 1241 var height = this._powerDrawHeight; | |
| 1242 // draw gridline | |
| 1243 this._drawGridline(this._minPower, this._maxPower, height); | |
| 1244 | |
| 1245 // draw power graph | |
| 1246 // as we only have power samples in timestamp, we should eliminated the first event as we don't know its start point of time period. | |
| 1247 var initialX = 0; | |
| 1248 var initialY = 0; | |
| 1249 var previousX = 0; | |
| 1250 for (var k = 0; k < histogram.length; k++) { | |
| 1251 var value = histogram[k]; | |
| 1252 if (value !== undefined) { | |
| 1253 initialX = k; | |
| 1254 previousX = k; | |
| 1255 initialY = value; | |
| 1256 break; | |
| 1257 } | |
| 1258 } | |
| 1259 | |
| 1260 var ctx = this._context; | |
| 1261 ctx.beginPath(); | |
| 1262 var isFirst = true; | |
| 1263 | |
| 1264 for (var x = previousX + 1; x < histogram.length; x++) { | |
| 1265 if (histogram[x] === undefined) | |
| 1266 continue; | |
| 1267 var currentY = height - histogram[x]; | |
| 1268 if (!isFirst) { | |
| 1269 ctx.lineTo(previousX, currentY); | |
| 1270 } else { | |
| 1271 ctx.moveTo(initialX, currentY); | |
| 1272 isFirst = false; | |
| 1273 } | |
| 1274 ctx.lineTo(x, currentY); | |
| 1275 previousX = x; | |
| 1276 } | |
| 1277 | |
| 1278 ctx.lineWidth = 0.5; | |
| 1279 ctx.strokeStyle = "rgba(20,0,0,0.8)"; | |
| 1280 ctx.stroke(); | |
| 1281 | |
| 1282 ctx.fillStyle = "rgba(255,192,0, 0.8);"; | |
| 1283 ctx.lineTo(previousX, this._canvas.height); | |
| 1284 ctx.lineTo(initialX, this._canvas.height); | |
| 1285 ctx.lineTo(initialX, height - initialY); | |
| 1286 ctx.fill(); | |
| 1287 ctx.closePath(); | |
| 1288 | |
| 1289 // draw energy for a selected time period | |
| 1290 if (this._windowStartTime > 0 && this._windowEndTime < Infinity && this. _windowStartTime < this._windowEndTime) | |
| 1291 this._drawEnergy(this._windowStartTime, this._windowEndTime); | |
| 1292 }, | |
| 1293 | |
| 1294 _drawGridline: function(minPower, maxPower, height) | |
| 1295 { | |
| 1296 var ctx = this._context; | |
| 1297 var width = this._canvas.width; | |
| 1298 var yFactor = (maxPower - minPower) / height; | |
| 1299 const labelPadding = 4 * window.devicePixelRatio; | |
| 1300 | |
| 1301 ctx.strokeStyle = "rgba(128,128,128,0.5)"; | |
| 1302 var gridHeight = height / 4; | |
| 1303 var yPositions = []; | |
| 1304 var powerScales = []; | |
| 1305 | |
| 1306 for (var i = 1; i < 4; i++) { | |
| 1307 var yPos = Math.round(gridHeight * i) - 0.5; | |
| 1308 var powerScale = yFactor * (height - yPos) + minPower; | |
| 1309 | |
| 1310 //draw gridline | |
| 1311 ctx.beginPath(); | |
| 1312 ctx.moveTo(0, yPos); | |
| 1313 ctx.lineTo(width, yPos); | |
| 1314 ctx.stroke(); | |
| 1315 | |
| 1316 //draw scale for gridline | |
| 1317 if (!powerScale) | |
| 1318 continue; | |
| 1319 ctx.beginPath(); | |
| 1320 var label = this._createTextLabel(WebInspector.UIString("%.2f\u2009w att", powerScale)); | |
| 1321 ctx.save(); | |
| 1322 this._context.fillStyle = "black"; | |
| 1323 ctx.fillText(label.name, 2, yPos - 2); | |
| 1324 ctx.stroke(); | |
| 1325 ctx.restore(); | |
| 1326 } | |
| 1327 }, | |
| 1328 | |
| 1329 _restorePowerMarker: function() | |
| 1330 { | |
| 1331 this._restoreImageUnderMarker(this._pointSaver); | |
| 1332 delete this._pointSaver; | |
| 1333 | |
| 1334 this._restoreImageUnderMarker(this._powerTextSaver); | |
| 1335 delete this._powerTextSaver; | |
| 1336 }, | |
| 1337 | |
| 1338 _onMouseMove: function(event) | |
| 1339 { | |
| 1340 this._restorePowerMarker(); | |
| 1341 var powerValue; | |
| 1342 var index = Math.round(event.offsetX); | |
| 1343 var isInBlankArea = true; | |
| 1344 for (var i = 0; i < index + 1; i++) { | |
| 1345 if (this._powerEventsHistogram[i]) { | |
| 1346 isInBlankArea = false; | |
| 1347 break; | |
| 1348 } | |
| 1349 } | |
| 1350 if (isInBlankArea) | |
| 1351 return; | |
| 1352 | |
| 1353 for (var i = index + 1; i < this._powerEventsHistogram.length; i++) { | |
| 1354 if (this._powerEventsHistogram[i]) { | |
| 1355 powerValue = this._powerEventsHistogram[i].value; | |
| 1356 break; | |
| 1357 } | |
| 1358 } | |
| 1359 | |
| 1360 var xPos = event.offsetX; | |
| 1361 var yPos = this._powerDrawHeight - Math.round(this._yFactor * (powerValu e - this._minPower)); | |
| 1362 this._drawPoint(xPos, yPos); | |
| 1363 | |
| 1364 this._drawPowerText(xPos, yPos, powerValue); | |
| 1365 }, | |
| 1366 | |
| 1367 _drawPoint: function(xPos, yPos) | |
| 1368 { | |
| 1369 const radius = 2; | |
| 1370 this._pointSaver = this._saveArcImageUnderMarker(xPos, yPos, radius); | |
| 1371 this._context.beginPath(); | |
| 1372 this._context.arc(xPos, yPos, radius, Math.PI*2, false) | |
| 1373 this._context.strokeStyle = "red"; | |
| 1374 this._context.fillStyle = "red"; | |
| 1375 this._context.fill(); | |
| 1376 this._context.stroke(); | |
| 1377 }, | |
| 1378 | |
| 1379 _drawPowerText: function(xPointPos, yPointPos, powerValue) | |
| 1380 { | |
| 1381 var label = this._createTextLabel(WebInspector.UIString("%.2f\u2009watt" , powerValue)); | |
| 1382 var textYPos = yPointPos - 3 - label.height > 0 ? yPointPos - 3: yPointP os + 3 + label.height; | |
| 1383 var textXPos = xPointPos + label.width > this._canvas.width ? this._canv as.width - label.width : xPointPos; | |
| 1384 this._context.beginPath(); | |
| 1385 this._powerTextSaver = this._saveRectImageUnderMarker(textXPos, textYPos - label.height, label.width, label.height); | |
| 1386 this._context.fillText(label.name, textXPos, textYPos); | |
| 1387 this._context.stroke(); | |
| 1388 }, | |
| 1389 | |
| 1390 _saveArcImageUnderMarker: function(x, y, radius) | |
| 1391 { | |
| 1392 const w = radius + 1; | |
| 1393 var imageData = this._context.getImageData(x - w, y - w, 2 * w, 2 * w); | |
| 1394 return { | |
| 1395 x: x - w, | |
| 1396 y: y - w, | |
| 1397 imageData: imageData | |
| 1398 }; | |
| 1399 }, | |
| 1400 | |
| 1401 _saveRectImageUnderMarker: function(x, y, w, h) | |
| 1402 { | |
| 1403 var imageData = this._context.getImageData(x, y, w, h); | |
| 1404 return { | |
| 1405 x: x, | |
| 1406 y: y, | |
| 1407 imageData: imageData | |
| 1408 }; | |
| 1409 }, | |
| 1410 | |
| 1411 | |
| 1412 _restoreImageUnderMarker: function(imageUnderMarker) | |
| 1413 { | |
| 1414 if (imageUnderMarker) | |
| 1415 this._context.putImageData(imageUnderMarker.imageData, imageUnderMar ker.x, imageUnderMarker.y); | |
| 1416 }, | |
| 1417 | |
| 1418 __proto__: WebInspector.TimelineOverviewBase.prototype | |
| 1419 } | |
| 1420 | |
| 1421 /** | |
| 1028 * @param {WebInspector.TimelineOverviewPane} pane | 1422 * @param {WebInspector.TimelineOverviewPane} pane |
| 1029 * @constructor | 1423 * @constructor |
| 1030 * @implements {WebInspector.TimelinePresentationModel.Filter} | 1424 * @implements {WebInspector.TimelinePresentationModel.Filter} |
| 1031 */ | 1425 */ |
| 1032 WebInspector.TimelineWindowFilter = function(pane) | 1426 WebInspector.TimelineWindowFilter = function(pane) |
| 1033 { | 1427 { |
| 1034 this._pane = pane; | 1428 this._pane = pane; |
| 1035 } | 1429 } |
| 1036 | 1430 |
| 1037 WebInspector.TimelineWindowFilter.prototype = { | 1431 WebInspector.TimelineWindowFilter.prototype = { |
| 1038 /** | 1432 /** |
| 1039 * @param {!WebInspector.TimelinePresentationModel.Record} record | 1433 * @param {!WebInspector.TimelinePresentationModel.Record} record |
| 1040 * @return {boolean} | 1434 * @return {boolean} |
| 1041 */ | 1435 */ |
| 1042 accept: function(record) | 1436 accept: function(record) |
| 1043 { | 1437 { |
| 1044 return record.lastChildEndTime >= this._pane._windowStartTime && record. startTime <= this._pane._windowEndTime; | 1438 return record.lastChildEndTime >= this._pane._windowStartTime && record. startTime <= this._pane._windowEndTime; |
| 1045 } | 1439 } |
| 1046 } | 1440 } |
| OLD | NEW |