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 |