Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(723)

Side by Side Diff: Source/devtools/front_end/FlameChart.js

Issue 185533004: FlameChart: convert colors magic into dataProvider.entryColor getter (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: minor changes Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « Source/devtools/front_end/CPUProfileView.js ('k') | Source/devtools/front_end/TimelineFlameChart.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698