Skip to content

Commit

Permalink
Merge pull request #127 from Kitware/suspense-hook
Browse files Browse the repository at this point in the history
Add onViewReadySuspense hook
  • Loading branch information
floryst authored Mar 1, 2024
2 parents 5bd0ec1 + d47f388 commit c4e287e
Show file tree
Hide file tree
Showing 23 changed files with 226 additions and 40 deletions.
8 changes: 4 additions & 4 deletions src/core/Algorithm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { usePrevious } from '../utils/usePrevious';
import useUnmount from '../utils/useUnmount';
import {
DownstreamContext,
useDownstream,
useRepresentation,
useDownstreamContext,
useRepresentationContext,
} from './contexts';

export interface AlgorithmProps extends PropsWithChildren {
Expand Down Expand Up @@ -46,8 +46,8 @@ export default function Algorithm(props: AlgorithmProps) {
return algo;
});

const representation = useRepresentation();
const downstream = useDownstream();
const representation = useRepresentationContext();
const downstream = useDownstreamContext();

useEffect(() => {
let algoChanged = false;
Expand Down
4 changes: 2 additions & 2 deletions src/core/CellData.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { PropsWithChildren, useCallback } from 'react';
import { FieldDataContext, useDataset } from './contexts';
import { FieldDataContext, useDatasetContext } from './contexts';

export default function CellData(props: PropsWithChildren) {
const dataset = useDataset();
const dataset = useDatasetContext();
const getCellData = useCallback(() => {
return dataset.getDataSet().getCellData();
}, [dataset]);
Expand Down
6 changes: 3 additions & 3 deletions src/core/DataArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import deletionRegistry from '../utils/DeletionRegistry';
import useGetterRef from '../utils/useGetterRef';
import { usePrevious } from '../utils/usePrevious';
import useUnmount from '../utils/useUnmount';
import { useDataset, useFieldData } from './contexts';
import { useDatasetContext, useFieldDataContext } from './contexts';

export interface DataArrayProps {
/**
Expand Down Expand Up @@ -61,8 +61,8 @@ export default function DataArray(props: DataArrayProps) {
return da;
});

const getFieldData = useFieldData();
const dataset = useDataset();
const getFieldData = useFieldDataContext();
const dataset = useDatasetContext();

const { registration = DefaultProps.registration } = props;

Expand Down
6 changes: 3 additions & 3 deletions src/core/Dataset.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { vtkObject } from '@kitware/vtk.js/interfaces';
import { useEffect } from 'react';
import { useDownstream, useRepresentation } from './contexts';
import { useDownstreamContext, useRepresentationContext } from './contexts';

export interface DatasetProps {
dataset: vtkObject | null;
}

export default function Dataset(props: DatasetProps) {
const representation = useRepresentation();
const downstream = useDownstream();
const representation = useRepresentationContext();
const downstream = useDownstreamContext();

const { dataset } = props;

Expand Down
4 changes: 2 additions & 2 deletions src/core/FieldData.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { PropsWithChildren, useCallback } from 'react';
import { FieldDataContext, useDataset } from './contexts';
import { FieldDataContext, useDatasetContext } from './contexts';

export default function FieldData(props: PropsWithChildren) {
const dataset = useDataset();
const dataset = useDatasetContext();
const getFieldData = useCallback(() => {
return dataset.getDataSet().getFieldData();
}, [dataset]);
Expand Down
10 changes: 7 additions & 3 deletions src/core/ImageData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import { IDataset } from '../types';
import deletionRegistry from '../utils/DeletionRegistry';
import useGetterRef from '../utils/useGetterRef';
import useUnmount from '../utils/useUnmount';
import { DatasetContext, useDownstream, useRepresentation } from './contexts';
import {
DatasetContext,
useDownstreamContext,
useRepresentationContext,
} from './contexts';

export interface ImageDataProps extends PropsWithChildren {
/**
Expand Down Expand Up @@ -63,8 +67,8 @@ export default forwardRef(function PolyData(props: ImageDataProps, fwdRef) {
return im;
});

const representation = useRepresentation();
const downstream = useDownstream();
const representation = useRepresentationContext();
const downstream = useDownstreamContext();

// dataset API
const dataset = useMemo<IDataset<vtkImageData>>(
Expand Down
4 changes: 2 additions & 2 deletions src/core/PointData.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { PropsWithChildren, useCallback } from 'react';
import { FieldDataContext, useDataset } from './contexts';
import { FieldDataContext, useDatasetContext } from './contexts';

export default function PointData(props: PropsWithChildren) {
const dataset = useDataset();
const dataset = useDatasetContext();
const getPointData = useCallback(() => {
return dataset.getDataSet().getPointData();
}, [dataset]);
Expand Down
10 changes: 7 additions & 3 deletions src/core/PolyData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ import deletionRegistry from '../utils/DeletionRegistry';
import useGetterRef from '../utils/useGetterRef';
import { usePrevious } from '../utils/usePrevious';
import useUnmount from '../utils/useUnmount';
import { DatasetContext, useDownstream, useRepresentation } from './contexts';
import {
DatasetContext,
useDownstreamContext,
useRepresentationContext,
} from './contexts';

export interface PolyDataProps extends PropsWithChildren {
/**
Expand Down Expand Up @@ -103,8 +107,8 @@ export default forwardRef(function PolyData(props: PolyDataProps, fwdRef) {
return pd;
});

const representation = useRepresentation();
const downstream = useDownstream();
const representation = useRepresentationContext();
const downstream = useDownstreamContext();

// dataset API
const dataset = useMemo<IDataset<vtkPolyData>>(
Expand Down
6 changes: 3 additions & 3 deletions src/core/Reader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import vtk from '@kitware/vtk.js/vtk';
import { PropsWithChildren, useCallback, useEffect, useRef } from 'react';
import { VtkConstructor } from '../types';
import deletionRegistry from '../utils/DeletionRegistry';
import { useDownstream, useRepresentation } from './contexts';
import { useDownstreamContext, useRepresentationContext } from './contexts';

export interface ReaderProps extends PropsWithChildren {
/**
Expand Down Expand Up @@ -71,7 +71,7 @@ export default function Reader(props: ReaderProps) {
);
}

const representation = useRepresentation();
const representation = useRepresentationContext();

const createReader = useCallback(() => {
if (typeof vtkClass === 'string') {
Expand Down Expand Up @@ -138,7 +138,7 @@ export default function Reader(props: ReaderProps) {

// --- downstream registration --- //

const downstream = useDownstream();
const downstream = useDownstreamContext();
const { port } = props;

useEffect(() => {
Expand Down
14 changes: 7 additions & 7 deletions src/core/ShareDataSet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ import {
DownstreamContext,
RepresentationContext,
ShareDataSetContext,
useDownstream,
useRepresentation,
useShareDataSet,
useDownstreamContext,
useRepresentationContext,
useShareDataSetContext,
} from './contexts';
import useDataEvents from './modules/useDataEvents';

Expand Down Expand Up @@ -138,7 +138,7 @@ export interface RegisterDataSetProps extends PropsWithChildren {
}

export function RegisterDataSet(props: RegisterDataSetProps) {
const share = useShareDataSet();
const share = useShareDataSetContext();
const { id } = props;

// --- handle registrations --- //
Expand Down Expand Up @@ -206,10 +206,10 @@ export interface UseDataSetProps extends PropsWithChildren {

export function UseDataSet(props: UseDataSetProps) {
const { id, port = 0 } = props;
const share = useShareDataSet();
const share = useShareDataSetContext();
// TODO if useDataSet is input to an algorithm, should representation be null?
const representation = useRepresentation();
const downstream = useDownstream();
const representation = useRepresentationContext();
const downstream = useDownstreamContext();

useEffect(() => {
return share.onDataAvailable(id, (ds) => {
Expand Down
1 change: 1 addition & 0 deletions src/core/View.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default forwardRef(function View(props: ViewProps, fwdRef) {
multiViewRoot ? parentedViewRef.current : singleViewRef.current;
return {
isInMultiViewRoot: () => multiViewRoot,
isMounted: () => getView()?.isMounted() ?? false,
getViewContainer: () => getView()?.getViewContainer() ?? null,
getOpenGLRenderWindow: () => getView()?.getOpenGLRenderWindow() ?? null,
getRenderWindow: () => getView()?.getRenderWindow() ?? null,
Expand Down
4 changes: 2 additions & 2 deletions src/core/VolumeController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Contexts } from '..';
import deletionRegistry from '../utils/DeletionRegistry';
import useGetterRef from '../utils/useGetterRef';
import useUnmount from '../utils/useUnmount';
import { useRepresentation } from './contexts';
import { useRepresentationContext } from './contexts';

export interface VolumeControllerProps {
/**
Expand Down Expand Up @@ -35,7 +35,7 @@ export default function VolumeController(props: VolumeControllerProps) {
const view = useContext(Contexts.ViewContext);
if (!view) throw new Error('Need view context');

const volumeRep = useRepresentation();
const volumeRep = useRepresentationContext();

const updateWidget = useCallback(() => {
const volume = volumeRep.getMapper()?.getInputData() as
Expand Down
16 changes: 11 additions & 5 deletions src/core/contexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ export const MultiViewRootContext = createContext<boolean>(false);

export const ViewContext = createContext<IView | null>(null);

export function useViewContext() {
const view = useContext(ViewContext);
if (!view) throw new Error('No View context!');
return view;
}

export function useRenderWindowContext() {
const rw = useContext(RenderWindowContext);
if (!rw) throw new Error('No RenderWindow context!');
Expand All @@ -49,31 +55,31 @@ export function useRendererContext() {
return r;
}

export function useFieldData<T = vtkFieldData>() {
export function useFieldDataContext<T = vtkFieldData>() {
const fd = useContext(FieldDataContext);
if (!fd) throw new Error('No FieldData context!');
return fd as () => T;
}

export function useDataset<T = vtkDataSet>() {
export function useDatasetContext<T = vtkDataSet>() {
const ds = useContext(DatasetContext);
if (!ds) throw new Error('No Dataset context!');
return ds as IDataset<T>;
}

export function useRepresentation() {
export function useRepresentationContext() {
const rep = useContext(RepresentationContext);
if (!rep) throw new Error('No Representation context!');
return rep;
}

export function useDownstream() {
export function useDownstreamContext() {
const ds = useContext(DownstreamContext);
if (!ds) throw new Error('No Downstream context!');
return ds;
}

export function useShareDataSet() {
export function useShareDataSetContext() {
const share = useContext(ShareDataSetContext);
if (!share) throw new Error('No ShareDataSet context!');
return share;
Expand Down
9 changes: 9 additions & 0 deletions src/core/internal/ParentedView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
} from '../modules/useInteractorStyle';
import useViewEvents, { ViewEvents } from '../modules/useViewEvents';
import Renderer from '../Renderer';
import { viewMountedEvent } from './events';
import { DefaultProps, ViewProps } from './view-shared';

/**
Expand Down Expand Up @@ -172,9 +173,16 @@ const ParentedView = forwardRef(function ParentedView(

// --- api --- //

let mounted = false;
useMount(() => {
mounted = true;
viewMountedEvent.trigger();
});

const api = useMemo<IView>(
() => ({
isInMultiViewRoot: () => true,
isMounted: () => mounted,
getViewContainer: () => containerRef.current,
getOpenGLRenderWindow: () => openGLRenderWindowAPI,
getRenderWindow: () => renderWindowAPI,
Expand All @@ -187,6 +195,7 @@ const ParentedView = forwardRef(function ParentedView(
rendererRef.current?.resetCamera(boundsToUse),
}),
[
mounted,
openGLRenderWindowAPI,
renderWindowAPI,
getInteractorStyle,
Expand Down
10 changes: 9 additions & 1 deletion src/core/internal/SingleView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import useViewEvents, { ViewEvents } from '../modules/useViewEvents';
import OpenGLRenderWindow from '../OpenGLRenderWindow';
import Renderer from '../Renderer';
import RenderWindow from '../RenderWindow';
import { viewMountedEvent } from './events';
import { DefaultProps, ViewProps } from './view-shared';

/**
Expand Down Expand Up @@ -84,9 +85,16 @@ const SingleView = forwardRef(function SingleView(props: ViewProps, fwdRef) {

// --- api --- //

let mounted = false;
useMount(() => {
mounted = true;
viewMountedEvent.trigger();
});

const api = useMemo<IView>(
() => ({
isInMultiViewRoot: () => false,
isMounted: () => mounted,
getViewContainer: () =>
openGLRenderWindowRef.current?.getContainer() ?? null,
getOpenGLRenderWindow: () => openGLRenderWindowRef.current,
Expand All @@ -99,7 +107,7 @@ const SingleView = forwardRef(function SingleView(props: ViewProps, fwdRef) {
resetCamera: (boundsToUse?: Bounds) =>
rendererRef.current?.resetCamera(boundsToUse),
}),
[getInteractorStyle, setInteractorStyle]
[mounted, getInteractorStyle, setInteractorStyle]
);

useImperativeHandle(fwdRef, () => api);
Expand Down
33 changes: 33 additions & 0 deletions src/core/internal/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export type EventListener = (...args: any[]) => void;

function createEvent() {
const callbacks: EventListener[] = [];

const off = (callback: EventListener) => {
const idx = callbacks.indexOf(callback);
if (idx === -1) return;
callbacks.splice(idx, 1);
};

const on = (callback: EventListener) => {
callbacks.push(callback);
return () => off(callback);
};

const once = (callback: EventListener) => {
const stop = on(() => {
stop();
callback();
});
};

const trigger = (...args: any[]) => {
callbacks.forEach((cb) => {
cb(...args);
});
};

return { off, on, once, trigger };
}

export const viewMountedEvent = createEvent();
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import '@kitware/vtk.js/Rendering/OpenGL/Profiles/Volume';
export { default as Algorithm } from './core/Algorithm';
export type { AlgorithmProps } from './core/Algorithm';
export { default as CellData } from './core/CellData';
export * from './core/contexts';
export * as Contexts from './core/contexts';
export { default as DataArray } from './core/DataArray';
export type { DataArrayProps } from './core/DataArray';
Expand Down Expand Up @@ -46,3 +47,4 @@ export { default as View } from './core/View';
export type { ViewProps } from './core/View';
export { default as VolumeController } from './core/VolumeController';
export { default as VolumeRepresentation } from './core/VolumeRepresentation';
export * from './suspense';
1 change: 1 addition & 0 deletions src/suspense/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useViewReadySuspense';
Loading

0 comments on commit c4e287e

Please sign in to comment.