@@ -13,6 +13,7 @@ import {
1313} from 'firefox-profiler/components/shared/chart/Viewport' ;
1414import { ChartCanvas } from 'firefox-profiler/components/shared/chart/Canvas' ;
1515import { TooltipMarker } from 'firefox-profiler/components/tooltip/Marker' ;
16+ import { FlowGapTooltip } from 'firefox-profiler/components/tooltip/FlowGap' ;
1617import TextMeasurement from 'firefox-profiler/utils/text-measurement' ;
1718import { bisectionRight } from 'firefox-profiler/utils/bisect' ;
1819import {
@@ -33,8 +34,10 @@ import type {
3334 FlowTimingRow ,
3435 FlowTimingArrow ,
3536} from 'firefox-profiler/types' ;
36- import { getStartEndRangeForMarker } from 'firefox-profiler/utils' ;
37- import { ensureExists } from 'firefox-profiler/utils/flow' ;
37+ import {
38+ ensureExists ,
39+ assertExhaustiveCheck ,
40+ } from 'firefox-profiler/utils/flow' ;
3841import { computeArrowsRelatedToMarker } from 'firefox-profiler/profile-logic/marker-data' ;
3942
4043import type {
@@ -44,13 +47,28 @@ import type {
4447
4548import type { WrapFunctionInDispatch } from 'firefox-profiler/utils/connect' ;
4649
47- type HoveredFlowPanelItems = { |
50+ type FlowPanelHoverInfo = { |
4851 rowIndex : number | null ,
4952 flowIndex : IndexIntoFlowTable | null ,
50- indexInFlowMarkers : number | null , // index into flows[flowIndex].flowMarkers
51- threadIndex : ThreadIndex | null ,
52- markerIndex : MarkerIndex | null ,
53- flowMarkerIndex : number | null ,
53+ hoveredItem : HoveredFlowPanelItem | null ,
54+ | } ;
55+
56+ type HoveredFlowPanelItem =
57+ | { |
58+ type : 'SINGLE_MARKER' ,
59+ hoveredMarker : SingleHoveredFlowPanelItem ,
60+ | }
61+ | { |
62+ type : 'BETWEEN_MARKERS' ,
63+ markerBeforeHoveredGap : SingleHoveredFlowPanelItem ,
64+ markerAfterHoveredGap : SingleHoveredFlowPanelItem ,
65+ | } ;
66+
67+ type SingleHoveredFlowPanelItem = { |
68+ indexInFlowMarkers : number , // index into flows[flowIndex].flowMarkers
69+ threadIndex : ThreadIndex ,
70+ markerIndex : MarkerIndex ,
71+ flowMarkerIndex : number ,
5472| } ;
5573
5674type OwnProps = { |
@@ -90,7 +108,7 @@ class FlowPanelCanvasImpl extends React.PureComponent<Props> {
90108 drawCanvas = (
91109 ctx : CanvasRenderingContext2D ,
92110 scale : ChartCanvasScale ,
93- hoverInfo : ChartCanvasHoverInfo < HoveredFlowPanelItems >
111+ hoverInfo : ChartCanvasHoverInfo < FlowPanelHoverInfo >
94112 ) => {
95113 const {
96114 rowHeight,
@@ -124,15 +142,19 @@ class FlowPanelCanvasImpl extends React.PureComponent<Props> {
124142 this . drawSeparatorsAndLabels ( ctx , startRow , endRow ) ;
125143
126144 const { hoveredItem } = hoverInfo ;
127- if ( hoveredItem !== null ) {
128- const { threadIndex, flowMarkerIndex } = hoveredItem ;
145+ if (
146+ hoveredItem !== null &&
147+ hoveredItem . hoveredItem &&
148+ hoveredItem . hoveredItem . type === 'SINGLE_MARKER'
149+ ) {
150+ const { threadIndex, flowMarkerIndex } =
151+ hoveredItem . hoveredItem . hoveredMarker ;
129152 if ( threadIndex !== null && flowMarkerIndex !== null ) {
130153 const arrows = this . _memoizedGetArrows (
131154 threadIndex ,
132155 flowMarkerIndex ,
133156 flowTiming
134157 ) ;
135- console . log ( { arrows } ) ;
136158 this . drawArrows ( ctx , arrows , startRow , endRow ) ;
137159 }
138160 }
@@ -678,7 +700,7 @@ class FlowPanelCanvasImpl extends React.PureComponent<Props> {
678700 ctx . restore ( ) ;
679701 }
680702
681- hitTest = ( x : CssPixels , y : CssPixels ) : HoveredFlowPanelItems | null => {
703+ hitTest = ( x : CssPixels , y : CssPixels ) : FlowPanelHoverInfo | null => {
682704 const {
683705 rangeStart,
684706 rangeEnd,
@@ -695,11 +717,6 @@ class FlowPanelCanvasImpl extends React.PureComponent<Props> {
695717 return null ;
696718 }
697719
698- let markerIndex = null ;
699- let flowMarkerIndex = null ;
700- let threadIndex = null ;
701- let indexInFlowMarkers = null ;
702-
703720 const markerContainerWidth = containerWidth - marginLeft - marginRight ;
704721
705722 const rangeLength : Milliseconds = rangeEnd - rangeStart ;
@@ -766,40 +783,85 @@ class FlowPanelCanvasImpl extends React.PureComponent<Props> {
766783 // 3. When we found the closest, we still have to check if it's in close
767784 // enough!
768785 if ( isMarkerTimingInDotRadius ( closest ) ) {
769- markerIndex = markerTiming . markerIndex [ closest ] ;
770- flowMarkerIndex = markerTiming . flowMarkerIndex [ closest ] ;
771- threadIndex = markerTiming . threadIndex [ closest ] ;
772- indexInFlowMarkers = closest ;
786+ return {
787+ rowIndex,
788+ flowIndex,
789+ hoveredItem : {
790+ type : 'SINGLE_MARKER' ,
791+ hoveredMarker : {
792+ markerIndex : markerTiming . markerIndex [ closest ] ,
793+ flowMarkerIndex : markerTiming . flowMarkerIndex [ closest ] ,
794+ threadIndex : markerTiming . threadIndex [ closest ] ,
795+ indexInFlowMarkers : closest ,
796+ } ,
797+ } ,
798+ } ;
773799 }
800+
801+ // The cursor is between two markers.
802+ return {
803+ rowIndex,
804+ flowIndex,
805+ hoveredItem : {
806+ type : 'BETWEEN_MARKERS' ,
807+ markerBeforeHoveredGap : {
808+ markerIndex : markerTiming . markerIndex [ prevStartIndex ] ,
809+ flowMarkerIndex : markerTiming . flowMarkerIndex [ prevStartIndex ] ,
810+ threadIndex : markerTiming . threadIndex [ prevStartIndex ] ,
811+ indexInFlowMarkers : prevStartIndex ,
812+ } ,
813+ markerAfterHoveredGap : {
814+ markerIndex : markerTiming . markerIndex [ nextStartIndex ] ,
815+ flowMarkerIndex : markerTiming . flowMarkerIndex [ nextStartIndex ] ,
816+ threadIndex : markerTiming . threadIndex [ nextStartIndex ] ,
817+ indexInFlowMarkers : nextStartIndex ,
818+ } ,
819+ } ,
820+ } ;
774821 } else if ( nextStartIndex === 0 ) {
775822 // 4. Special case 1: the mouse cursor is at the left of all markers in
776823 // this line. Then, we have only 1 candidate, we can check if it's inside
777824 // our hit test range right away.
778825 if ( isMarkerTimingInDotRadius ( nextStartIndex ) ) {
779- markerIndex = markerTiming . markerIndex [ nextStartIndex ] ;
780- flowMarkerIndex = markerTiming . flowMarkerIndex [ nextStartIndex ] ;
781- threadIndex = markerTiming . threadIndex [ nextStartIndex ] ;
782- indexInFlowMarkers = nextStartIndex ;
826+ return {
827+ rowIndex,
828+ flowIndex,
829+ hoveredItem : {
830+ type : 'SINGLE_MARKER' ,
831+ hoveredMarker : {
832+ markerIndex : markerTiming . markerIndex [ nextStartIndex ] ,
833+ flowMarkerIndex : markerTiming . flowMarkerIndex [ nextStartIndex ] ,
834+ threadIndex : markerTiming . threadIndex [ nextStartIndex ] ,
835+ indexInFlowMarkers : nextStartIndex ,
836+ } ,
837+ } ,
838+ } ;
783839 }
784840 } else {
785841 // 5. Special case 2: the mouse cursor is at the right of all markers in
786842 // this line. Then we only have 1 candidate as well, let's check if it's
787843 // inside our hit test range.
788844 if ( isMarkerTimingInDotRadius ( nextStartIndex - 1 ) ) {
789- markerIndex = markerTiming . markerIndex [ nextStartIndex - 1 ] ;
790- flowMarkerIndex = markerTiming . flowMarkerIndex [ nextStartIndex - 1 ] ;
791- threadIndex = markerTiming . threadIndex [ nextStartIndex - 1 ] ;
792- indexInFlowMarkers = nextStartIndex - 1 ;
845+ return {
846+ rowIndex,
847+ flowIndex,
848+ hoveredItem : {
849+ type : 'SINGLE_MARKER' ,
850+ hoveredMarker : {
851+ markerIndex : markerTiming . markerIndex [ nextStartIndex - 1 ] ,
852+ flowMarkerIndex : markerTiming . flowMarkerIndex [ nextStartIndex - 1 ] ,
853+ threadIndex : markerTiming . threadIndex [ nextStartIndex - 1 ] ,
854+ indexInFlowMarkers : nextStartIndex - 1 ,
855+ } ,
856+ } ,
857+ } ;
793858 }
794859 }
795860
796861 return {
797862 rowIndex,
798863 flowIndex,
799- indexInFlowMarkers,
800- markerIndex,
801- flowMarkerIndex,
802- threadIndex,
864+ hoveredItem : null ,
803865 } ;
804866 } ;
805867
@@ -834,36 +896,9 @@ class FlowPanelCanvasImpl extends React.PureComponent<Props> {
834896 this . props . changeMouseTimePosition ( null ) ;
835897 } ;
836898
837- onDoubleClickMarker = ( hoveredItems : HoveredFlowPanelItems | null ) => {
838- const markerIndex = hoveredItems === null ? null : hoveredItems . markerIndex ;
839- const threadIndex = hoveredItems === null ? null : hoveredItems . threadIndex ;
840- if ( markerIndex === null || threadIndex === null ) {
841- return ;
842- }
843- const {
844- fullMarkerListPerThread,
845- updatePreviewSelection,
846- rangeStart,
847- rangeEnd,
848- } = this . props ;
849- const marker = ensureExists (
850- fullMarkerListPerThread [ threadIndex ] [ markerIndex ]
851- ) ;
852- const { start, end } = getStartEndRangeForMarker (
853- rangeStart ,
854- rangeEnd ,
855- marker
856- ) ;
899+ onDoubleClickMarker = ( _hoveredItems : FlowPanelHoverInfo | null ) => { } ;
857900
858- updatePreviewSelection ( {
859- hasSelection : true ,
860- isModifying : false ,
861- selectionStart : start ,
862- selectionEnd : end ,
863- } ) ;
864- } ;
865-
866- onSelectItem = ( hoveredItems : HoveredFlowPanelItems | null ) => {
901+ onSelectItem = ( hoveredItems : FlowPanelHoverInfo | null ) => {
867902 const flowIndex = hoveredItems === null ? null : hoveredItems . flowIndex ;
868903 if ( flowIndex === null ) {
869904 return ;
@@ -873,35 +908,65 @@ class FlowPanelCanvasImpl extends React.PureComponent<Props> {
873908 changeActiveFlows ( [ flowIndex ] ) ;
874909 } ;
875910
876- onRightClickMarker = ( _hoveredItems : HoveredFlowPanelItems | null ) => {
911+ onRightClickMarker = ( _hoveredItems : FlowPanelHoverInfo | null ) => {
877912 // const markerIndex = hoveredItems === null ? null : hoveredItems.markerIndex;
878913 // const { changeRightClickedMarker, threadsKey } = this.props;
879914 // changeRightClickedMarker(threadsKey, markerIndex);
880915 } ;
881916
882- getHoveredMarkerInfo = ( {
883- threadIndex,
884- markerIndex,
885- } : HoveredFlowPanelItems ) : React . Node => {
886- if (
887- ! this . props . shouldDisplayTooltips ( ) ||
888- threadIndex === null ||
889- markerIndex === null
890- ) {
917+ getHoveredMarkerInfo = ( hoverInfo : FlowPanelHoverInfo ) : React . Node => {
918+ if ( ! this . props . shouldDisplayTooltips ( ) || hoverInfo . hoveredItem === null ) {
891919 return null ;
892920 }
893921
894- const marker = ensureExists (
895- this . props . fullMarkerListPerThread [ threadIndex ] [ markerIndex ]
896- ) ;
897- return (
898- < TooltipMarker
899- markerIndex = { markerIndex }
900- marker = { marker }
901- threadsKey = { threadIndex }
902- restrictHeightWidth = { true }
903- />
904- ) ;
922+ const { hoveredItem } = hoverInfo ;
923+
924+ switch ( hoveredItem . type ) {
925+ case 'SINGLE_MARKER' : {
926+ const { threadIndex, markerIndex } = hoveredItem . hoveredMarker ;
927+
928+ const marker = ensureExists (
929+ this . props . fullMarkerListPerThread [ threadIndex ] [ markerIndex ]
930+ ) ;
931+ return (
932+ < TooltipMarker
933+ markerIndex = { markerIndex }
934+ marker = { marker }
935+ threadsKey = { threadIndex }
936+ restrictHeightWidth = { true }
937+ />
938+ ) ;
939+ }
940+ case 'BETWEEN_MARKERS' : {
941+ const { markerBeforeHoveredGap, markerAfterHoveredGap } = hoveredItem ;
942+ const beforeGapMarker = ensureExists (
943+ this . props . fullMarkerListPerThread [
944+ markerBeforeHoveredGap . threadIndex
945+ ] [ markerBeforeHoveredGap . markerIndex ]
946+ ) ;
947+ const afterGapMarker = ensureExists (
948+ this . props . fullMarkerListPerThread [ markerAfterHoveredGap . threadIndex ] [
949+ markerAfterHoveredGap . markerIndex
950+ ]
951+ ) ;
952+ return (
953+ < FlowGapTooltip
954+ beforeGapMarkerIndex = { markerBeforeHoveredGap . markerIndex }
955+ beforeGapMarker = { beforeGapMarker }
956+ beforeGapThreadIndex = { markerBeforeHoveredGap . threadIndex }
957+ afterGapMarkerIndex = { markerAfterHoveredGap . markerIndex }
958+ afterGapMarker = { afterGapMarker }
959+ afterGapThreadIndex = { markerAfterHoveredGap . threadIndex }
960+ />
961+ ) ;
962+ }
963+ default : {
964+ throw assertExhaustiveCheck (
965+ hoveredItem . type ,
966+ 'Unhandled HoveredFlowPanelItem type.'
967+ ) ;
968+ }
969+ }
905970 } ;
906971
907972 render ( ) {
0 commit comments