Files
SpeedScope/src/views/flamechart-view-container.tsx
T
Jamie Wong 9452aeae82 Provide prev/next buttons to cycle through search results, make search results more visually prominent (#304)
This PR addresses two key pieces of feedback provided on search in #38 

1. Make the search results more visually prominent
2. Make it easier to find the matches by having some way of jumping to next

For the visual prominence facet, I switched from yellow outlines to orange backgrounds.

|Before|After|
|-|-|
|![image](https://user-images.githubusercontent.com/150329/89276105-14746700-d5f8-11ea-9c9d-1dfdfc3bd6d7.png)|![image](https://user-images.githubusercontent.com/150329/89276070-045c8780-d5f8-11ea-8664-9da0af569cec.png)|

For the easy identification portion, I added prev/next buttons to each view, which can also be operated by hitting Enter for next or Shift+Enter for previous.

![Kapture 2020-08-04 at 2 16 57](https://user-images.githubusercontent.com/150329/89276542-a1b7bb80-d5f8-11ea-8642-a172a6561734.gif)
2020-08-04 02:20:26 -07:00

213 lines
6.8 KiB
TypeScript

import {h} from 'preact'
import {FlamechartID, FlamechartViewState} from '../store/flamechart-view-state'
import {CanvasContext} from '../gl/canvas-context'
import {Flamechart} from '../lib/flamechart'
import {FlamechartRenderer, FlamechartRendererOptions} from '../gl/flamechart-renderer'
import {useActionCreator} from '../lib/preact-redux'
import {Frame, Profile, CallTreeNode} from '../lib/profile'
import {memoizeByShallowEquality} from '../lib/utils'
import {FlamechartView} from './flamechart-view'
import {
getRowAtlas,
createGetColorBucketForFrame,
getCanvasContext,
createGetCSSColorForFrame,
getFrameToColorBucket,
} from '../store/getters'
import {Vec2, Rect} from '../lib/math'
import {actions} from '../store/actions'
import {memo} from 'preact/compat'
import {ActiveProfileState} from '../store'
import {FlamechartSearchContextProvider} from './flamechart-search-view'
interface FlamechartSetters {
setLogicalSpaceViewportSize: (logicalSpaceViewportSize: Vec2) => void
setConfigSpaceViewportRect: (configSpaceViewportRect: Rect) => void
setNodeHover: (hover: {node: CallTreeNode; event: MouseEvent} | null) => void
setSelectedNode: (node: CallTreeNode | null) => void
}
const {
setHoveredNode,
setLogicalSpaceViewportSize,
setConfigSpaceViewportRect,
setSelectedNode,
} = actions.flamechart
export function useFlamechartSetters(id: FlamechartID, profileIndex: number): FlamechartSetters {
return {
setNodeHover: useActionCreator(
(hover: {node: CallTreeNode; event: MouseEvent} | null) =>
setHoveredNode({profileIndex, args: {id, hover}}),
[profileIndex, id],
),
setLogicalSpaceViewportSize: useActionCreator(
(logicalSpaceViewportSize: Vec2) =>
setLogicalSpaceViewportSize({profileIndex, args: {id, logicalSpaceViewportSize}}),
[profileIndex, id],
),
setConfigSpaceViewportRect: useActionCreator(
(configSpaceViewportRect: Rect) =>
setConfigSpaceViewportRect({profileIndex, args: {id, configSpaceViewportRect}}),
[profileIndex, id],
),
setSelectedNode: useActionCreator(
(selectedNode: CallTreeNode | null) =>
setSelectedNode({profileIndex, args: {id, selectedNode}}),
[profileIndex, id],
),
}
}
export type FlamechartViewProps = {
canvasContext: CanvasContext
flamechart: Flamechart
flamechartRenderer: FlamechartRenderer
renderInverted: boolean
getCSSColorForFrame: (frame: Frame) => string
} & FlamechartSetters &
FlamechartViewState
export const getChronoViewFlamechart = memoizeByShallowEquality(
({
profile,
getColorBucketForFrame,
}: {
profile: Profile
getColorBucketForFrame: (frame: Frame) => number
}): Flamechart => {
return new Flamechart({
getTotalWeight: profile.getTotalWeight.bind(profile),
forEachCall: profile.forEachCall.bind(profile),
formatValue: profile.formatValue.bind(profile),
getColorBucketForFrame,
})
},
)
export const createMemoizedFlamechartRenderer = (options?: FlamechartRendererOptions) =>
memoizeByShallowEquality(
({
canvasContext,
flamechart,
}: {
canvasContext: CanvasContext
flamechart: Flamechart
}): FlamechartRenderer => {
return new FlamechartRenderer(
canvasContext.gl,
getRowAtlas(canvasContext),
flamechart,
canvasContext.rectangleBatchRenderer,
canvasContext.flamechartColorPassRenderer,
options,
)
},
)
const getChronoViewFlamechartRenderer = createMemoizedFlamechartRenderer()
export interface FlamechartViewContainerProps {
activeProfileState: ActiveProfileState
glCanvas: HTMLCanvasElement
}
export const ChronoFlamechartView = memo((props: FlamechartViewContainerProps) => {
const {activeProfileState, glCanvas} = props
const {index, profile, chronoViewState} = activeProfileState
const canvasContext = getCanvasContext(glCanvas)
const frameToColorBucket = getFrameToColorBucket(profile)
const getColorBucketForFrame = createGetColorBucketForFrame(frameToColorBucket)
const getCSSColorForFrame = createGetCSSColorForFrame(frameToColorBucket)
const flamechart = getChronoViewFlamechart({profile, getColorBucketForFrame})
const flamechartRenderer = getChronoViewFlamechartRenderer({
canvasContext,
flamechart,
})
const setters = useFlamechartSetters(FlamechartID.CHRONO, index)
return (
<FlamechartSearchContextProvider
flamechart={flamechart}
selectedNode={chronoViewState.selectedNode}
setSelectedNode={setters.setSelectedNode}
configSpaceViewportRect={chronoViewState.configSpaceViewportRect}
setConfigSpaceViewportRect={setters.setConfigSpaceViewportRect}
>
<FlamechartView
renderInverted={false}
flamechart={flamechart}
flamechartRenderer={flamechartRenderer}
canvasContext={canvasContext}
getCSSColorForFrame={getCSSColorForFrame}
{...chronoViewState}
{...setters}
/>
</FlamechartSearchContextProvider>
)
})
export const getLeftHeavyFlamechart = memoizeByShallowEquality(
({
profile,
getColorBucketForFrame,
}: {
profile: Profile
getColorBucketForFrame: (frame: Frame) => number
}): Flamechart => {
return new Flamechart({
getTotalWeight: profile.getTotalNonIdleWeight.bind(profile),
forEachCall: profile.forEachCallGrouped.bind(profile),
formatValue: profile.formatValue.bind(profile),
getColorBucketForFrame,
})
},
)
const getLeftHeavyFlamechartRenderer = createMemoizedFlamechartRenderer()
export const LeftHeavyFlamechartView = memo((ownProps: FlamechartViewContainerProps) => {
const {activeProfileState, glCanvas} = ownProps
const {index, profile, leftHeavyViewState} = activeProfileState
const canvasContext = getCanvasContext(glCanvas)
const frameToColorBucket = getFrameToColorBucket(profile)
const getColorBucketForFrame = createGetColorBucketForFrame(frameToColorBucket)
const getCSSColorForFrame = createGetCSSColorForFrame(frameToColorBucket)
const flamechart = getLeftHeavyFlamechart({
profile,
getColorBucketForFrame,
})
const flamechartRenderer = getLeftHeavyFlamechartRenderer({
canvasContext,
flamechart,
})
const setters = useFlamechartSetters(FlamechartID.LEFT_HEAVY, index)
return (
<FlamechartSearchContextProvider
flamechart={flamechart}
selectedNode={leftHeavyViewState.selectedNode}
setSelectedNode={setters.setSelectedNode}
configSpaceViewportRect={leftHeavyViewState.configSpaceViewportRect}
setConfigSpaceViewportRect={setters.setConfigSpaceViewportRect}
>
<FlamechartView
renderInverted={false}
flamechart={flamechart}
flamechartRenderer={flamechartRenderer}
canvasContext={canvasContext}
getCSSColorForFrame={getCSSColorForFrame}
{...leftHeavyViewState}
{...setters}
/>
</FlamechartSearchContextProvider>
)
})