Skip to content

Commit

Permalink
fix(ts): Add typescript specific to widget behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
bruyeret authored and floryst committed Feb 6, 2024
1 parent c63e700 commit 50b08a9
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 20 deletions.
9 changes: 9 additions & 0 deletions Sources/Common/Core/DataArray/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ export interface vtkDataArray extends vtkObject {
*/
getData(): number[]|TypedArray;

/**
* Call this method when the underlying data has changed
* This method calls `modified()`
* For example, when you need to modify chunks of the array, it is faster
* to get the underlying array with `getData()`, modify it, and then call
* `dataChange()`.
*/
dataChange(): void;

/**
* Get the range of the given component.
*
Expand Down
30 changes: 26 additions & 4 deletions Sources/Widgets/Core/AbstractWidgetFactory/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ export interface IGetWidgetForViewParams {
initialValues?: object;
}

export interface vtkAbstractWidgetFactory extends vtkObject {
export interface vtkAbstractWidgetFactory<WidgetInstance extends vtkAbstractWidget> extends vtkObject {
/**
* Will return the widget associated with the view with Id id `locator.viewId`.
* If there is no widget associated with the view, a new widget will be constructed, provided
* that the renderer, viewType, and optionally initialValues are also provided.
*
* @param {IGetWidgetForViewParams} locator
*/
getWidgetForView(locator: IGetWidgetForViewParams): Nullable<vtkAbstractWidget>;
getWidgetForView(locator: IGetWidgetForViewParams): Nullable<WidgetInstance>;

/**
* Get a list of all the view ids.
Expand Down Expand Up @@ -107,21 +107,43 @@ export interface vtkAbstractWidgetFactory extends vtkObject {
invokeWidgetChangeEvent(...args: unknown[]): void;
}

/**
* This hack is to "remember" the generic type T that this function turn publicAPI into
* This is because typescript is completely "structural" and doesn't have any way to declare "nominal" types
* See: https://github.com/microsoft/TypeScript/issues/202
* For example, in this code, widgetInstance is a vtkResliceCursorWidgetCPRInstance:
*
* import vtkResliceCursorWidget from '@kitware/vtk.js/Widgets/Widgets3D/ResliceCursorWidget';
* import widgetBehavior from '@kitware/vtk.js/Widgets/Widgets3D/ResliceCursorWidget/cprBehavior';
*
* const widget = vtkResliceCursorWidget.newInstance({
* planes: ['Y', 'Z'],
* behavior: widgetBehavior,
* });
* const widgetInstance = widgetManager.addWidget(widget);
*/
declare const ExtendSymbol: unique symbol;
export type ExtendWidgetBehavior<WidgetInstance> = ((publicAPI: object, model: object) => void) & { [ExtendSymbol]: WidgetInstance };

export interface IAbstractWidgetFactoryInitialValues<WidgetInstance extends vtkAbstractWidget = vtkAbstractWidget> {
behavior?: ExtendWidgetBehavior<WidgetInstance>;
}

/**
* Method used to decorate a given object (publicAPI+model) with vtkAbstractWidgetFactory characteristics.
*
* @param publicAPI object on which methods will be bounds (public)
* @param model object on which data structure will be bounds (protected)
* @param initialValues (default: {})
*/
export function extend(publicAPI: object, model: object, initialValues? : object): void;
export function extend<WidgetInstance extends vtkAbstractWidget = vtkAbstractWidget>(publicAPI: object, model: object, initialValues?: IAbstractWidgetFactoryInitialValues<WidgetInstance>): void;

/**
* Method used to create a new instance of vtkAbstractWidgetFactory
*
* @param initialValues for pre-setting some of its content
*/
export function newInstance(initialValues?: object): vtkAbstractWidgetFactory;
export function newInstance<WidgetInstance extends vtkAbstractWidget = vtkAbstractWidget>(initialValues?: IAbstractWidgetFactoryInitialValues<WidgetInstance>): vtkAbstractWidgetFactory<WidgetInstance>;

export declare const vtkAbstractWidgetFactory: {
newInstance: typeof newInstance,
Expand Down
10 changes: 5 additions & 5 deletions Sources/Widgets/Core/WidgetManager/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,11 @@ export interface vtkWidgetManager extends vtkObject {
* @param {ViewTypes} [viewType]
* @param {Object} [initialValues]
*/
addWidget(
widget: vtkAbstractWidgetFactory,
addWidget<WidgetFactory extends vtkAbstractWidgetFactory<any>>(
widget: WidgetFactory,
viewType?: ViewTypes,
initialValues?: object
): Nullable<vtkAbstractWidget>;
): WidgetFactory extends vtkAbstractWidgetFactory<infer WidgetInstance> ? WidgetInstance : never;

/**
* Unregister all widgets from the widget manager.
Expand All @@ -145,7 +145,7 @@ export interface vtkWidgetManager extends vtkObject {
*
* @param {vtkAbstractWidget | vtkAbstractWidgetFactory} widget The widget to remove
*/
removeWidget(widget: vtkAbstractWidget | vtkAbstractWidgetFactory): void;
removeWidget(widget: vtkAbstractWidget | vtkAbstractWidgetFactory<any>): void;

/**
* Given x and y parameter, get selected data.
Expand All @@ -165,7 +165,7 @@ export interface vtkWidgetManager extends vtkObject {
*
* @param {vtkAbstractWidget | vtkAbstractWidgetFactory} widget The widget instance which should get the focus.
*/
grabFocus(widget: vtkAbstractWidget | vtkAbstractWidgetFactory): void;
grabFocus(widget: vtkAbstractWidget | vtkAbstractWidgetFactory<any>): void;

/**
* Release the focus.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import vtkAbstractWidgetFactory from "../../Core/AbstractWidgetFactory";
import { vtkAbstractWidgetFactory, IAbstractWidgetFactoryInitialValues } from "../../Core/AbstractWidgetFactory";
import vtkAbstractWidget from '../../Core/AbstractWidget'
import { Bounds } from "../../../types";
import { ViewTypes } from "../../Core/WidgetManager/Constants";

export interface vtkInteractiveOrientationWidget extends vtkAbstractWidgetFactory {
export interface vtkInteractiveOrientationWidget<WidgetInstance extends vtkAbstractWidget = vtkAbstractWidget> extends vtkAbstractWidgetFactory<WidgetInstance> {
/**
* Set the widget bounds
*
Expand All @@ -16,21 +17,23 @@ export interface vtkInteractiveOrientationWidget extends vtkAbstractWidgetFactor
getRepresentationForViewType(viewType: ViewTypes): unknown;
}

export interface IInteractiveOrientationWidgetInitialValues<WidgetInstance extends vtkAbstractWidget> extends IAbstractWidgetFactoryInitialValues<WidgetInstance> {}

/**
* Method use to decorate a given object (publicAPI+model) with vtkInteractiveOrientationWidget characteristics.
*
* @param publicAPI object on which methods will be bounds (public)
* @param model object on which data structure will be bounds (protected)
* @param {object} [initialValues] (default: {})
*/
export function extend(publicAPI: object, model: object, initialValues? : Record<string, unknown>): void;
export function extend<WidgetInstance extends vtkAbstractWidget>(publicAPI: object, model: object, initialValues? : IInteractiveOrientationWidgetInitialValues<WidgetInstance>): void;

/**
* Creates a new instance of vtkInteractiveOrientationWidget
*
* @param {object} [initialValues] for pre-setting some of its content
*/
export function newInstance(initialValues? : Record<string, unknown>): vtkInteractiveOrientationWidget;
export function newInstance<WidgetInstance extends vtkAbstractWidget = vtkAbstractWidget>(initialValues? : IInteractiveOrientationWidgetInitialValues<WidgetInstance>): vtkInteractiveOrientationWidget<WidgetInstance>;

export declare const vtkInteractiveOrientationWidget: {
newInstance: typeof newInstance,
Expand Down
5 changes: 5 additions & 0 deletions Sources/Widgets/Widgets3D/ResliceCursorWidget/behavior.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import vtkAbstractWidget from "../../Core/AbstractWidget";

export default interface vtkResliceCursorWidgetDefaultInstance extends vtkAbstractWidget {
invokeInternalInteractionEvent: () => void;
}
16 changes: 9 additions & 7 deletions Sources/Widgets/Widgets3D/ResliceCursorWidget/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { mat4 } from 'gl-matrix';
import vtkAbstractWidgetFactory from '../../Core/AbstractWidgetFactory';
import { vtkAbstractWidgetFactory, IAbstractWidgetFactoryInitialValues } from '../../Core/AbstractWidgetFactory';
import vtkResliceCursorWidgetDefaultInstance from './behavior';
import vtkAbstractWidget from '../../Core/AbstractWidget'
import vtkImageData from '../../../Common/DataModel/ImageData';
import vtkImageReslice from '../../../Imaging/Core/ImageReslice';
import vtkPlaneSource from '../../../Filters/Sources/PlaneSource';
Expand All @@ -16,7 +18,7 @@ export interface IDisplayScaleParams {
rendererPixelDims: Vector2
}

export interface vtkResliceCursorWidget extends vtkAbstractWidgetFactory {
export interface vtkResliceCursorWidget<WidgetInstance extends vtkAbstractWidget = vtkResliceCursorWidgetDefaultInstance> extends vtkAbstractWidgetFactory<WidgetInstance> {

/**
* @param {ViewTypes} viewType
Expand Down Expand Up @@ -81,7 +83,7 @@ export interface vtkResliceCursorWidget extends vtkAbstractWidgetFactory {

}

export interface IResliceCursorWidgetInitialValues {}
export interface IResliceCursorWidgetInitialValues<WidgetInstance extends vtkAbstractWidget> extends IAbstractWidgetFactoryInitialValues<WidgetInstance> {}

/**
* Method used to decorate a given object (publicAPI+model) with vtkResliceCursorWidget characteristics.
Expand All @@ -90,18 +92,18 @@ export interface IResliceCursorWidgetInitialValues {}
* @param model object on which data structure will be bounds (protected)
* @param initialValues (default: {})
*/
export function extend(
export function extend<WidgetInstance extends vtkAbstractWidget>(
publicAPI: object,
model: object,
initialValues?: IResliceCursorWidgetInitialValues
): vtkResliceCursorWidget;
initialValues?: IResliceCursorWidgetInitialValues<WidgetInstance>
): void;

/**
* Method used to create a new instance of vtkResliceCursorWidget
*
* @param initialValues for pre-setting some of its content
*/
export function newInstance(initialValues?: IResliceCursorWidgetInitialValues): vtkResliceCursorWidget;
export function newInstance<WidgetInstance extends vtkAbstractWidget = vtkResliceCursorWidgetDefaultInstance>(initialValues?: IResliceCursorWidgetInitialValues<WidgetInstance>): vtkResliceCursorWidget<WidgetInstance>;

export declare const vtkResliceCursorWidget: {
newInstance: typeof newInstance;
Expand Down

0 comments on commit 50b08a9

Please sign in to comment.