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 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
101 /** | 101 /** |
102 * @interface | 102 * @interface |
103 */ | 103 */ |
104 WebInspector.FlameChartDataProvider = function() | 104 WebInspector.FlameChartDataProvider = function() |
105 { | 105 { |
106 } | 106 } |
107 | 107 |
108 /** @typedef {!{ | 108 /** @typedef {!{ |
109 entryLevels: !Array.<number>, | 109 entryLevels: !Array.<number>, |
110 entryTotalTimes: !Array.<number>, | 110 entryTotalTimes: !Array.<number>, |
111 entryOffsets: !Array.<number>, | 111 entryOffsets: !Array.<number> |
112 colorEntryIndexes: !Array.<number> | |
113 }} | 112 }} |
114 */ | 113 */ |
115 WebInspector.FlameChart.TimelineData; | 114 WebInspector.FlameChart.TimelineData; |
116 | 115 |
117 WebInspector.FlameChartDataProvider.prototype = { | 116 WebInspector.FlameChartDataProvider.prototype = { |
118 /** | 117 /** |
119 * @return {number} | 118 * @return {number} |
120 */ | 119 */ |
121 barHeight: function() { }, | 120 barHeight: function() { }, |
122 | 121 |
(...skipping 18 matching lines...) Expand all Loading... | |
141 * @return {number} | 140 * @return {number} |
142 */ | 141 */ |
143 maxStackDepth: function() { }, | 142 maxStackDepth: function() { }, |
144 | 143 |
145 /** | 144 /** |
146 * @return {?WebInspector.FlameChart.TimelineData} | 145 * @return {?WebInspector.FlameChart.TimelineData} |
147 */ | 146 */ |
148 timelineData: function() { }, | 147 timelineData: function() { }, |
149 | 148 |
150 /** | 149 /** |
151 * @return {!WebInspector.FlameChart.ColorGenerator} | |
152 */ | |
153 colorGenerator: function() { }, | |
154 | |
155 /** | |
156 * @param {number} entryIndex | 150 * @param {number} entryIndex |
157 * @return {?Array.<!{title: string, text: string}>} | 151 * @return {?Array.<!{title: string, text: string}>} |
158 */ | 152 */ |
159 prepareHighlightedEntryInfo: function(entryIndex) { }, | 153 prepareHighlightedEntryInfo: function(entryIndex) { }, |
160 | 154 |
161 /** | 155 /** |
162 * @param {number} entryIndex | 156 * @param {number} entryIndex |
163 * @return {boolean} | 157 * @return {boolean} |
164 */ | 158 */ |
165 canJumpToEntry: function(entryIndex) { }, | 159 canJumpToEntry: function(entryIndex) { }, |
166 | 160 |
167 /** | 161 /** |
168 * @param {number} entryIndex | 162 * @param {number} entryIndex |
169 * @return {?Object} | 163 * @return {?Object} |
170 */ | 164 */ |
171 entryData: function(entryIndex) { }, | 165 entryData: function(entryIndex) { }, |
172 | 166 |
173 /** | 167 /** |
174 * @param {number} entryIndex | 168 * @param {number} entryIndex |
175 * @return {?string} | 169 * @return {?string} |
176 */ | 170 */ |
177 entryTitle: function(entryIndex) { }, | 171 entryTitle: function(entryIndex) { }, |
178 | 172 |
179 /** | 173 /** |
180 * @param {number} entryIndex | 174 * @param {number} entryIndex |
181 * @return {?string} | 175 * @return {?string} |
182 */ | 176 */ |
183 entryFont: function(entryIndex) { }, | 177 entryFont: function(entryIndex) { }, |
178 | |
179 /** | |
180 * @param {number} entryIndex | |
181 * @return {!string} | |
182 */ | |
183 entryColor: function(entryIndex) { }, | |
184 } | 184 } |
185 | 185 |
186 /** | 186 /** |
187 * @constructor | 187 * @constructor |
188 * @implements {WebInspector.TimelineGrid.Calculator} | 188 * @implements {WebInspector.TimelineGrid.Calculator} |
189 */ | 189 */ |
190 WebInspector.FlameChart.Calculator = function() | 190 WebInspector.FlameChart.Calculator = function() |
191 { | 191 { |
192 this._paddingLeft = 0; | 192 this._paddingLeft = 0; |
193 } | 193 } |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 WebInspector.FlameChart.Events = { | 356 WebInspector.FlameChart.Events = { |
357 EntrySelected: "EntrySelected" | 357 EntrySelected: "EntrySelected" |
358 } | 358 } |
359 | 359 |
360 /** | 360 /** |
361 * @constructor | 361 * @constructor |
362 */ | 362 */ |
363 WebInspector.FlameChart.ColorGenerator = function() | 363 WebInspector.FlameChart.ColorGenerator = function() |
364 { | 364 { |
365 this._colors = {}; | 365 this._colors = {}; |
366 this._colorIndexes = []; | |
367 this._currentColorIndex = 0; | 366 this._currentColorIndex = 0; |
368 } | 367 } |
369 | 368 |
370 WebInspector.FlameChart.ColorGenerator.prototype = { | 369 WebInspector.FlameChart.ColorGenerator.prototype = { |
371 /** | 370 /** |
372 * @param {string} id | 371 * @param {string} id |
373 * @param {string|!CanvasGradient} color | 372 * @param {string|!CanvasGradient} color |
374 */ | 373 */ |
375 setColorForID: function(id, color) | 374 setColorForID: function(id, color) |
376 { | 375 { |
377 var colorData = {index: this._currentColorIndex++, color: color}; | 376 this._colors[id] = color; |
378 this._colors[id] = colorData; | |
379 this._colorIndexes[colorData.index] = colorData; | |
380 }, | 377 }, |
381 | 378 |
382 /** | 379 /** |
383 * @param {!string} id | 380 * @param {!string} id |
384 * @param {number=} sat | 381 * @param {number=} sat |
385 * @return {!Object} | 382 * @return {!string} |
386 */ | 383 */ |
387 colorForID: function(id, sat) | 384 colorForID: function(id, sat) |
388 { | 385 { |
389 if (typeof sat !== "number") | 386 if (typeof sat !== "number") |
390 sat = 100; | 387 sat = 100; |
391 var colors = this._colors; | 388 var color = this._colors[id]; |
392 var color = colors[id]; | |
393 if (!color) { | 389 if (!color) { |
394 colors[id] = color = this._createColor(this._currentColorIndex++, sa t); | 390 color = this._createColor(this._currentColorIndex++, sat); |
395 this._colorIndexes[color.index] = color; | 391 this._colors[id] = color; |
396 } | 392 } |
397 return color; | 393 return color; |
398 }, | 394 }, |
399 | 395 |
400 /** | 396 /** |
401 * @param {!number} index | 397 * @param {!number} index |
402 */ | |
403 _colorForIndex: function(index) | |
404 { | |
405 return this._colorIndexes[index]; | |
406 }, | |
407 | |
408 /** | |
409 * @param {!number} index | |
410 * @param {!number} sat | 398 * @param {!number} sat |
411 */ | 399 */ |
412 _createColor: function(index, sat) | 400 _createColor: function(index, sat) |
413 { | 401 { |
414 var hue = (index * 7 + 12 * (index % 2)) % 360; | 402 var hue = (index * 7 + 12 * (index % 2)) % 360; |
415 return {index: index, color: "hsla(" + hue + ", " + sat + "%, 66%, 0.7)" }; | 403 return "hsla(" + hue + ", " + sat + "%, 66%, 0.7)"; |
416 } | 404 } |
417 } | 405 } |
418 | 406 |
419 /** | 407 /** |
420 * @constructor | 408 * @constructor |
421 * @extends {WebInspector.View} | 409 * @extends {WebInspector.View} |
422 * @implements {WebInspector.TimeRangeController} | 410 * @implements {WebInspector.TimeRangeController} |
423 * @param {!WebInspector.FlameChartDataProvider} dataProvider | 411 * @param {!WebInspector.FlameChartDataProvider} dataProvider |
424 */ | 412 */ |
425 WebInspector.FlameChart.OverviewPane = function(dataProvider) | 413 WebInspector.FlameChart.OverviewPane = function(dataProvider) |
(...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
811 if (!timelineData) | 799 if (!timelineData) |
812 return; | 800 return; |
813 var ratio = window.devicePixelRatio; | 801 var ratio = window.devicePixelRatio; |
814 this._canvas.width = width * ratio; | 802 this._canvas.width = width * ratio; |
815 this._canvas.height = height * ratio; | 803 this._canvas.height = height * ratio; |
816 this._canvas.style.width = width + "px"; | 804 this._canvas.style.width = width + "px"; |
817 this._canvas.style.height = height + "px"; | 805 this._canvas.style.height = height + "px"; |
818 | 806 |
819 var context = this._canvas.getContext("2d"); | 807 var context = this._canvas.getContext("2d"); |
820 context.scale(ratio, ratio); | 808 context.scale(ratio, ratio); |
821 var timeWindowRight = this._timeWindowRight; | 809 var timeWindowRight = this._timeWindowRight - this._zeroTime; |
810 var timeWindowLeft = this._timeWindowLeft - this._zeroTime; | |
822 var timeToPixel = this._timeToPixel; | 811 var timeToPixel = this._timeToPixel; |
823 var pixelWindowLeft = this._pixelWindowLeft; | 812 var pixelWindowLeft = this._pixelWindowLeft; |
824 var paddingLeft = this._paddingLeft; | 813 var paddingLeft = this._paddingLeft; |
825 var minWidth = this._minWidth; | 814 var minWidth = this._minWidth; |
826 var entryTotalTimes = timelineData.entryTotalTimes; | 815 var entryTotalTimes = timelineData.entryTotalTimes; |
827 var entryOffsets = timelineData.entryOffsets; | 816 var entryOffsets = timelineData.entryOffsets; |
828 var entryLevels = timelineData.entryLevels; | 817 var entryLevels = timelineData.entryLevels; |
829 var colorEntryIndexes = timelineData.colorEntryIndexes; | |
830 | 818 |
831 var colorGenerator = this._dataProvider.colorGenerator(); | |
832 var titleIndexes = new Uint32Array(timelineData.entryTotalTimes); | 819 var titleIndexes = new Uint32Array(timelineData.entryTotalTimes); |
833 var lastTitleIndex = 0; | 820 var lastTitleIndex = 0; |
834 var dotsWidth = context.measureText("\u2026").width; | 821 var dotsWidth = context.measureText("\u2026").width; |
835 var textPaddingLeft = 2; | 822 var textPaddingLeft = 2; |
836 this._minTextWidth = context.measureText("\u2026").width + textPaddingLe ft; | 823 this._minTextWidth = context.measureText("\u2026").width + textPaddingLe ft; |
837 var minTextWidth = this._minTextWidth; | 824 var minTextWidth = this._minTextWidth; |
838 | 825 |
839 var marksField = []; | 826 var lastDrawOffset = new Int32Array(this._dataProvider.maxStackDepth()); |
840 for (var i = 0; i < this._dataProvider.maxStackDepth(); ++i) | 827 for (var i = 0; i < lastDrawOffset.length; ++i) |
841 marksField.push(new Uint16Array(width)); | 828 lastDrawOffset[i] = -1; |
842 | 829 |
843 var barX = 0; | 830 var barX = 0; |
831 var barY = 0; | |
844 var barWidth = 0; | 832 var barWidth = 0; |
845 var barRight = 0; | 833 var barRight = 0; |
846 var barLevel = 0; | 834 var barLevel = 0; |
835 var barHeight = this._barHeight; | |
847 this._baseHeight = this._isTopDown ? WebInspector.FlameChart.DividersBar Height : height - this._barHeight; | 836 this._baseHeight = this._isTopDown ? WebInspector.FlameChart.DividersBar Height : height - this._barHeight; |
848 context.strokeStyle = "black"; | 837 context.strokeStyle = "black"; |
849 var color; | 838 var color; |
850 var entryIndex = 0; | 839 var entryIndex = 0; |
851 var entryOffset = 0; | 840 var entryOffset = 0; |
852 for (var colorIndex = 0; colorIndex < colorEntryIndexes.length; ++colorI ndex) { | 841 |
853 color = colorGenerator._colorForIndex(colorIndex); | 842 var colorBuckets = {}; |
854 context.fillStyle = color.color; | 843 var colors = []; |
855 var indexes = colorEntryIndexes[colorIndex]; | 844 var bucket = []; |
856 if (!indexes) | 845 |
846 var textBaseHeight = this._baseHeight + this._barHeight - 4; | |
847 var lastUsedFont = ""; | |
848 var font; | |
pfeldman
2014/03/03 14:42:47
Extract method then.
| |
849 var text = ""; | |
850 var xText = 0; | |
851 var textWidth = 0; | |
852 var title = ""; | |
853 | |
854 var entryOffsetRight = 0; | |
855 var maxBarLevel = height / this._barHeight; | |
856 for (entryIndex = 0; entryIndex < entryOffsets.length; ++entryIndex) { | |
857 // stop if we reached right border in time (entries were ordered by start time). | |
858 entryOffset = entryOffsets[entryIndex]; | |
859 if (entryOffset > timeWindowRight) | |
860 break; | |
861 | |
862 // skip if it is not visible (top/bottom side) | |
863 barLevel = entryLevels[entryIndex]; | |
864 if (barLevel > maxBarLevel) | |
857 continue; | 865 continue; |
866 | |
867 // skip if it is not visible (left side). | |
868 entryOffsetRight = entryOffset + entryTotalTimes[entryIndex]; | |
869 if (entryOffsetRight < timeWindowLeft) | |
870 continue; | |
871 | |
872 barRight = this._offsetToPosition(entryOffsetRight); | |
873 | |
874 if (barRight <= lastDrawOffset[barLevel]) | |
875 continue; | |
876 barX = Math.max(this._offsetToPosition(entryOffset), lastDrawOffset[ barLevel]); | |
877 lastDrawOffset[barLevel] = barRight; | |
878 | |
879 barWidth = barRight - barX; | |
880 | |
881 color = this._dataProvider.entryColor(entryIndex); | |
882 bucket = colorBuckets[color]; | |
883 if (!bucket) { | |
884 bucket = []; | |
885 colorBuckets[color] = bucket; | |
886 } | |
887 bucket.push(entryIndex); | |
888 } | |
889 colors = Object.keys(colorBuckets); | |
890 // We don't use for in here because it couldn't be optimized. | |
891 for (var c = 0; c < colors.length; ++c) { | |
892 color = colors[c]; | |
893 context.fillStyle = color; | |
894 var indexes = colorBuckets[color]; | |
858 context.beginPath(); | 895 context.beginPath(); |
859 for (var i = 0; i < indexes.length; ++i) { | 896 for (var i = 0; i < indexes.length; ++i) { |
860 entryIndex = indexes[i]; | 897 entryIndex = indexes[i]; |
861 entryOffset = entryOffsets[entryIndex]; | 898 entryOffset = entryOffsets[entryIndex]; |
862 if (entryOffset > timeWindowRight) | |
863 break; | |
864 barX = this._offsetToPosition(entryOffset); | 899 barX = this._offsetToPosition(entryOffset); |
865 if (barX >= width) | |
866 continue; | |
867 barRight = this._offsetToPosition(entryOffset + entryTotalTimes[ entryIndex]); | 900 barRight = this._offsetToPosition(entryOffset + entryTotalTimes[ entryIndex]); |
868 if (barRight < 0) | 901 barWidth = Math.max(barRight - barX, minWidth); |
869 continue; | |
870 barWidth = (barRight - barX) || minWidth; | |
871 barLevel = entryLevels[entryIndex]; | 902 barLevel = entryLevels[entryIndex]; |
872 var marksRow = marksField[barLevel]; | 903 barY = this._levelToHeight(barLevel); |
873 if (barWidth <= marksRow[barX]) // skip the bar if there is anot her bar here. | |
874 continue; | |
875 marksRow[barX] = barWidth; | |
876 var barY = this._levelToHeight(barLevel); | |
877 context.rect(barX, barY, barWidth, this._barHeight); | 904 context.rect(barX, barY, barWidth, this._barHeight); |
878 if (barWidth > minTextWidth) | 905 if (barWidth > minTextWidth) |
879 titleIndexes[lastTitleIndex++] = entryIndex; | 906 titleIndexes[lastTitleIndex++] = entryIndex; |
880 } | 907 } |
881 context.fill(); | 908 context.fill(); |
882 } | 909 } |
883 | |
884 context.textBaseline = "alphabetic"; | 910 context.textBaseline = "alphabetic"; |
885 context.fillStyle = "#333"; | 911 context.fillStyle = "#333"; |
886 this._dotsWidth = context.measureText("\u2026").width; | 912 this._dotsWidth = context.measureText("\u2026").width; |
887 | 913 |
888 var textBaseHeight = this._baseHeight + this._barHeight - 4; | |
889 var lastUsedFont = ""; | |
890 var font; | |
891 for (var i = 0; i < lastTitleIndex; ++i) { | 914 for (var i = 0; i < lastTitleIndex; ++i) { |
892 entryIndex = titleIndexes[i]; | 915 entryIndex = titleIndexes[i]; |
893 var text = this._dataProvider.entryTitle(entryIndex); | 916 text = this._dataProvider.entryTitle(entryIndex); |
894 if (!text || !text.length) | 917 if (!text || !text.length) |
895 continue; | 918 continue; |
896 font = this._dataProvider.entryFont(entryIndex); | 919 font = this._dataProvider.entryFont(entryIndex); |
897 if (font !== lastUsedFont) | 920 if (font !== lastUsedFont) |
898 context.font = font; | 921 context.font = font; |
899 | 922 |
900 entryOffset = entryOffsets[entryIndex]; | 923 entryOffset = entryOffsets[entryIndex]; |
901 barX = this._offsetToPosition(entryOffset); | 924 barX = this._offsetToPosition(entryOffset); |
902 barRight = this._offsetToPosition(entryOffset + entryTotalTimes[entr yIndex]); | 925 barRight = this._offsetToPosition(entryOffset + entryTotalTimes[entr yIndex]); |
903 barWidth = (barRight - barX) || minWidth; | 926 barWidth = Math.max(barRight - barX, minWidth); |
904 var xText = Math.max(0, barX); | 927 xText = Math.max(0, barX); |
905 var widthText = barWidth - textPaddingLeft + barX - xText; | 928 textWidth = barWidth - textPaddingLeft + barX - xText; |
906 var title = this._prepareText(context, text, widthText); | 929 title = this._prepareText(context, text, textWidth); |
907 if (title) | 930 if (title) |
908 context.fillText(title, xText + textPaddingLeft, textBaseHeight - entryLevels[entryIndex] * this._barHeightDelta); | 931 context.fillText(title, xText + textPaddingLeft, textBaseHeight - entryLevels[entryIndex] * this._barHeightDelta); |
909 } | 932 } |
910 | |
911 this._updateHighlightElement(); | 933 this._updateHighlightElement(); |
912 }, | 934 }, |
913 | 935 |
914 _updateHighlightElement: function() | 936 _updateHighlightElement: function() |
915 { | 937 { |
916 if (this._highlightElement.parentElement) | 938 if (this._highlightElement.parentElement) |
917 this._highlightElement.remove(); | 939 this._highlightElement.remove(); |
918 var entryIndex = this._highlightedEntryIndex; | 940 var entryIndex = this._highlightedEntryIndex; |
919 if (entryIndex === -1) | 941 if (entryIndex === -1) |
920 return; | 942 return; |
921 var timelineData = this._timelineData(); | 943 var timelineData = this._timelineData(); |
922 var entryOffset = timelineData.entryOffsets[entryIndex]; | 944 var entryOffset = timelineData.entryOffsets[entryIndex]; |
923 var barX = this._offsetToPosition(entryOffset); | 945 var barX = this._offsetToPosition(entryOffset); |
924 var barRight = this._offsetToPosition(entryOffset + timelineData.entryTo talTimes[entryIndex]); | 946 var barRight = this._offsetToPosition(entryOffset + timelineData.entryTo talTimes[entryIndex]); |
925 var barWidth = (barRight - barX) || this._minWidth; | 947 var barWidth = Math.max(barRight - barX, this._minWidth); |
926 | 948 |
927 var style = this._highlightElement.style; | 949 var style = this._highlightElement.style; |
928 style.left = barX + "px"; | 950 style.left = barX + "px"; |
929 style.width = barWidth + "px"; | 951 style.width = barWidth + "px"; |
930 style.top = this._levelToHeight(timelineData.entryLevels[entryIndex]) + "px"; | 952 style.top = this._levelToHeight(timelineData.entryLevels[entryIndex]) + "px"; |
931 style.height = this._barHeight + "px"; | 953 style.height = this._barHeight + "px"; |
932 this.element.appendChild(this._highlightElement); | 954 this.element.appendChild(this._highlightElement); |
933 }, | 955 }, |
934 | 956 |
935 _offsetToPosition: function(offset) | 957 _offsetToPosition: function(offset) |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1049 this._timelineGrid.hideDividers(); | 1071 this._timelineGrid.hideDividers(); |
1050 this.draw(this.element.clientWidth, this.element.clientHeight); | 1072 this.draw(this.element.clientWidth, this.element.clientHeight); |
1051 this._calculator._updateBoundaries(this); | 1073 this._calculator._updateBoundaries(this); |
1052 this._timelineGrid.element.style.width = this.element.clientWidth; | 1074 this._timelineGrid.element.style.width = this.element.clientWidth; |
1053 var offsets = this._dataProvider.dividerOffsets(this._calculator.minimum Boundary(), this._calculator.maximumBoundary()); | 1075 var offsets = this._dataProvider.dividerOffsets(this._calculator.minimum Boundary(), this._calculator.maximumBoundary()); |
1054 this._timelineGrid.updateDividers(this._calculator, offsets, true); | 1076 this._timelineGrid.updateDividers(this._calculator, offsets, true); |
1055 }, | 1077 }, |
1056 | 1078 |
1057 __proto__: WebInspector.View.prototype | 1079 __proto__: WebInspector.View.prototype |
1058 } | 1080 } |
OLD | NEW |