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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
61 this._canvas.addEventListener("mousemove", this._onMouseMove.bind(this), fal se); | 61 this._canvas.addEventListener("mousemove", this._onMouseMove.bind(this), fal se); |
62 this._canvas.addEventListener("mousewheel", this._onMouseWheel.bind(this), f alse); | 62 this._canvas.addEventListener("mousewheel", this._onMouseWheel.bind(this), f alse); |
63 this._canvas.addEventListener("click", this._onClick.bind(this), false); | 63 this._canvas.addEventListener("click", this._onClick.bind(this), false); |
64 WebInspector.installDragHandle(this._canvas, this._startCanvasDragging.bind( this), this._canvasDragging.bind(this), this._endCanvasDragging.bind(this), "mov e", null); | 64 WebInspector.installDragHandle(this._canvas, this._startCanvasDragging.bind( this), this._canvasDragging.bind(this), this._endCanvasDragging.bind(this), "mov e", null); |
65 | 65 |
66 this._vScrollElement = this.element.createChild("div", "flame-chart-v-scroll "); | 66 this._vScrollElement = this.element.createChild("div", "flame-chart-v-scroll "); |
67 this._vScrollContent = this._vScrollElement.createChild("div"); | 67 this._vScrollContent = this._vScrollElement.createChild("div"); |
68 this._vScrollElement.addEventListener("scroll", this.scheduleUpdate.bind(thi s), false); | 68 this._vScrollElement.addEventListener("scroll", this.scheduleUpdate.bind(thi s), false); |
69 | 69 |
70 this._entryInfo = this.element.createChild("div", "profile-entry-info"); | 70 this._entryInfo = this.element.createChild("div", "profile-entry-info"); |
71 this._markerHighlighElement = this.element.createChild("div", "flame-chart-m arker-highlight-element"); | |
71 this._highlightElement = this.element.createChild("div", "flame-chart-highli ght-element"); | 72 this._highlightElement = this.element.createChild("div", "flame-chart-highli ght-element"); |
72 this._selectedElement = this.element.createChild("div", "flame-chart-selecte d-element"); | 73 this._selectedElement = this.element.createChild("div", "flame-chart-selecte d-element"); |
73 | 74 |
74 this._dataProvider = dataProvider; | 75 this._dataProvider = dataProvider; |
75 | 76 |
76 this._windowLeft = 0.0; | 77 this._windowLeft = 0.0; |
77 this._windowRight = 1.0; | 78 this._windowRight = 1.0; |
78 this._windowWidth = 1.0; | 79 this._windowWidth = 1.0; |
79 this._timeWindowLeft = 0; | 80 this._timeWindowLeft = 0; |
80 this._timeWindowRight = Infinity; | 81 this._timeWindowRight = Infinity; |
81 this._barHeight = dataProvider.barHeight(); | 82 this._barHeight = dataProvider.barHeight(); |
82 this._barHeightDelta = this._isTopDown ? -this._barHeight : this._barHeight; | 83 this._barHeightDelta = this._isTopDown ? -this._barHeight : this._barHeight; |
83 this._minWidth = 1; | 84 this._minWidth = 1; |
84 this._paddingLeft = this._dataProvider.paddingLeft(); | 85 this._paddingLeft = this._dataProvider.paddingLeft(); |
85 this._markerPadding = 2; | 86 this._markerPadding = 2; |
86 this._markerRadius = this._barHeight / 2 - this._markerPadding; | 87 this._markerRadius = this._barHeight / 2 - this._markerPadding; |
88 this._highlightedMarkerIndex = -1; | |
87 this._highlightedEntryIndex = -1; | 89 this._highlightedEntryIndex = -1; |
88 this._selectedEntryIndex = -1; | 90 this._selectedEntryIndex = -1; |
89 this._textWidth = {}; | 91 this._textWidth = {}; |
90 } | 92 } |
91 | 93 |
92 WebInspector.FlameChart.DividersBarHeight = 20; | 94 WebInspector.FlameChart.DividersBarHeight = 20; |
93 | 95 |
94 /** | 96 /** |
95 * @interface | 97 * @interface |
96 */ | 98 */ |
97 WebInspector.FlameChartDataProvider = function() | 99 WebInspector.FlameChartDataProvider = function() |
98 { | 100 { |
99 } | 101 } |
100 | 102 |
101 /** @typedef {!{ | 103 /** |
102 entryLevels: (!Array.<number>|!Uint8Array), | 104 * @constructor |
103 entryTotalTimes: (!Array.<number>|!Float32Array), | 105 * @param {!Array.<number>|!Uint8Array} entryLevels |
104 entryStartTimes: (!Array.<number>|!Float64Array) | 106 * @param {!Array.<number>|!Float32Array} entryTotalTimes |
105 }} | 107 * @param {!Array.<number>|!Float64Array} entryStartTimes |
106 */ | 108 */ |
107 WebInspector.FlameChart.TimelineData; | 109 WebInspector.FlameChart.TimelineData = function(entryLevels, entryTotalTimes, en tryStartTimes) |
110 { | |
111 this.entryLevels = entryLevels; | |
112 this.entryTotalTimes = entryTotalTimes; | |
113 this.entryStartTimes = entryStartTimes; | |
114 /** @type {!Array.<number>} */ | |
115 this.markerTimestamps = []; | |
116 } | |
108 | 117 |
109 WebInspector.FlameChartDataProvider.prototype = { | 118 WebInspector.FlameChartDataProvider.prototype = { |
110 /** | 119 /** |
111 * @return {number} | 120 * @return {number} |
112 */ | 121 */ |
113 barHeight: function() { }, | 122 barHeight: function() { }, |
114 | 123 |
115 /** | 124 /** |
116 * @param {number} startTime | 125 * @param {number} startTime |
117 * @param {number} endTime | 126 * @param {number} endTime |
118 * @return {?Array.<number>} | 127 * @return {?Array.<number>} |
119 */ | 128 */ |
120 dividerOffsets: function(startTime, endTime) { }, | 129 dividerOffsets: function(startTime, endTime) { }, |
121 | 130 |
122 /** | 131 /** |
132 * @param {number} index | |
133 * @return {string} | |
134 */ | |
135 markerColor: function(index) { }, | |
136 | |
137 /** | |
138 * @param {number} index | |
139 * @return {string} | |
140 */ | |
141 markerTitle: function(index) { }, | |
142 | |
143 /** | |
123 * @return {number} | 144 * @return {number} |
124 */ | 145 */ |
125 minimumBoundary: function() { }, | 146 minimumBoundary: function() { }, |
126 | 147 |
127 /** | 148 /** |
128 * @return {number} | 149 * @return {number} |
129 */ | 150 */ |
130 totalTime: function() { }, | 151 totalTime: function() { }, |
131 | 152 |
132 /** | 153 /** |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
448 this._isDragging = false; | 469 this._isDragging = false; |
449 }, | 470 }, |
450 | 471 |
451 /** | 472 /** |
452 * @param {!Event} event | 473 * @param {!Event} event |
453 */ | 474 */ |
454 _onMouseMove: function(event) | 475 _onMouseMove: function(event) |
455 { | 476 { |
456 if (this._isDragging) | 477 if (this._isDragging) |
457 return; | 478 return; |
479 | |
480 var inDividersBar = event.offsetY < WebInspector.FlameChart.DividersBarH eight; | |
481 this._highlightedMarkerIndex = inDividersBar ? this._markerIndexAtPositi on(event.offsetX) : -1; | |
482 this._updateMarkerHighlight(); | |
483 if (inDividersBar) | |
484 return; | |
485 | |
458 var entryIndex = this._coordinatesToEntryIndex(event.offsetX, event.offs etY); | 486 var entryIndex = this._coordinatesToEntryIndex(event.offsetX, event.offs etY); |
459 | 487 |
460 if (this._highlightedEntryIndex === entryIndex) | 488 if (this._highlightedEntryIndex === entryIndex) |
461 return; | 489 return; |
462 | 490 |
463 if (entryIndex === -1 || !this._dataProvider.canJumpToEntry(entryIndex)) | 491 if (entryIndex === -1 || !this._dataProvider.canJumpToEntry(entryIndex)) |
464 this._canvas.style.cursor = "default"; | 492 this._canvas.style.cursor = "default"; |
465 else | 493 else |
466 this._canvas.style.cursor = "pointer"; | 494 this._canvas.style.cursor = "pointer"; |
467 | 495 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
555 } else { | 583 } else { |
556 cursorLevel = Math.floor((this._canvas.height / window.devicePixelRa tio - y) / this._barHeight); | 584 cursorLevel = Math.floor((this._canvas.height / window.devicePixelRa tio - y) / this._barHeight); |
557 offsetFromLevel = this._canvas.height / window.devicePixelRatio - cu rsorLevel * this._barHeight; | 585 offsetFromLevel = this._canvas.height / window.devicePixelRatio - cu rsorLevel * this._barHeight; |
558 } | 586 } |
559 var entryStartTimes = timelineData.entryStartTimes; | 587 var entryStartTimes = timelineData.entryStartTimes; |
560 var entryTotalTimes = timelineData.entryTotalTimes; | 588 var entryTotalTimes = timelineData.entryTotalTimes; |
561 var entryIndexes = this._timelineLevels[cursorLevel]; | 589 var entryIndexes = this._timelineLevels[cursorLevel]; |
562 if (!entryIndexes || !entryIndexes.length) | 590 if (!entryIndexes || !entryIndexes.length) |
563 return -1; | 591 return -1; |
564 | 592 |
593 /** | |
594 * @param {number} time | |
595 * @param {number} entryIndex | |
596 * @return {number} | |
597 */ | |
565 function comparator(time, entryIndex) | 598 function comparator(time, entryIndex) |
566 { | 599 { |
567 return time - entryStartTimes[entryIndex]; | 600 return time - entryStartTimes[entryIndex]; |
568 } | 601 } |
569 var indexOnLevel = Math.max(entryIndexes.upperBound(cursorTime, comparat or) - 1, 0); | 602 var indexOnLevel = Math.max(entryIndexes.upperBound(cursorTime, comparat or) - 1, 0); |
570 | 603 |
571 /** | 604 /** |
572 * @this {WebInspector.FlameChart} | 605 * @this {WebInspector.FlameChart} |
573 * @param {number} entryIndex | 606 * @param {number} entryIndex |
574 * @return {boolean} | 607 * @return {boolean} |
(...skipping 17 matching lines...) Expand all Loading... | |
592 var entryIndex = entryIndexes[indexOnLevel]; | 625 var entryIndex = entryIndexes[indexOnLevel]; |
593 if (checkEntryHit.call(this, entryIndex)) | 626 if (checkEntryHit.call(this, entryIndex)) |
594 return entryIndex; | 627 return entryIndex; |
595 entryIndex = entryIndexes[indexOnLevel + 1]; | 628 entryIndex = entryIndexes[indexOnLevel + 1]; |
596 if (checkEntryHit.call(this, entryIndex)) | 629 if (checkEntryHit.call(this, entryIndex)) |
597 return entryIndex; | 630 return entryIndex; |
598 return -1; | 631 return -1; |
599 }, | 632 }, |
600 | 633 |
601 /** | 634 /** |
635 * @param {number} x | |
636 * @return {number} | |
637 */ | |
638 _markerIndexAtPosition: function(x) | |
639 { | |
640 var markers = this._timelineData().markerTimestamps; | |
641 if (!markers) | |
642 return -1; | |
643 var accurracyOffsetPx = 1; | |
644 var time = this._cursorTime(x); | |
645 var leftTime = this._cursorTime(x - accurracyOffsetPx); | |
646 var rightTime = this._cursorTime(x + accurracyOffsetPx); | |
647 | |
648 /** | |
649 * @param {number} time | |
650 * @param {number} markerTimestamp | |
651 * @return {number} | |
652 */ | |
653 function comparator(time, markerTimestamp) | |
654 { | |
655 return time - markerTimestamp; | |
656 } | |
657 var left = markers.lowerBound(leftTime, comparator); | |
658 var markerIndex = -1; | |
659 var distance = Infinity; | |
660 for (var i = left; i < markers.length; i++) { | |
661 if (markers[i] > rightTime) | |
alph
2014/07/21 14:21:07
nit: you can move the check into the for condition
yurys
2014/07/21 14:30:00
Done.
| |
662 break; | |
663 var nextDistance = Math.abs(markers[i] - time); | |
664 if (nextDistance < distance) { | |
665 markerIndex = i; | |
666 distance = nextDistance; | |
667 } | |
668 } | |
669 return markerIndex; | |
670 }, | |
671 | |
672 /** | |
602 * @param {number} height | 673 * @param {number} height |
603 * @param {number} width | 674 * @param {number} width |
604 */ | 675 */ |
605 _draw: function(width, height) | 676 _draw: function(width, height) |
606 { | 677 { |
607 var timelineData = this._timelineData(); | 678 var timelineData = this._timelineData(); |
608 if (!timelineData) | 679 if (!timelineData) |
609 return; | 680 return; |
610 | 681 |
611 var context = this._canvas.getContext("2d"); | 682 var context = this._canvas.getContext("2d"); |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
739 if (!text || !text.length) | 810 if (!text || !text.length) |
740 continue; | 811 continue; |
741 | 812 |
742 context.fillStyle = this._dataProvider.textColor(entryIndex); | 813 context.fillStyle = this._dataProvider.textColor(entryIndex); |
743 context.fillText(text, barX + textPadding, textBaseHeight - barLevel * this._barHeightDelta); | 814 context.fillText(text, barX + textPadding, textBaseHeight - barLevel * this._barHeightDelta); |
744 } | 815 } |
745 context.restore(); | 816 context.restore(); |
746 | 817 |
747 var offsets = this._dataProvider.dividerOffsets(this._calculator.minimum Boundary(), this._calculator.maximumBoundary()); | 818 var offsets = this._dataProvider.dividerOffsets(this._calculator.minimum Boundary(), this._calculator.maximumBoundary()); |
748 WebInspector.TimelineGrid.drawCanvasGrid(this._canvas, this._calculator, offsets); | 819 WebInspector.TimelineGrid.drawCanvasGrid(this._canvas, this._calculator, offsets); |
820 this._drawMarkers(); | |
749 | 821 |
750 this._updateElementPosition(this._highlightElement, this._highlightedEnt ryIndex); | 822 this._updateElementPosition(this._highlightElement, this._highlightedEnt ryIndex); |
751 this._updateElementPosition(this._selectedElement, this._selectedEntryIn dex); | 823 this._updateElementPosition(this._selectedElement, this._selectedEntryIn dex); |
824 this._updateMarkerHighlight(); | |
825 }, | |
826 | |
827 _drawMarkers: function() | |
828 { | |
829 var markerTimestamps = this._timelineData().markerTimestamps; | |
830 /** | |
831 * @param {number} time | |
832 * @param {number} markerTimestamp | |
833 * @return {number} | |
834 */ | |
835 function compare(time, markerTimestamp) | |
836 { | |
837 return time - markerTimestamp; | |
838 } | |
839 var left = markerTimestamps.lowerBound(this._calculator.minimumBoundary( ), compare); | |
840 var right = markerTimestamps.upperBound(this._calculator.maximumBoundary (), compare); | |
alph
2014/07/21 14:21:07
nit: you don't really need to calculate it. you ca
yurys
2014/07/21 14:30:00
Done.
| |
841 | |
842 var context = this._canvas.getContext("2d"); | |
843 context.save(); | |
844 var ratio = window.devicePixelRatio; | |
845 context.scale(ratio, ratio); | |
846 var height = WebInspector.FlameChart.DividersBarHeight - 1; | |
847 context.lineWidth = 2; | |
848 for (var i = left; i < right; i++) { | |
849 var timestamp = markerTimestamps[i]; | |
850 var position = this._calculator.computePosition(timestamp); | |
851 context.strokeStyle = this._dataProvider.markerColor(i); | |
852 context.beginPath(); | |
853 context.moveTo(position, 0); | |
854 context.lineTo(position, height); | |
855 context.stroke(); | |
856 } | |
857 context.restore(); | |
858 }, | |
859 | |
860 _updateMarkerHighlight: function() | |
861 { | |
862 var element = this._markerHighlighElement; | |
863 if (element.parentElement) | |
864 element.remove(); | |
865 var markerIndex = this._highlightedMarkerIndex; | |
866 if (markerIndex === -1) | |
867 return; | |
868 var barX = this._timeToPosition(this._timelineData().markerTimestamps[ma rkerIndex]); | |
869 element.title = this._dataProvider.markerTitle(markerIndex); | |
870 var style = element.style; | |
871 style.left = barX + "px"; | |
872 style.backgroundColor = this._dataProvider.markerColor(markerIndex); | |
873 this.element.appendChild(element); | |
752 }, | 874 }, |
753 | 875 |
754 /** | 876 /** |
755 * @param {?WebInspector.FlameChart.TimelineData} timelineData | 877 * @param {?WebInspector.FlameChart.TimelineData} timelineData |
756 */ | 878 */ |
757 _processTimelineData: function(timelineData) | 879 _processTimelineData: function(timelineData) |
758 { | 880 { |
759 if (!timelineData) { | 881 if (!timelineData) { |
760 this._timelineLevels = null; | 882 this._timelineLevels = null; |
761 this._rawTimelineData = null; | 883 this._rawTimelineData = null; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
946 if (!this._timelineData()) | 1068 if (!this._timelineData()) |
947 return; | 1069 return; |
948 this._resetCanvas(); | 1070 this._resetCanvas(); |
949 this._updateBoundaries(); | 1071 this._updateBoundaries(); |
950 this._calculator._updateBoundaries(this); | 1072 this._calculator._updateBoundaries(this); |
951 this._draw(this._offsetWidth, this._offsetHeight); | 1073 this._draw(this._offsetWidth, this._offsetHeight); |
952 }, | 1074 }, |
953 | 1075 |
954 reset: function() | 1076 reset: function() |
955 { | 1077 { |
1078 this._highlightedMarkerIndex = -1; | |
956 this._highlightedEntryIndex = -1; | 1079 this._highlightedEntryIndex = -1; |
957 this._selectedEntryIndex = -1; | 1080 this._selectedEntryIndex = -1; |
958 this._textWidth = {}; | 1081 this._textWidth = {}; |
959 this.update(); | 1082 this.update(); |
960 }, | 1083 }, |
961 | 1084 |
962 __proto__: WebInspector.HBox.prototype | 1085 __proto__: WebInspector.HBox.prototype |
963 } | 1086 } |
OLD | NEW |