| 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; |
| 849 var text = ""; |
| 850 var xText = 0; |
| 851 var textWidth = 0; |
| 852 var title = ""; |
| 853 var i = 0; |
| 854 var c = 0; |
| 855 |
| 856 var entryOffsetRight = 0; |
| 857 var maxBarLevel = height / this._barHeight; |
| 858 for (entryIndex = 0; entryIndex < entryOffsets.length; ++entryIndex) { |
| 859 // stop if we reached right border in time (entries were ordered by
start time). |
| 860 entryOffset = entryOffsets[entryIndex]; |
| 861 if (entryOffset > timeWindowRight) |
| 862 break; |
| 863 |
| 864 // skip if it is not visible (top/bottom side) |
| 865 barLevel = entryLevels[entryIndex]; |
| 866 if (barLevel > maxBarLevel) |
| 857 continue; | 867 continue; |
| 868 |
| 869 // skip if it is not visible (left side). |
| 870 entryOffsetRight = entryOffset + entryTotalTimes[entryIndex]; |
| 871 if (entryOffsetRight < timeWindowLeft) |
| 872 continue; |
| 873 |
| 874 barRight = this._offsetToPosition(entryOffsetRight); |
| 875 |
| 876 if (barRight <= lastDrawOffset[barLevel]) |
| 877 continue; |
| 878 barX = Math.max(this._offsetToPosition(entryOffset), lastDrawOffset[
barLevel]); |
| 879 lastDrawOffset[barLevel] = barRight; |
| 880 |
| 881 barWidth = barRight - barX; |
| 882 |
| 883 color = this._dataProvider.entryColor(entryIndex); |
| 884 bucket = colorBuckets[color]; |
| 885 if (!bucket) { |
| 886 bucket = []; |
| 887 colorBuckets[color] = bucket; |
| 888 } |
| 889 bucket.push(entryIndex); |
| 890 } |
| 891 colors = Object.keys(colorBuckets); |
| 892 // We don't use for in here because it couldn't be optimized. |
| 893 for (c = 0; c < colors.length; ++c) { |
| 894 color = colors[c]; |
| 895 context.fillStyle = color; |
| 896 var indexes = colorBuckets[color]; |
| 858 context.beginPath(); | 897 context.beginPath(); |
| 859 for (var i = 0; i < indexes.length; ++i) { | 898 for (i = 0; i < indexes.length; ++i) { |
| 860 entryIndex = indexes[i]; | 899 entryIndex = indexes[i]; |
| 861 entryOffset = entryOffsets[entryIndex]; | 900 entryOffset = entryOffsets[entryIndex]; |
| 862 if (entryOffset > timeWindowRight) | |
| 863 break; | |
| 864 barX = this._offsetToPosition(entryOffset); | 901 barX = this._offsetToPosition(entryOffset); |
| 865 if (barX >= width) | |
| 866 continue; | |
| 867 barRight = this._offsetToPosition(entryOffset + entryTotalTimes[
entryIndex]); | 902 barRight = this._offsetToPosition(entryOffset + entryTotalTimes[
entryIndex]); |
| 868 if (barRight < 0) | 903 barWidth = Math.max(barRight - barX, minWidth); |
| 869 continue; | |
| 870 barWidth = (barRight - barX) || minWidth; | |
| 871 barLevel = entryLevels[entryIndex]; | 904 barLevel = entryLevels[entryIndex]; |
| 872 var marksRow = marksField[barLevel]; | 905 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); | 906 context.rect(barX, barY, barWidth, this._barHeight); |
| 878 if (barWidth > minTextWidth) | 907 if (barWidth > minTextWidth) |
| 879 titleIndexes[lastTitleIndex++] = entryIndex; | 908 titleIndexes[lastTitleIndex++] = entryIndex; |
| 880 } | 909 } |
| 881 context.fill(); | 910 context.fill(); |
| 882 } | 911 } |
| 883 | |
| 884 context.textBaseline = "alphabetic"; | 912 context.textBaseline = "alphabetic"; |
| 885 context.fillStyle = "#333"; | 913 context.fillStyle = "#333"; |
| 886 this._dotsWidth = context.measureText("\u2026").width; | 914 this._dotsWidth = context.measureText("\u2026").width; |
| 887 | 915 |
| 888 var textBaseHeight = this._baseHeight + this._barHeight - 4; | 916 for (i = 0; i < lastTitleIndex; ++i) { |
| 889 var lastUsedFont = ""; | |
| 890 var font; | |
| 891 for (var i = 0; i < lastTitleIndex; ++i) { | |
| 892 entryIndex = titleIndexes[i]; | 917 entryIndex = titleIndexes[i]; |
| 893 var text = this._dataProvider.entryTitle(entryIndex); | 918 text = this._dataProvider.entryTitle(entryIndex); |
| 894 if (!text || !text.length) | 919 if (!text || !text.length) |
| 895 continue; | 920 continue; |
| 896 font = this._dataProvider.entryFont(entryIndex); | 921 font = this._dataProvider.entryFont(entryIndex); |
| 897 if (font !== lastUsedFont) | 922 if (font !== lastUsedFont) |
| 898 context.font = font; | 923 context.font = font; |
| 899 | 924 |
| 900 entryOffset = entryOffsets[entryIndex]; | 925 entryOffset = entryOffsets[entryIndex]; |
| 901 barX = this._offsetToPosition(entryOffset); | 926 barX = this._offsetToPosition(entryOffset); |
| 902 barRight = this._offsetToPosition(entryOffset + entryTotalTimes[entr
yIndex]); | 927 barRight = this._offsetToPosition(entryOffset + entryTotalTimes[entr
yIndex]); |
| 903 barWidth = (barRight - barX) || minWidth; | 928 barWidth = Math.max(barRight - barX, minWidth); |
| 904 var xText = Math.max(0, barX); | 929 xText = Math.max(0, barX); |
| 905 var widthText = barWidth - textPaddingLeft + barX - xText; | 930 textWidth = barWidth - textPaddingLeft + barX - xText; |
| 906 var title = this._prepareText(context, text, widthText); | 931 title = this._prepareText(context, text, textWidth); |
| 907 if (title) | 932 if (title) |
| 908 context.fillText(title, xText + textPaddingLeft, textBaseHeight
- entryLevels[entryIndex] * this._barHeightDelta); | 933 context.fillText(title, xText + textPaddingLeft, textBaseHeight
- entryLevels[entryIndex] * this._barHeightDelta); |
| 909 } | 934 } |
| 910 | |
| 911 this._updateHighlightElement(); | 935 this._updateHighlightElement(); |
| 912 }, | 936 }, |
| 913 | 937 |
| 914 _updateHighlightElement: function() | 938 _updateHighlightElement: function() |
| 915 { | 939 { |
| 916 if (this._highlightElement.parentElement) | 940 if (this._highlightElement.parentElement) |
| 917 this._highlightElement.remove(); | 941 this._highlightElement.remove(); |
| 918 var entryIndex = this._highlightedEntryIndex; | 942 var entryIndex = this._highlightedEntryIndex; |
| 919 if (entryIndex === -1) | 943 if (entryIndex === -1) |
| 920 return; | 944 return; |
| 921 var timelineData = this._timelineData(); | 945 var timelineData = this._timelineData(); |
| 922 var entryOffset = timelineData.entryOffsets[entryIndex]; | 946 var entryOffset = timelineData.entryOffsets[entryIndex]; |
| 923 var barX = this._offsetToPosition(entryOffset); | 947 var barX = this._offsetToPosition(entryOffset); |
| 924 var barRight = this._offsetToPosition(entryOffset + timelineData.entryTo
talTimes[entryIndex]); | 948 var barRight = this._offsetToPosition(entryOffset + timelineData.entryTo
talTimes[entryIndex]); |
| 925 var barWidth = (barRight - barX) || this._minWidth; | 949 var barWidth = Math.max(barRight - barX, this._minWidth); |
| 926 | 950 |
| 927 var style = this._highlightElement.style; | 951 var style = this._highlightElement.style; |
| 928 style.left = barX + "px"; | 952 style.left = barX + "px"; |
| 929 style.width = barWidth + "px"; | 953 style.width = barWidth + "px"; |
| 930 style.top = this._levelToHeight(timelineData.entryLevels[entryIndex]) +
"px"; | 954 style.top = this._levelToHeight(timelineData.entryLevels[entryIndex]) +
"px"; |
| 931 style.height = this._barHeight + "px"; | 955 style.height = this._barHeight + "px"; |
| 932 this.element.appendChild(this._highlightElement); | 956 this.element.appendChild(this._highlightElement); |
| 933 }, | 957 }, |
| 934 | 958 |
| 935 _offsetToPosition: function(offset) | 959 _offsetToPosition: function(offset) |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 this._timelineGrid.hideDividers(); | 1073 this._timelineGrid.hideDividers(); |
| 1050 this.draw(this.element.clientWidth, this.element.clientHeight); | 1074 this.draw(this.element.clientWidth, this.element.clientHeight); |
| 1051 this._calculator._updateBoundaries(this); | 1075 this._calculator._updateBoundaries(this); |
| 1052 this._timelineGrid.element.style.width = this.element.clientWidth; | 1076 this._timelineGrid.element.style.width = this.element.clientWidth; |
| 1053 var offsets = this._dataProvider.dividerOffsets(this._calculator.minimum
Boundary(), this._calculator.maximumBoundary()); | 1077 var offsets = this._dataProvider.dividerOffsets(this._calculator.minimum
Boundary(), this._calculator.maximumBoundary()); |
| 1054 this._timelineGrid.updateDividers(this._calculator, offsets, true); | 1078 this._timelineGrid.updateDividers(this._calculator, offsets, true); |
| 1055 }, | 1079 }, |
| 1056 | 1080 |
| 1057 __proto__: WebInspector.View.prototype | 1081 __proto__: WebInspector.View.prototype |
| 1058 } | 1082 } |
| OLD | NEW |