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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/ui_lazy/FlameChart.js

Issue 2423283002: DevTools: Extract ChartViewport out of FlameChart. (Closed)
Patch Set: Created 4 years, 2 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
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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 42
43 /** 43 /**
44 * @param {number} startTime 44 * @param {number} startTime
45 * @param {number} endTime 45 * @param {number} endTime
46 */ 46 */
47 updateRangeSelection: function(startTime, endTime) { }, 47 updateRangeSelection: function(startTime, endTime) { },
48 } 48 }
49 49
50 /** 50 /**
51 * @constructor 51 * @constructor
52 * @extends {WebInspector.HBox} 52 * @extends {WebInspector.ChartViewport}
caseq 2016/10/17 23:26:05 I don't think inheriting FlameChart form ChartView
alph 2016/10/17 23:41:04 I'd keep it the current way and update it later if
53 * @param {!WebInspector.FlameChartDataProvider} dataProvider 53 * @param {!WebInspector.FlameChartDataProvider} dataProvider
54 * @param {!WebInspector.FlameChartDelegate} flameChartDelegate 54 * @param {!WebInspector.FlameChartDelegate} flameChartDelegate
55 * @param {!WebInspector.Setting=} groupExpansionSetting 55 * @param {!WebInspector.Setting=} groupExpansionSetting
56 */ 56 */
57 WebInspector.FlameChart = function(dataProvider, flameChartDelegate, groupExpans ionSetting) 57 WebInspector.FlameChart = function(dataProvider, flameChartDelegate, groupExpans ionSetting)
58 { 58 {
59 WebInspector.HBox.call(this, true); 59 WebInspector.ChartViewport.call(this);
60 this.registerRequiredCSS("ui_lazy/flameChart.css"); 60 this.registerRequiredCSS("ui_lazy/flameChart.css");
61 this.contentElement.classList.add("flame-chart-main-pane"); 61 this.contentElement.classList.add("flame-chart-main-pane");
62 this._flameChartDelegate = flameChartDelegate; 62 this._flameChartDelegate = flameChartDelegate;
63 this._groupExpansionSetting = groupExpansionSetting; 63 this._groupExpansionSetting = groupExpansionSetting;
64 this._groupExpansionState = groupExpansionSetting && groupExpansionSetting.g et() || {}; 64 this._groupExpansionState = groupExpansionSetting && groupExpansionSetting.g et() || {};
65 65
66 this._dataProvider = dataProvider; 66 this._dataProvider = dataProvider;
67 this._calculator = new WebInspector.FlameChart.Calculator(dataProvider); 67 this._calculator = new WebInspector.FlameChart.Calculator(dataProvider);
68 68
69 this._canvas = this.contentElement.createChild("canvas"); 69 this._canvas = this.contentElement.createChild("canvas");
70 this._canvas.tabIndex = 1; 70 this._canvas.tabIndex = 1;
71 this.setDefaultFocusedElement(this._canvas); 71 this.setDefaultFocusedElement(this._canvas);
72 this._canvas.addEventListener("mousemove", this._onMouseMove.bind(this), fal se); 72 this._canvas.addEventListener("mousemove", this._onMouseMove.bind(this), fal se);
73 this._canvas.addEventListener("mouseout", this._onMouseOut.bind(this), false ); 73 this._canvas.addEventListener("mouseout", this._onMouseOut.bind(this), false );
74 this._canvas.addEventListener("mousewheel", this._onMouseWheel.bind(this), f alse);
75 this._canvas.addEventListener("click", this._onClick.bind(this), false); 74 this._canvas.addEventListener("click", this._onClick.bind(this), false);
76 this._canvas.addEventListener("keydown", this._onKeyDown.bind(this), false); 75 this._canvas.addEventListener("keydown", this._onKeyDown.bind(this), false);
77 WebInspector.installInertialDragHandle(this._canvas, this._startCanvasDraggi ng.bind(this), this._canvasDragging.bind(this), this._endCanvasDragging.bind(thi s), "-webkit-grabbing", null);
78 WebInspector.installDragHandle(this._canvas, this._startRangeSelection.bind( this), this._rangeSelectionDragging.bind(this), this._endRangeSelection.bind(thi s), "text", null);
79
80 this._vScrollElement = this.contentElement.createChild("div", "flame-chart-v -scroll");
81 this._vScrollContent = this._vScrollElement.createChild("div");
82 this._vScrollElement.addEventListener("scroll", this._onScroll.bind(this), f alse);
83 this._scrollTop = 0;
84 76
85 this._entryInfo = this.contentElement.createChild("div", "flame-chart-entry- info"); 77 this._entryInfo = this.contentElement.createChild("div", "flame-chart-entry- info");
86 this._markerHighlighElement = this.contentElement.createChild("div", "flame- chart-marker-highlight-element"); 78 this._markerHighlighElement = this.contentElement.createChild("div", "flame- chart-marker-highlight-element");
87 this._highlightElement = this.contentElement.createChild("div", "flame-chart -highlight-element"); 79 this._highlightElement = this.contentElement.createChild("div", "flame-chart -highlight-element");
88 this._selectedElement = this.contentElement.createChild("div", "flame-chart- selected-element"); 80 this._selectedElement = this.contentElement.createChild("div", "flame-chart- selected-element");
89 this._selectionOverlay = this.contentElement.createChild("div", "flame-chart -selection-overlay hidden");
90 this._selectedTimeSpanLabel = this._selectionOverlay.createChild("div", "tim e-span");
91 81
92 this._windowLeft = 0.0; 82 this._windowLeft = 0.0;
93 this._windowRight = 1.0; 83 this._windowRight = 1.0;
94 this._timeWindowLeft = 0; 84 this._timeWindowLeft = 0;
95 this._timeWindowRight = Infinity; 85 this._timeWindowRight = Infinity;
96 this._rangeSelectionStart = 0; 86 this._rangeSelectionStart = 0;
97 this._rangeSelectionEnd = 0; 87 this._rangeSelectionEnd = 0;
98 this._barHeight = dataProvider.barHeight(); 88 this._barHeight = dataProvider.barHeight();
99 this._paddingLeft = this._dataProvider.paddingLeft(); 89 this._paddingLeft = this._dataProvider.paddingLeft();
100 var markerPadding = 2; 90 var markerPadding = 2;
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 WebInspector.FlameChart.prototype = { 485 WebInspector.FlameChart.prototype = {
496 /** 486 /**
497 * @override 487 * @override
498 */ 488 */
499 willHide: function() 489 willHide: function()
500 { 490 {
501 this.hideHighlight(); 491 this.hideHighlight();
502 }, 492 },
503 493
504 /** 494 /**
505 * @override
506 * @return {!Array.<!Element>}
507 */
508 elementsToRestoreScrollPositionsFor: function()
509 {
510 return [this._vScrollElement];
511 },
512
513 /**
514 * @param {number} entryIndex 495 * @param {number} entryIndex
515 */ 496 */
516 highlightEntry: function(entryIndex) 497 highlightEntry: function(entryIndex)
517 { 498 {
518 if (this._highlightedEntryIndex === entryIndex) 499 if (this._highlightedEntryIndex === entryIndex)
519 return; 500 return;
520 this._highlightedEntryIndex = entryIndex; 501 this._highlightedEntryIndex = entryIndex;
521 this._updateElementPosition(this._highlightElement, this._highlightedEnt ryIndex); 502 this._updateElementPosition(this._highlightElement, this._highlightedEnt ryIndex);
522 }, 503 },
523 504
(...skipping 12 matching lines...) Expand all
536 this._canvas.height = this._offsetHeight * ratio; 517 this._canvas.height = this._offsetHeight * ratio;
537 this._canvas.style.width = this._offsetWidth + "px"; 518 this._canvas.style.width = this._offsetWidth + "px";
538 this._canvas.style.height = this._offsetHeight + "px"; 519 this._canvas.style.height = this._offsetHeight + "px";
539 }, 520 },
540 521
541 /** 522 /**
542 * @return {?WebInspector.FlameChart.TimelineData} 523 * @return {?WebInspector.FlameChart.TimelineData}
543 */ 524 */
544 _timelineData: function() 525 _timelineData: function()
545 { 526 {
527 if (!this._dataProvider)
528 return null;
546 var timelineData = this._dataProvider.timelineData(); 529 var timelineData = this._dataProvider.timelineData();
547 if (timelineData !== this._rawTimelineData || timelineData.entryStartTim es.length !== this._rawTimelineDataLength) 530 if (timelineData !== this._rawTimelineData || timelineData.entryStartTim es.length !== this._rawTimelineDataLength)
548 this._processTimelineData(timelineData); 531 this._processTimelineData(timelineData);
549 return this._rawTimelineData; 532 return this._rawTimelineData;
550 }, 533 },
551 534
552 _cancelAnimation: function()
553 {
554 if (this._cancelWindowTimesAnimation) {
555 this._timeWindowLeft = this._pendingAnimationTimeLeft;
556 this._timeWindowRight = this._pendingAnimationTimeRight;
557 this._cancelWindowTimesAnimation();
558 delete this._cancelWindowTimesAnimation;
559 }
560 },
561
562 /** 535 /**
563 * @param {number} entryIndex 536 * @param {number} entryIndex
564 */ 537 */
565 _revealEntry: function(entryIndex) 538 _revealEntry: function(entryIndex)
566 { 539 {
567 var timelineData = this._timelineData(); 540 var timelineData = this._timelineData();
568 if (!timelineData) 541 if (!timelineData)
569 return; 542 return;
570 // Think in terms of not where we are, but where we'll be after animatio n (if present) 543 // Think in terms of not where we are, but where we'll be after animatio n (if present)
571 var timeLeft = this._cancelWindowTimesAnimation ? this._pendingAnimation TimeLeft : this._timeWindowLeft; 544 var timeLeft = this._cancelWindowTimesAnimation ? this._pendingAnimation TimeLeft : this._timeWindowLeft;
572 var timeRight = this._cancelWindowTimesAnimation ? this._pendingAnimatio nTimeRight : this._timeWindowRight; 545 var timeRight = this._cancelWindowTimesAnimation ? this._pendingAnimatio nTimeRight : this._timeWindowRight;
573 var entryStartTime = timelineData.entryStartTimes[entryIndex]; 546 var entryStartTime = timelineData.entryStartTimes[entryIndex];
574 var entryTotalTime = timelineData.entryTotalTimes[entryIndex]; 547 var entryTotalTime = timelineData.entryTotalTimes[entryIndex];
575 var entryEndTime = entryStartTime + entryTotalTime; 548 var entryEndTime = entryStartTime + entryTotalTime;
576 var minEntryTimeWindow = Math.min(entryTotalTime, timeRight - timeLeft); 549 var minEntryTimeWindow = Math.min(entryTotalTime, timeRight - timeLeft);
577 550
578 var y = this._levelToHeight(timelineData.entryLevels[entryIndex]); 551 var y = this._levelToHeight(timelineData.entryLevels[entryIndex]);
579 if (this._vScrollElement.scrollTop > y) 552 this.setScrollOffset(y, this._barHeight);
580 this._vScrollElement.scrollTop = y;
581 else if (this._vScrollElement.scrollTop < y - this._offsetHeight + this. _barHeight)
582 this._vScrollElement.scrollTop = y - this._offsetHeight + this._barH eight;
583 553
584 if (timeLeft > entryEndTime) { 554 if (timeLeft > entryEndTime) {
585 var delta = timeLeft - entryEndTime + minEntryTimeWindow; 555 var delta = timeLeft - entryEndTime + minEntryTimeWindow;
586 this._flameChartDelegate.requestWindowTimes(timeLeft - delta, timeRi ght - delta); 556 this._flameChartDelegate.requestWindowTimes(timeLeft - delta, timeRi ght - delta);
587 } else if (timeRight < entryStartTime) { 557 } else if (timeRight < entryStartTime) {
588 var delta = entryStartTime - timeRight + minEntryTimeWindow; 558 var delta = entryStartTime - timeRight + minEntryTimeWindow;
589 this._flameChartDelegate.requestWindowTimes(timeLeft + delta, timeRi ght + delta); 559 this._flameChartDelegate.requestWindowTimes(timeLeft + delta, timeRi ght + delta);
590 } 560 }
591 }, 561 },
592 562
593 /** 563 /**
564 * @override
594 * @param {number} startTime 565 * @param {number} startTime
595 * @param {number} endTime 566 * @param {number} endTime
596 */ 567 */
597 setWindowTimes: function(startTime, endTime) 568 setWindowTimes: function(startTime, endTime)
598 { 569 {
599 if (this._muteAnimation || this._timeWindowLeft === 0 || this._timeWindo wRight === Infinity || (startTime === 0 && endTime === Infinity) || (startTime = == Infinity && endTime === Infinity)) { 570 WebInspector.FlameChart.prototype.__proto__.setWindowTimes.call(this, st artTime, endTime);
600 // Initial setup.
601 this._timeWindowLeft = startTime;
602 this._timeWindowRight = endTime;
603 this.scheduleUpdate();
604 return;
605 }
606
607 this._cancelAnimation();
608 this._updateHighlight(); 571 this._updateHighlight();
609 this._cancelWindowTimesAnimation = WebInspector.animateFunction(this.ele ment.window(), this._animateWindowTimes.bind(this),
610 [{from: this._timeWindowLeft, to: startTime}, {from: this._timeWindo wRight, to: endTime}], 5,
611 this._animationCompleted.bind(this));
612 this._pendingAnimationTimeLeft = startTime;
613 this._pendingAnimationTimeRight = endTime;
614 },
615
616 /**
617 * @param {number} startTime
618 * @param {number} endTime
619 */
620 _animateWindowTimes: function(startTime, endTime)
621 {
622 this._timeWindowLeft = startTime;
623 this._timeWindowRight = endTime;
624 this._updateHighlight();
625 this.update();
626 },
627
628 _animationCompleted: function()
629 {
630 delete this._cancelWindowTimesAnimation;
631 this._updateHighlight();
632 },
633
634 /**
635 * @param {!MouseEvent} event
636 */
637 _initMaxDragOffset: function(event)
638 {
639 this._maxDragOffsetSquared = 0;
640 this._dragStartX = event.pageX;
641 this._dragStartY = event.pageY;
642 },
643
644 /**
645 * @param {number} x
646 * @param {number} y
647 */
648 _updateMaxDragOffset: function(x, y)
649 {
650 var dx = x - this._dragStartX;
651 var dy = y - this._dragStartY;
652 var dragOffsetSquared = dx * dx + dy * dy;
653 this._maxDragOffsetSquared = Math.max(this._maxDragOffsetSquared, dragOf fsetSquared);
654 },
655
656 /**
657 * @return {number}
658 */
659 _maxDragOffset: function()
660 {
661 return Math.sqrt(this._maxDragOffsetSquared);
662 },
663
664 /**
665 * @param {number} x
666 * @param {number} y
667 * @param {!MouseEvent} event
668 * @return {boolean}
669 */
670 _startCanvasDragging: function(x, y, event)
671 {
672 if (event.shiftKey)
673 return false;
674 if (!this._timelineData() || this._timeWindowRight === Infinity)
675 return false;
676 this._isDragging = true;
677 this._initMaxDragOffset(event);
678 this._dragStartPointX = x;
679 this._dragStartPointY = y;
680 this._dragStartScrollTop = this._vScrollElement.scrollTop;
681 this._canvas.style.cursor = "";
682 this.hideHighlight();
683 return true;
684 },
685
686 /**
687 * @param {number} x
688 * @param {number} y
689 */
690 _canvasDragging: function(x, y)
691 {
692 var pixelShift = this._dragStartPointX - x;
693 this._dragStartPointX = x;
694 this._muteAnimation = true;
695 this._handlePanGesture(pixelShift * this._pixelToTime);
696 this._muteAnimation = false;
697
698 var pixelScroll = this._dragStartPointY - y;
699 this._vScrollElement.scrollTop = this._dragStartScrollTop + pixelScroll;
700 this._updateMaxDragOffset(x, y);
701 },
702
703 _endCanvasDragging: function()
704 {
705 this._isDragging = false;
706 this._updateHighlight();
707 },
708
709 /**
710 * @param {!MouseEvent} event
711 * @return {boolean}
712 */
713 _startRangeSelection: function(event)
714 {
715 if (!event.shiftKey)
716 return false;
717 this._isDragging = true;
718 this._initMaxDragOffset(event);
719 this._selectionOffsetShiftX = event.offsetX - event.pageX;
720 this._selectionOffsetShiftY = event.offsetY - event.pageY;
721 this._selectionStartX = event.offsetX;
722 var style = this._selectionOverlay.style;
723 style.left = this._selectionStartX + "px";
724 style.width = "1px";
725 this._selectedTimeSpanLabel.textContent = "";
726 this._selectionOverlay.classList.remove("hidden");
727 this.hideHighlight();
728 return true;
729 },
730
731 _endRangeSelection: function()
732 {
733 this._isDragging = false;
734 this._updateHighlight();
735 },
736
737 _hideRangeSelection: function()
738 {
739 this._selectionOverlay.classList.add("hidden");
740 },
741
742 /**
743 * @param {!MouseEvent} event
744 */
745 _rangeSelectionDragging: function(event)
746 {
747 this._updateMaxDragOffset(event.pageX, event.pageY);
748 var x = Number.constrain(event.pageX + this._selectionOffsetShiftX, 0, t his._offsetWidth);
749 var start = this._cursorTime(this._selectionStartX);
750 var end = this._cursorTime(x);
751 this._rangeSelectionStart = Math.min(start, end);
752 this._rangeSelectionEnd = Math.max(start, end);
753 this._updateRangeSelectionOverlay();
754 this._flameChartDelegate.updateRangeSelection(this._rangeSelectionStart, this._rangeSelectionEnd);
755 },
756
757 _updateRangeSelectionOverlay: function()
758 {
759 var /** @const */ margin = 100;
760 var left = Number.constrain(this._timeToPosition(this._rangeSelectionSta rt), -margin, this._offsetWidth + margin);
761 var right = Number.constrain(this._timeToPosition(this._rangeSelectionEn d), -margin, this._offsetWidth + margin);
762 var style = this._selectionOverlay.style;
763 style.left = left + "px";
764 style.width = (right - left) + "px";
765 var timeSpan = this._rangeSelectionEnd - this._rangeSelectionStart;
766 this._selectedTimeSpanLabel.textContent = Number.preciseMillisToString(t imeSpan, 2);
767 }, 572 },
768 573
769 /** 574 /**
770 * @param {!Event} event 575 * @param {!Event} event
771 */ 576 */
772 _onMouseMove: function(event) 577 _onMouseMove: function(event)
773 { 578 {
774 this._lastMouseOffsetX = event.offsetX; 579 this._lastMouseOffsetX = event.offsetX;
775 this._lastMouseOffsetY = event.offsetY; 580 this._lastMouseOffsetY = event.offsetY;
776 if (!this._enabled()) 581 if (!this._enabled())
777 return; 582 return;
778 if (this._isDragging) 583 if (this.isDragging())
779 return; 584 return;
780 if (this._coordinatesToGroupIndex(event.offsetX, event.offsetY) >= 0) { 585 if (this._coordinatesToGroupIndex(event.offsetX, event.offsetY) >= 0) {
781 this.hideHighlight(); 586 this.hideHighlight();
782 this._canvas.style.cursor = "pointer"; 587 this._canvas.style.cursor = "pointer";
783 return; 588 return;
784 } 589 }
785 this._updateHighlight(); 590 this._updateHighlight();
786 }, 591 },
787 592
788 _updateHighlight: function() 593 _updateHighlight: function()
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 var dy = quadrant & 1 ? -offsetY - infoHeight : offsetY; 647 var dy = quadrant & 1 ? -offsetY - infoHeight : offsetY;
843 x = Number.constrain(mouseX + dx, 0, parentWidth - infoWidth); 648 x = Number.constrain(mouseX + dx, 0, parentWidth - infoWidth);
844 y = Number.constrain(mouseY + dy, 0, parentHeight - infoHeight); 649 y = Number.constrain(mouseY + dy, 0, parentHeight - infoHeight);
845 if (x >= mouseX || mouseX >= x + infoWidth || y >= mouseY || mouseY >= y + infoHeight) 650 if (x >= mouseX || mouseX >= x + infoWidth || y >= mouseY || mouseY >= y + infoHeight)
846 break; 651 break;
847 } 652 }
848 this._entryInfo.style.left = x + "px"; 653 this._entryInfo.style.left = x + "px";
849 this._entryInfo.style.top = y + "px"; 654 this._entryInfo.style.top = y + "px";
850 }, 655 },
851 656
657 /**
658 * @param {!Event} event
659 */
852 _onClick: function(event) 660 _onClick: function(event)
853 { 661 {
854 this.focus(); 662 this.focus();
855 // onClick comes after dragStart and dragEnd events. 663 // onClick comes after dragStart and dragEnd events.
856 // So if there was drag (mouse move) in the middle of that events 664 // So if there was drag (mouse move) in the middle of that events
857 // we skip the click. Otherwise we jump to the sources. 665 // we skip the click. Otherwise we jump to the sources.
858 const clickThreshold = 5; 666 const clickThreshold = 5;
859 if (this._maxDragOffset() > clickThreshold) 667 if (this.maxDragOffset() > clickThreshold)
860 return; 668 return;
861 var groupIndex = this._coordinatesToGroupIndex(event.offsetX, event.offs etY); 669 var groupIndex = this._coordinatesToGroupIndex(event.offsetX, event.offs etY);
862 if (groupIndex >= 0) { 670 if (groupIndex >= 0) {
863 this._toggleGroupVisibility(groupIndex); 671 this._toggleGroupVisibility(groupIndex);
864 return; 672 return;
865 } 673 }
866 this._hideRangeSelection(); 674 this.hideRangeSelection();
867 this.dispatchEventToListeners(WebInspector.FlameChart.Events.EntrySelect ed, this._highlightedEntryIndex); 675 this.dispatchEventToListeners(WebInspector.FlameChart.Events.EntrySelect ed, this._highlightedEntryIndex);
868 }, 676 },
869 677
870 /** 678 /**
871 * @param {number} groupIndex 679 * @param {number} groupIndex
872 */ 680 */
873 _toggleGroupVisibility: function(groupIndex) 681 _toggleGroupVisibility: function(groupIndex)
874 { 682 {
875 if (!this._isGroupCollapsible(groupIndex)) 683 if (!this._isGroupCollapsible(groupIndex))
876 return; 684 return;
(...skipping 14 matching lines...) Expand all
891 } 699 }
892 700
893 this._updateHeight(); 701 this._updateHeight();
894 this._resetCanvas(); 702 this._resetCanvas();
895 this._draw(this._offsetWidth, this._offsetHeight); 703 this._draw(this._offsetWidth, this._offsetHeight);
896 }, 704 },
897 705
898 /** 706 /**
899 * @param {!Event} e 707 * @param {!Event} e
900 */ 708 */
901 _onMouseWheel: function(e)
902 {
903 if (!this._enabled())
904 return;
905 // Pan vertically when shift down only.
906 var panVertically = e.shiftKey && (e.wheelDeltaY || Math.abs(e.wheelDelt aX) === 120);
907 var panHorizontally = Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY) && !e.shiftKey;
908 if (panVertically) {
909 this._vScrollElement.scrollTop -= (e.wheelDeltaY || e.wheelDeltaX) / 120 * this._offsetHeight / 8;
910 } else if (panHorizontally) {
911 var shift = -e.wheelDeltaX * this._pixelToTime;
912 this._muteAnimation = true;
913 this._handlePanGesture(shift);
914 this._muteAnimation = false;
915 } else { // Zoom.
916 const mouseWheelZoomSpeed = 1 / 120;
917 this._handleZoomGesture(Math.pow(1.2, -(e.wheelDeltaY || e.wheelDelt aX) * mouseWheelZoomSpeed) - 1);
918 }
919
920 // Block swipe gesture.
921 e.consume(true);
922 },
923
924 /**
925 * @param {!Event} e
926 */
927 _onKeyDown: function(e) 709 _onKeyDown: function(e)
928 { 710 {
929 this._handleZoomPanKeys(e);
930 this._handleSelectionNavigation(e); 711 this._handleSelectionNavigation(e);
931 }, 712 },
932 713
933 /** 714 /**
934 * @param {!Event} e 715 * @param {!Event} e
935 */ 716 */
936 _handleSelectionNavigation: function(e) 717 _handleSelectionNavigation: function(e)
937 { 718 {
938 if (!WebInspector.KeyboardShortcut.hasNoModifiers(e)) 719 if (!WebInspector.KeyboardShortcut.hasNoModifiers(e))
939 return; 720 return;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 if (!entriesIntersect(this._selectedEntryIndex, levelIndexes[indexOn Level])) { 771 if (!entriesIntersect(this._selectedEntryIndex, levelIndexes[indexOn Level])) {
991 ++indexOnLevel; 772 ++indexOnLevel;
992 if (indexOnLevel >= levelIndexes.length || !entriesIntersect(thi s._selectedEntryIndex, levelIndexes[indexOnLevel])) 773 if (indexOnLevel >= levelIndexes.length || !entriesIntersect(thi s._selectedEntryIndex, levelIndexes[indexOnLevel]))
993 return; 774 return;
994 } 775 }
995 this.dispatchEventToListeners(WebInspector.FlameChart.Events.EntrySe lected, levelIndexes[indexOnLevel]); 776 this.dispatchEventToListeners(WebInspector.FlameChart.Events.EntrySe lected, levelIndexes[indexOnLevel]);
996 } 777 }
997 }, 778 },
998 779
999 /** 780 /**
1000 * @param {!Event} e
1001 */
1002 _handleZoomPanKeys: function(e)
1003 {
1004 if (!WebInspector.KeyboardShortcut.hasNoModifiers(e))
1005 return;
1006 var zoomMultiplier = e.shiftKey ? 0.8 : 0.3;
1007 var panMultiplier = e.shiftKey ? 320 : 80;
1008 if (e.keyCode === "A".charCodeAt(0)) {
1009 this._handlePanGesture(-panMultiplier * this._pixelToTime);
1010 e.consume(true);
1011 } else if (e.keyCode === "D".charCodeAt(0)) {
1012 this._handlePanGesture(panMultiplier * this._pixelToTime);
1013 e.consume(true);
1014 } else if (e.keyCode === "W".charCodeAt(0)) {
1015 this._handleZoomGesture(-zoomMultiplier);
1016 e.consume(true);
1017 } else if (e.keyCode === "S".charCodeAt(0)) {
1018 this._handleZoomGesture(zoomMultiplier);
1019 e.consume(true);
1020 }
1021 },
1022
1023 /**
1024 * @param {number} zoom
1025 */
1026 _handleZoomGesture: function(zoom)
1027 {
1028 this._cancelAnimation();
1029 var bounds = this._windowForGesture();
1030 var cursorTime = this._cursorTime(this._lastMouseOffsetX);
1031 bounds.left += (bounds.left - cursorTime) * zoom;
1032 bounds.right += (bounds.right - cursorTime) * zoom;
1033 this._requestWindowTimes(bounds);
1034 },
1035
1036 /**
1037 * @param {number} shift
1038 */
1039 _handlePanGesture: function(shift)
1040 {
1041 this._cancelAnimation();
1042 var bounds = this._windowForGesture();
1043 shift = Number.constrain(shift, this._minimumBoundary - bounds.left, thi s._totalTime + this._minimumBoundary - bounds.right);
1044 bounds.left += shift;
1045 bounds.right += shift;
1046 this._requestWindowTimes(bounds);
1047 },
1048
1049 /**
1050 * @return {{left: number, right: number}}
1051 */
1052 _windowForGesture: function()
1053 {
1054 var windowLeft = this._timeWindowLeft ? this._timeWindowLeft : this._dat aProvider.minimumBoundary();
1055 var windowRight = this._timeWindowRight !== Infinity ? this._timeWindowR ight : this._dataProvider.minimumBoundary() + this._dataProvider.totalTime();
1056 return {left: windowLeft, right: windowRight};
1057 },
1058
1059 /**
1060 * @param {{left: number, right: number}} bounds
1061 */
1062 _requestWindowTimes: function(bounds)
1063 {
1064 bounds.left = Number.constrain(bounds.left, this._minimumBoundary, this. _totalTime + this._minimumBoundary);
1065 bounds.right = Number.constrain(bounds.right, this._minimumBoundary, thi s._totalTime + this._minimumBoundary);
1066 if (bounds.right - bounds.left < WebInspector.FlameChart.MinimalTimeWind owMs)
1067 return;
1068 this._flameChartDelegate.requestWindowTimes(bounds.left, bounds.right);
1069 },
1070
1071 /**
1072 * @param {number} x 781 * @param {number} x
1073 * @return {number} 782 * @return {number}
1074 */ 783 */
1075 _cursorTime: function(x) 784 _cursorTime: function(x)
1076 { 785 {
1077 return (x + this._pixelWindowLeft - this._paddingLeft) * this._pixelToTi me + this._minimumBoundary; 786 return (x + this._pixelWindowLeft - this._paddingLeft) * this._pixelToTi me + this._minimumBoundary;
1078 }, 787 },
1079 788
1080 /** 789 /**
1081 * @param {number} x 790 * @param {number} x
1082 * @param {number} y 791 * @param {number} y
1083 * @return {number} 792 * @return {number}
1084 */ 793 */
1085 _coordinatesToEntryIndex: function(x, y) 794 _coordinatesToEntryIndex: function(x, y)
1086 { 795 {
1087 if (x < 0 || y < 0) 796 if (x < 0 || y < 0)
1088 return -1; 797 return -1;
1089 y += this._scrollTop; 798 y += this.scrollOffset();
1090 var timelineData = this._timelineData(); 799 var timelineData = this._timelineData();
1091 if (!timelineData) 800 if (!timelineData)
1092 return -1; 801 return -1;
1093 var cursorTime = this._cursorTime(x); 802 var cursorTime = this._cursorTime(x);
1094 var cursorLevel = this._visibleLevelOffsets.upperBound(y) - 1; 803 var cursorLevel = this._visibleLevelOffsets.upperBound(y) - 1;
1095 if (cursorLevel < 0 || !this._visibleLevels[cursorLevel]) 804 if (cursorLevel < 0 || !this._visibleLevels[cursorLevel])
1096 return -1; 805 return -1;
1097 var offsetFromLevel = y - this._visibleLevelOffsets[cursorLevel]; 806 var offsetFromLevel = y - this._visibleLevelOffsets[cursorLevel];
1098 if (offsetFromLevel > this._barHeight) 807 if (offsetFromLevel > this._barHeight)
1099 return -1; 808 return -1;
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 855
1147 /** 856 /**
1148 * @param {number} x 857 * @param {number} x
1149 * @param {number} y 858 * @param {number} y
1150 * @return {number} 859 * @return {number}
1151 */ 860 */
1152 _coordinatesToGroupIndex: function(x, y) 861 _coordinatesToGroupIndex: function(x, y)
1153 { 862 {
1154 if (x < 0 || y < 0) 863 if (x < 0 || y < 0)
1155 return -1; 864 return -1;
1156 y += this._scrollTop; 865 y += this.scrollOffset();
1157 var groups = this._rawTimelineData.groups || []; 866 var groups = this._rawTimelineData.groups || [];
1158 var group = this._groupOffsets.upperBound(y) - 1; 867 var group = this._groupOffsets.upperBound(y) - 1;
1159 868
1160 if (group < 0 || group >= groups.length || y - this._groupOffsets[group] >= groups[group].style.height) 869 if (group < 0 || group >= groups.length || y - this._groupOffsets[group] >= groups[group].style.height)
1161 return -1; 870 return -1;
1162 var context = this._canvas.getContext("2d"); 871 var context = this._canvas.getContext("2d");
1163 context.save(); 872 context.save();
1164 context.font = groups[group].style.font; 873 context.font = groups[group].style.font;
1165 var right = this._headerLeftPadding + this._labelWidthForGroup(context, groups[group]); 874 var right = this._headerLeftPadding + this._labelWidthForGroup(context, groups[group]);
1166 context.restore(); 875 context.restore();
(...skipping 29 matching lines...) Expand all
1196 } 905 }
1197 return markerIndex; 906 return markerIndex;
1198 }, 907 },
1199 908
1200 /** 909 /**
1201 * @param {number} time 910 * @param {number} time
1202 * @return {number} 911 * @return {number}
1203 */ 912 */
1204 _markerIndexBeforeTime: function(time) 913 _markerIndexBeforeTime: function(time)
1205 { 914 {
1206 /** 915 return this._timelineData().markers.lowerBound(time, (markerTimestamp, m arker) => markerTimestamp - marker.startTime());
1207 * @param {number} markerTimestamp
1208 * @param {!WebInspector.FlameChartMarker} marker
1209 * @return {number}
1210 */
1211 function comparator(markerTimestamp, marker)
1212 {
1213 return markerTimestamp - marker.startTime();
1214 }
1215 return this._timelineData().markers.lowerBound(time, comparator);
1216 }, 916 },
1217 917
1218 /** 918 /**
1219 * @param {number} height 919 * @param {number} height
1220 * @param {number} width 920 * @param {number} width
1221 */ 921 */
1222 _draw: function(width, height) 922 _draw: function(width, height)
1223 { 923 {
1224 var timelineData = this._timelineData(); 924 var timelineData = this._timelineData();
1225 if (!timelineData) 925 if (!timelineData)
1226 return; 926 return;
1227 927
1228 var context = this._canvas.getContext("2d"); 928 var context = this._canvas.getContext("2d");
1229 context.save(); 929 context.save();
1230 var ratio = window.devicePixelRatio; 930 var ratio = window.devicePixelRatio;
931 var top = this.scrollOffset();
1231 context.scale(ratio, ratio); 932 context.scale(ratio, ratio);
1232 context.translate(0, -this._scrollTop); 933 context.translate(0, -top);
1233 context.font = "11px " + WebInspector.fontFamily(); 934 context.font = "11px " + WebInspector.fontFamily();
1234 935
1235 var timeWindowRight = this._timeWindowRight; 936 var timeWindowRight = this._timeWindowRight;
1236 var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._ti meToPixel; 937 var timeWindowLeft = this._timeWindowLeft - this._paddingLeft / this._ti meToPixel;
1237 var entryTotalTimes = timelineData.entryTotalTimes; 938 var entryTotalTimes = timelineData.entryTotalTimes;
1238 var entryStartTimes = timelineData.entryStartTimes; 939 var entryStartTimes = timelineData.entryStartTimes;
1239 var entryLevels = timelineData.entryLevels; 940 var entryLevels = timelineData.entryLevels;
1240 941
1241 var titleIndices = []; 942 var titleIndices = [];
1242 var markerIndices = []; 943 var markerIndices = [];
1243 var textPadding = this._dataProvider.textPadding(); 944 var textPadding = this._dataProvider.textPadding();
1244 var minTextWidth = 2 * textPadding + this._measureWidth(context, "\u2026 "); 945 var minTextWidth = 2 * textPadding + this._measureWidth(context, "\u2026 ");
1245 var barHeight = this._barHeight; 946 var barHeight = this._barHeight;
1246 var top = this._scrollTop;
1247 var minVisibleBarLevel = Math.max(this._visibleLevelOffsets.upperBound(t op) - 1, 0); 947 var minVisibleBarLevel = Math.max(this._visibleLevelOffsets.upperBound(t op) - 1, 0);
1248 948
1249 /** @type {!Map<string, !Array<number>>} */ 949 /** @type {!Map<string, !Array<number>>} */
1250 var colorBuckets = new Map(); 950 var colorBuckets = new Map();
1251 for (var level = minVisibleBarLevel; level < this._dataProvider.maxStack Depth(); ++level) { 951 for (var level = minVisibleBarLevel; level < this._dataProvider.maxStack Depth(); ++level) {
1252 if (this._levelToHeight(level) > top + height) 952 if (this._levelToHeight(level) > top + height)
1253 break; 953 break;
1254 if (!this._visibleLevels[level]) 954 if (!this._visibleLevels[level])
1255 continue; 955 continue;
1256 956
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1353 context.restore(); 1053 context.restore();
1354 1054
1355 var offsets = this._dataProvider.dividerOffsets(this._calculator.minimum Boundary(), this._calculator.maximumBoundary()); 1055 var offsets = this._dataProvider.dividerOffsets(this._calculator.minimum Boundary(), this._calculator.maximumBoundary());
1356 WebInspector.TimelineGrid.drawCanvasGrid(this._canvas, this._calculator, offsets); 1056 WebInspector.TimelineGrid.drawCanvasGrid(this._canvas, this._calculator, offsets);
1357 this._drawMarkers(); 1057 this._drawMarkers();
1358 this._drawGroupHeaders(width, height); 1058 this._drawGroupHeaders(width, height);
1359 1059
1360 this._updateElementPosition(this._highlightElement, this._highlightedEnt ryIndex); 1060 this._updateElementPosition(this._highlightElement, this._highlightedEnt ryIndex);
1361 this._updateElementPosition(this._selectedElement, this._selectedEntryIn dex); 1061 this._updateElementPosition(this._selectedElement, this._selectedEntryIn dex);
1362 this._updateMarkerHighlight(); 1062 this._updateMarkerHighlight();
1363 this._updateRangeSelectionOverlay();
1364 }, 1063 },
1365 1064
1366 /** 1065 /**
1367 * @param {number} width 1066 * @param {number} width
1368 * @param {number} height 1067 * @param {number} height
1369 */ 1068 */
1370 _drawGroupHeaders: function(width, height) 1069 _drawGroupHeaders: function(width, height)
1371 { 1070 {
1372 var context = this._canvas.getContext("2d"); 1071 var context = this._canvas.getContext("2d");
1373 var top = this._scrollTop; 1072 var top = this.scrollOffset();
1374 var ratio = window.devicePixelRatio; 1073 var ratio = window.devicePixelRatio;
1375 var barHeight = this._barHeight; 1074 var barHeight = this._barHeight;
1376 var textBaseHeight = barHeight - this._dataProvider.textBaseline(); 1075 var textBaseHeight = barHeight - this._dataProvider.textBaseline();
1377 var groups = this._rawTimelineData.groups || []; 1076 var groups = this._rawTimelineData.groups || [];
1378 if (!groups.length) 1077 if (!groups.length)
1379 return; 1078 return;
1380 1079
1381 var groupOffsets = this._groupOffsets; 1080 var groupOffsets = this._groupOffsets;
1382 var lastGroupOffset = Array.prototype.peekLast.call(groupOffsets); 1081 var lastGroupOffset = Array.prototype.peekLast.call(groupOffsets);
1383 var colorUsage = WebInspector.ThemeSupport.ColorUsage; 1082 var colorUsage = WebInspector.ThemeSupport.ColorUsage;
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
1765 var nextGroupLevel = isLastGroup ? this._dataProvider.maxStackDepth() : groups[index + 1].startLevel; 1464 var nextGroupLevel = isLastGroup ? this._dataProvider.maxStackDepth() : groups[index + 1].startLevel;
1766 // For groups that only have one line and share header line, pretend the se are not collapsible. 1465 // For groups that only have one line and share header line, pretend the se are not collapsible.
1767 return nextGroupLevel !== groups[index].startLevel + 1; 1466 return nextGroupLevel !== groups[index].startLevel + 1;
1768 }, 1467 },
1769 1468
1770 /** 1469 /**
1771 * @param {number} entryIndex 1470 * @param {number} entryIndex
1772 */ 1471 */
1773 setSelectedEntry: function(entryIndex) 1472 setSelectedEntry: function(entryIndex)
1774 { 1473 {
1775 if (entryIndex === -1 && !this._isDragging) 1474 if (entryIndex === -1 && !this.isDragging())
1776 this._hideRangeSelection(); 1475 this.hideRangeSelection();
1777 if (this._selectedEntryIndex === entryIndex) 1476 if (this._selectedEntryIndex === entryIndex)
1778 return; 1477 return;
1779 this._selectedEntryIndex = entryIndex; 1478 this._selectedEntryIndex = entryIndex;
1780 this._revealEntry(entryIndex); 1479 this._revealEntry(entryIndex);
1781 this._updateElementPosition(this._selectedElement, this._selectedEntryIn dex); 1480 this._updateElementPosition(this._selectedElement, this._selectedEntryIn dex);
1782 }, 1481 },
1783 1482
1784 /** 1483 /**
1785 * @param {!Element} element 1484 * @param {!Element} element
1786 * @param {number} entryIndex 1485 * @param {number} entryIndex
(...skipping 10 matching lines...) Expand all
1797 return; 1496 return;
1798 var timelineData = this._timelineData(); 1497 var timelineData = this._timelineData();
1799 var barX = this._timeToPositionClipped(timeRange.startTime); 1498 var barX = this._timeToPositionClipped(timeRange.startTime);
1800 var barRight = this._timeToPositionClipped(timeRange.endTime); 1499 var barRight = this._timeToPositionClipped(timeRange.endTime);
1801 if (barRight === 0 || barX === this._offsetWidth) 1500 if (barRight === 0 || barX === this._offsetWidth)
1802 return; 1501 return;
1803 var barWidth = barRight - barX; 1502 var barWidth = barRight - barX;
1804 var barCenter = barX + barWidth / 2; 1503 var barCenter = barX + barWidth / 2;
1805 barWidth = Math.max(barWidth, elementMinWidth); 1504 barWidth = Math.max(barWidth, elementMinWidth);
1806 barX = barCenter - barWidth / 2; 1505 barX = barCenter - barWidth / 2;
1807 var barY = this._levelToHeight(timelineData.entryLevels[entryIndex]) - t his._scrollTop; 1506 var barY = this._levelToHeight(timelineData.entryLevels[entryIndex]) - t his.scrollOffset();
1808 var style = element.style; 1507 var style = element.style;
1809 style.left = barX + "px"; 1508 style.left = barX + "px";
1810 style.top = barY + "px"; 1509 style.top = barY + "px";
1811 style.width = barWidth + "px"; 1510 style.width = barWidth + "px";
1812 style.height = this._barHeight - 1 + "px"; 1511 style.height = this._barHeight - 1 + "px";
1813 this.contentElement.appendChild(element); 1512 this.contentElement.appendChild(element);
1814 }, 1513 },
1815 1514
1816 /** 1515 /**
1817 * @param {number} time 1516 * @param {number} time
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1917 } else { 1616 } else {
1918 this._windowLeft = 0; 1617 this._windowLeft = 0;
1919 this._windowRight = 1; 1618 this._windowRight = 1;
1920 } 1619 }
1921 1620
1922 var totalPixels = Math.floor((this._offsetWidth - this._paddingLeft) / w indowWidth); 1621 var totalPixels = Math.floor((this._offsetWidth - this._paddingLeft) / w indowWidth);
1923 this._pixelWindowLeft = Math.floor(totalPixels * this._windowLeft); 1622 this._pixelWindowLeft = Math.floor(totalPixels * this._windowLeft);
1924 1623
1925 this._timeToPixel = totalPixels / this._totalTime; 1624 this._timeToPixel = totalPixels / this._totalTime;
1926 this._pixelToTime = this._totalTime / totalPixels; 1625 this._pixelToTime = this._totalTime / totalPixels;
1927
1928 this._updateScrollBar();
1929 }, 1626 },
1930 1627
1931 _updateHeight: function() 1628 _updateHeight: function()
1932 { 1629 {
1933 this._totalHeight = this._levelToHeight(this._dataProvider.maxStackDepth ()); 1630 var height = this._levelToHeight(this._dataProvider.maxStackDepth());
1934 this._vScrollContent.style.height = this._totalHeight + "px"; 1631 this.setContentHeight(height);
1935 if (this._scrollTop + this._offsetHeight > this._totalHeight) {
1936 this._scrollTop = Math.max(0, this._totalHeight - this._offsetHeight );
1937 this._vScrollElement.scrollTop = this._scrollTop;
1938 }
1939 }, 1632 },
1940 1633
1634 /**
1635 * @override
1636 */
1941 onResize: function() 1637 onResize: function()
1942 { 1638 {
1943 this._updateScrollBar(); 1639 WebInspector.FlameChart.prototype.__proto__.onResize.call(this);
1944 this._updateContentElementSize();
1945 this.scheduleUpdate(); 1640 this.scheduleUpdate();
1946 }, 1641 },
1947 1642
1948 _updateScrollBar: function() 1643 /**
1949 { 1644 * @override
1950 var showScroll = this._totalHeight > this._offsetHeight; 1645 */
1951 if (this._vScrollElement.classList.contains("hidden") === showScroll) {
1952 this._vScrollElement.classList.toggle("hidden", !showScroll);
1953 this._updateContentElementSize();
1954 }
1955 },
1956
1957 _updateContentElementSize: function()
1958 {
1959 var offsetWidth = this._vScrollElement.offsetLeft;
1960 if (!offsetWidth)
1961 offsetWidth = this.contentElement.offsetWidth;
1962 this._offsetWidth = offsetWidth;
1963 this._offsetHeight = this.contentElement.offsetHeight;
1964 },
1965
1966 _onScroll: function()
1967 {
1968 this._scrollTop = this._vScrollElement.scrollTop;
1969 this.scheduleUpdate();
1970 },
1971
1972 scheduleUpdate: function()
1973 {
1974 if (this._updateTimerId || this._cancelWindowTimesAnimation)
1975 return;
1976 this._updateTimerId = this.element.window().requestAnimationFrame(this.u pdate.bind(this));
1977 },
1978
1979 update: function() 1646 update: function()
1980 { 1647 {
1981 this._updateTimerId = 0;
1982 if (!this._timelineData()) 1648 if (!this._timelineData())
1983 return; 1649 return;
1984 this._resetCanvas(); 1650 this._resetCanvas();
1985 this._updateHeight(); 1651 this._updateHeight();
1986 this._updateBoundaries(); 1652 this._updateBoundaries();
1987 this._calculator._updateBoundaries(this); 1653 this._calculator._updateBoundaries(this);
1988 this._draw(this._offsetWidth, this._offsetHeight); 1654 this._draw(this._offsetWidth, this._offsetHeight);
1989 if (!this._isDragging) 1655 if (!this.isDragging())
1990 this._updateHighlight(); 1656 this._updateHighlight();
1991 }, 1657 },
1992 1658
1993 reset: function() 1659 reset: function()
1994 { 1660 {
1995 this._vScrollElement.scrollTop = 0; 1661 WebInspector.FlameChart.prototype.__proto__.reset.call(this);
1996 this._scrollTop = 0;
1997 this._highlightedMarkerIndex = -1; 1662 this._highlightedMarkerIndex = -1;
1998 this._highlightedEntryIndex = -1; 1663 this._highlightedEntryIndex = -1;
1999 this._selectedEntryIndex = -1; 1664 this._selectedEntryIndex = -1;
2000 this._rangeSelectionStart = 0;
2001 this._rangeSelectionEnd = 0;
2002 /** @type {!Map<string,!Map<string,number>>} */ 1665 /** @type {!Map<string,!Map<string,number>>} */
2003 this._textWidth = new Map(); 1666 this._textWidth = new Map();
2004 this.update(); 1667 this.update();
2005 }, 1668 },
2006 1669
2007 _enabled: function() 1670 _enabled: function()
2008 { 1671 {
2009 return this._rawTimelineDataLength !== 0; 1672 return this._rawTimelineDataLength !== 0;
2010 }, 1673 },
2011 1674
2012 __proto__: WebInspector.HBox.prototype 1675 __proto__: WebInspector.ChartViewport.prototype
2013 } 1676 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698