diff --git a/Sources/Testing/testAlgorithm.js b/Sources/Testing/testAlgorithm.js index ef83701bf58..144b347a6c8 100644 --- a/Sources/Testing/testAlgorithm.js +++ b/Sources/Testing/testAlgorithm.js @@ -63,3 +63,50 @@ test('Macro methods algo tests', (t) => { t.end(); }); + +test('Macro shouldUpdate returns true if output is deleted', (t) => { + const algo = { + publicAPI: {}, + model: {}, + }; + const input1 = { + publicAPI: {}, + model: {}, + }; + + const input2 = { + publicAPI: {}, + model: {}, + }; + + macro.obj(algo.publicAPI, algo.model); + macro.algo(algo.publicAPI, algo.model, 1, 1); + + macro.obj(input1.publicAPI, input1.model); + macro.obj(input2.publicAPI, input2.model); + + // trivial producer + algo.publicAPI.requestData = (inData, outData) => { + outData[0] = inData[0]; + }; + + algo.publicAPI.setInputData(input1.publicAPI, 0); + t.equal( + input1.publicAPI, + algo.publicAPI.getOutputData(), + 'Trivial producer outputs first input data' + ); + + // delete output data + algo.publicAPI.getOutputData().delete(); + + // set new data + algo.publicAPI.setInputData(input2.publicAPI, 0); + t.equal( + input2.publicAPI, + algo.publicAPI.getOutputData(), + 'Trivial producer outputs second input data' + ); + + t.end(); +}); diff --git a/Sources/Testing/testMacro.js b/Sources/Testing/testMacro.js index 753650b54d3..60d638c210c 100644 --- a/Sources/Testing/testMacro.js +++ b/Sources/Testing/testMacro.js @@ -428,3 +428,16 @@ test('Macro methods keystore tests', (t) => { t.end(); }); + +test('Macro debounce can be cancelled', (t) => { + const func = () => { + t.fail('Should not call cancelled debounce function'); + }; + + const debFunc = macro.debounce(func, 5); + debFunc(); + debFunc.cancel(); + + // end the test after the debounce phase + setTimeout(() => t.end(), 10); +}); diff --git a/Sources/interfaces.d.ts b/Sources/interfaces.d.ts index fed2fb1870b..30260bea9d0 100644 --- a/Sources/interfaces.d.ts +++ b/Sources/interfaces.d.ts @@ -16,6 +16,14 @@ export interface vtkRange { max: number; } +/** + * Represents a debounced function. + */ +export interface vtkDebouncedFunction { + (...args: any) : any; + cancel() : void; +} + export interface vtkOutputPort { filter: vtkAlgorithm; } diff --git a/Sources/macro.d.ts b/Sources/macro.d.ts index bc19ec36e8d..29688dad86e 100644 --- a/Sources/macro.d.ts +++ b/Sources/macro.d.ts @@ -1,4 +1,4 @@ -import { vtkSubscription, vtkProperty, vtkPropertyDomain } from "./interfaces"; +import { vtkSubscription, vtkDebouncedFunction, vtkProperty, vtkPropertyDomain } from "./interfaces"; /** * Allow user to redefine vtkXXXMacro method call. @@ -305,8 +305,10 @@ export function traverseInstanceTree( * @param func * @param wait * @param immediate (default false) + * @returns vtkDebouncedFunction A debounced function that can be called. + * Use .cancel() to clear any pending debounced call. */ -export function debounce(func: (...args: any) => any, wait: number, immediate?: boolean): (...args: any) => any; +export function debounce(func: (...args: any) => any, wait: number, immediate?: boolean): vtkDebouncedFunction; /** * Creates a throttled function that only invokes `func` at most once per diff --git a/Sources/macro.js b/Sources/macro.js index fd797061e74..17206ac5387 100644 --- a/Sources/macro.js +++ b/Sources/macro.js @@ -705,6 +705,11 @@ export function algo(publicAPI, model, numberOfInputs, numberOfOutputs) { if (!model.output[count]) { return true; } + + if (model.output[count].isDeleted()) { + return true; + } + const mt = model.output[count].getMTime(); if (mt < localMTime) { return true; @@ -985,7 +990,7 @@ export function traverseInstanceTree( export function debounce(func, wait, immediate) { let timeout; - return (...args) => { + const debounced = (...args) => { const context = this; const later = () => { timeout = null; @@ -1000,6 +1005,10 @@ export function debounce(func, wait, immediate) { func.apply(context, args); } }; + + debounced.cancel = () => clearTimeout(timeout); + + return debounced; } // ----------------------------------------------------------------------------