From 1d0255a6a38e0292548b30febc0ff49aa431e7e1 Mon Sep 17 00:00:00 2001 From: Adam Sherwood Date: Tue, 23 Jan 2024 22:43:15 +0000 Subject: [PATCH] adds subscriptions to variables --- dist/constraint.d.ts | 4 ++-- dist/constraint.d.ts.map | 2 +- dist/variable.d.ts | 12 ++++++++++++ dist/variable.d.ts.map | 2 +- dist/variable.js | 20 ++++++++++++++++++++ docs/Kiwi.md | 24 ++++++++++++++++++++++++ src/variable.ts | 22 ++++++++++++++++++++++ test/main.js | 27 +++++++++++++++++++++++++++ 8 files changed, 109 insertions(+), 4 deletions(-) diff --git a/dist/constraint.d.ts b/dist/constraint.d.ts index c1d5bd8..9658dee 100644 --- a/dist/constraint.d.ts +++ b/dist/constraint.d.ts @@ -12,8 +12,8 @@ import { Variable } from './variable.js'; * @enum {Number} */ export declare enum Operator { - Le = 0, - Ge = 1, + Le = 0,// <= + Ge = 1,// >= Eq = 2 } /** diff --git a/dist/constraint.d.ts.map b/dist/constraint.d.ts.map index 7b000d9..cc27994 100644 --- a/dist/constraint.d.ts.map +++ b/dist/constraint.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"constraint.d.ts","sourceRoot":"","sources":["../src/constraint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAA;AAE1C,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AAEtC;;;;;;;;;;GAUG;AACH,oBAAY,QAAQ;IACnB,EAAE,IAAA;IACF,EAAE,IAAA;IACF,EAAE,IAAA;CACF;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,UAAU;gBAErB,UAAU,EAAE,UAAU,GAAG,QAAQ,EACjC,QAAQ,EAAE,QAAQ,EAClB,GAAG,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,EACpC,QAAQ,GAAE,MAA0B;IAWrC;;;OAGG;IACI,EAAE,IAAI,MAAM;IAInB;;;;OAIG;IACI,UAAU,IAAI,UAAU;IAI/B;;;;OAIG;IACI,EAAE,IAAI,QAAQ;IAIrB;;;;OAIG;IACI,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;IAMzB,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,GAAG,CAAiB;CAC5B"} \ No newline at end of file +{"version":3,"file":"constraint.d.ts","sourceRoot":"","sources":["../src/constraint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAA;AAE1C,OAAO,EAAC,QAAQ,EAAC,MAAM,eAAe,CAAA;AAEtC;;;;;;;;;;GAUG;AACH,oBAAY,QAAQ;IACnB,EAAE,IAAA,CAAE,KAAK;IACT,EAAE,IAAA,CAAE,KAAK;IACT,EAAE,IAAA;CACF;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,UAAU;gBAErB,UAAU,EAAE,UAAU,GAAG,QAAQ,EACjC,QAAQ,EAAE,QAAQ,EAClB,GAAG,CAAC,EAAE,UAAU,GAAG,QAAQ,GAAG,MAAM,EACpC,QAAQ,GAAE,MAA0B;IAWrC;;;OAGG;IACI,EAAE,IAAI,MAAM;IAInB;;;;OAIG;IACI,UAAU,IAAI,UAAU;IAI/B;;;;OAIG;IACI,EAAE,IAAI,QAAQ;IAIrB;;;;OAIG;IACI,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;IAMzB,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,GAAG,CAAiB;CAC5B"} \ No newline at end of file diff --git a/dist/variable.d.ts b/dist/variable.d.ts index 9b5da8a..2a52df5 100644 --- a/dist/variable.d.ts +++ b/dist/variable.d.ts @@ -45,6 +45,17 @@ export declare class Variable { * @private */ setValue(value: number): void; + /** + * Set a callback for whenever the value changes. + * + * @param {function(number,number):void} callback to call whenever the variable value changes + */ + subscribe(callback: (value: number, previousValue: number) => void): void; + /** + * Stops the variable from calling the callback when the variable value + * changes. + */ + unsubscribe(): void; /** * Creates a new Expression by adding a number, variable or expression * to the variable. @@ -85,5 +96,6 @@ export declare class Variable { private _value; private _context; private _id; + private _callback; } //# sourceMappingURL=variable.d.ts.map \ No newline at end of file diff --git a/dist/variable.d.ts.map b/dist/variable.d.ts.map index 647ee11..d85666d 100644 --- a/dist/variable.d.ts.map +++ b/dist/variable.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"variable.d.ts","sourceRoot":"","sources":["../src/variable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAA;AAE1C;;;;;GAKG;AACH,qBAAa,QAAQ;gBACR,IAAI,GAAE,MAAW;IAI7B;;;OAGG;IACI,EAAE,IAAI,MAAM;IAInB;;;;OAIG;IACI,IAAI,IAAI,MAAM;IAIrB;;;;OAIG;IACI,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIlC;;;OAGG;IACI,OAAO,IAAI,GAAG;IAIrB;;;OAGG;IACI,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAIrC;;;;OAIG;IACI,KAAK,IAAI,MAAM;IAItB;;;OAGG;IACI,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIpC;;;;;;OAMG;IACI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU;IAI9D;;;;;;OAMG;IACI,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU;IAI/D;;;;;OAKG;IACI,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU;IAIhD;;;;;OAKG;IACI,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU;IAI9C;;;OAGG;IACI,MAAM,IAAI,GAAG;IAOb,QAAQ,IAAI,MAAM;IAIzB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,GAAG,CAAkB;CAC7B"} \ No newline at end of file +{"version":3,"file":"variable.d.ts","sourceRoot":"","sources":["../src/variable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,iBAAiB,CAAA;AAE1C;;;;;GAKG;AACH,qBAAa,QAAQ;gBACR,IAAI,GAAE,MAAW;IAI7B;;;OAGG;IACI,EAAE,IAAI,MAAM;IAInB;;;;OAIG;IACI,IAAI,IAAI,MAAM;IAIrB;;;;OAIG;IACI,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIlC;;;OAGG;IACI,OAAO,IAAI,GAAG;IAIrB;;;OAGG;IACI,UAAU,CAAC,OAAO,EAAE,GAAG,GAAG,IAAI;IAIrC;;;;OAIG;IACI,KAAK,IAAI,MAAM;IAItB;;;OAGG;IACI,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQpC;;;;OAIG;IACI,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI;IAIhF;;;OAGG;IACI,WAAW,IAAI,IAAI;IAI1B;;;;;;OAMG;IACI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU;IAI9D;;;;;;OAMG;IACI,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,GAAG,UAAU;IAI/D;;;;;OAKG;IACI,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU;IAIhD;;;;;OAKG;IACI,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU;IAI9C;;;OAGG;IACI,MAAM,IAAI,GAAG;IAOb,QAAQ,IAAI,MAAM;IAIzB,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,GAAG,CAAkB;IAC7B,OAAO,CAAC,SAAS,CAAgD;CACjE"} \ No newline at end of file diff --git a/dist/variable.js b/dist/variable.js index 0406b80..bb0e649 100644 --- a/dist/variable.js +++ b/dist/variable.js @@ -59,7 +59,26 @@ export class Variable { * @private */ setValue(value) { + var previousValue = this._value; this._value = value; + if (this._callback && previousValue !== value) { + this._callback(value, previousValue); + } + } + /** + * Set a callback for whenever the value changes. + * + * @param {function(number,number):void} callback to call whenever the variable value changes + */ + subscribe(callback) { + this._callback = callback; + } + /** + * Stops the variable from calling the callback when the variable value + * changes. + */ + unsubscribe() { + this._callback = null; } /** * Creates a new Expression by adding a number, variable or expression @@ -116,6 +135,7 @@ export class Variable { _value = 0.0; _context = null; _id = VarId++; + _callback; } /** * The internal variable id counter. diff --git a/docs/Kiwi.md b/docs/Kiwi.md index 5add837..3e058b3 100644 --- a/docs/Kiwi.md +++ b/docs/Kiwi.md @@ -48,6 +48,8 @@ console.assert(centerX.value() === 250) - [.name()](#module_@lume/kiwi..Variable+name) ⇒ String - [.setName(name)](#module_@lume/kiwi..Variable+setName) - [.value()](#module_@lume/kiwi..Variable+value) ⇒ Number + - [.subscribe(callback)](#module_@lume/kiwi..Variable+subscribe) + - [.unsubscribe()](#module_@lume/kiwi..Variable+unsubscribe) - [.plus(value)](#module_@lume/kiwi..Variable+plus) ⇒ Expression - [.minus(value)](#module_@lume/kiwi..Variable+minus) ⇒ Expression - [.multiply(coefficient)](#module_@lume/kiwi..Variable+multiply) ⇒ Expression @@ -98,6 +100,8 @@ The primary user constraint variable. - [.name()](#module_@lume/kiwi..Variable+name) ⇒ String - [.setName(name)](#module_@lume/kiwi..Variable+setName) - [.value()](#module_@lume/kiwi..Variable+value) ⇒ Number + - [.subscribe(callback)](#module_@lume/kiwi..Variable+subscribe) + - [.unsubscribe()](#module_@lume/kiwi..Variable+unsubscribe) - [.plus(value)](#module_@lume/kiwi..Variable+plus) ⇒ Expression - [.minus(value)](#module_@lume/kiwi..Variable+minus) ⇒ Expression - [.multiply(coefficient)](#module_@lume/kiwi..Variable+multiply) ⇒ Expression @@ -139,6 +143,26 @@ Returns the value of the variable. **Kind**: instance method of [Variable](#module_@lume/kiwi..Variable) **Returns**: Number - Calculated value + + +### variable.subscribe(callback) + +Set a callback for whenever the value changes. + +**Kind**: instance method of [Variable](#module_@lume/kiwi..Variable) + +| Param | Type | Description | +| -------- | --------------------- | ------------------------------------------- | +| callback | function | to call whenever the variable value changes | + + + +### variable.unsubscribe() + +Stops the variable from calling the callback when the variable value +changes. + +**Kind**: instance method of [Variable](#module_@lume/kiwi..Variable) ### variable.plus(value) ⇒ Expression diff --git a/src/variable.ts b/src/variable.ts index 5cec2d7..de7940f 100644 --- a/src/variable.ts +++ b/src/variable.ts @@ -67,7 +67,28 @@ export class Variable { * @private */ public setValue(value: number): void { + var previousValue = this._value this._value = value + if (this._callback && previousValue !== value) { + this._callback(value, previousValue) + } + } + + /** + * Set a callback for whenever the value changes. + * + * @param {function(number,number):void} callback to call whenever the variable value changes + */ + public subscribe(callback: (value: number, previousValue: number) => void): void { + this._callback = callback + } + + /** + * Stops the variable from calling the callback when the variable value + * changes. + */ + public unsubscribe(): void { + this._callback = null } /** @@ -131,6 +152,7 @@ export class Variable { private _value: number = 0.0 private _context: any = null private _id: number = VarId++ + private _callback: (value: number, previousValue: number) => void } /** diff --git a/test/main.js b/test/main.js index 47e428d..c8c7d6b 100644 --- a/test/main.js +++ b/test/main.js @@ -39,6 +39,33 @@ describe('import kiwi', function () { solver.updateVariables() assert.equal(200, variable.value()) }) + it('variable.subscribe(callback) => value: 400', function () { + var var2 = new kiwi.Variable() + var val, previousVal + var2.subscribe((value, previousValue) => ((val = value), (previousVal = previousValue))) + assert.equal(val, undefined) + assert.equal(previousVal, undefined) + solver.addEditVariable(var2, kiwi.Strength.strong) + solver.suggestValue(var2, 400) + solver.updateVariables() + assert.equal(val, 400) + assert.equal(previousVal, 0) + solver.suggestValue(var2, 500) + solver.updateVariables() + assert.equal(val, 500) + assert.equal(previousVal, 400) + }) + it('variable.unsubscribe()', function () { + var var2 = new kiwi.Variable() + var val, previousVal + var2.subscribe((value, previousValue) => ((val = value), (previousVal = previousValue))) + solver.addEditVariable(var2, kiwi.Strength.strong) + solver.suggestValue(var2, 300) + var2.unsubscribe() + solver.updateVariables() + assert.equal(val, undefined) + assert.equal(previousVal, undefined) + }) it('solver.removeEditVariable(variable) => solver.hasEditVariable(): false', function () { assert(solver.hasEditVariable(variable)) solver.removeEditVariable(variable)