diff --git a/src/widget.ts b/src/widget.ts index a53bb82..9bc7732 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -377,6 +377,34 @@ export class CanvasManagerModel extends WidgetModel { static model_module_version = MODULE_VERSION; } +export class AsyncValueWidgetModel extends WidgetModel { + initialize(attributes: any, options: any) { + super.initialize(attributes, options); + + this._initPromise = new Promise(resolve => { + this._resolve = resolve; + }); + } + + async initialized(): Promise { + return this._initPromise; + } + + set value(v: ValueType) { + this._underlyingValue = v; + this._resolve(v); + } + + get value(): ValueType | undefined { + return this._underlyingValue; + } + + protected _underlyingValue: ValueType | undefined = undefined; + + private _initPromise: Promise; + private _resolve: (value: ValueType) => void; +} + export class Path2DModel extends WidgetModel { defaults() { return { @@ -401,7 +429,7 @@ export class Path2DModel extends WidgetModel { static model_module_version = MODULE_VERSION; } -export class PatternModel extends WidgetModel { +export class PatternModel extends AsyncValueWidgetModel { defaults() { return { ...super.defaults(), @@ -430,7 +458,7 @@ export class PatternModel extends WidgetModel { } if (patternSource == undefined) { - throw 'Could not understand the souce for the pattern'; + throw 'Could not understand the source for the pattern'; } const pattern = PatternModel.ctx.createPattern( @@ -450,8 +478,6 @@ export class PatternModel extends WidgetModel { image: { deserialize: unpack_models as any } }; - value: CanvasPattern; - static model_name = 'PatternModel'; static model_module = MODULE_NAME; static model_module_version = MODULE_VERSION; @@ -462,7 +488,7 @@ export class PatternModel extends WidgetModel { ); } -class GradientModel extends WidgetModel { +class GradientModel extends AsyncValueWidgetModel { defaults() { return { ...super.defaults(), @@ -481,8 +507,10 @@ class GradientModel extends WidgetModel { this.createGradient(); - for (const colorStop of this.get('color_stops')) { - this.value.addColorStop(colorStop[0], colorStop[1]); + if (this.value) { + for (const colorStop of this.get('color_stops')) { + this.value.addColorStop(colorStop[0], colorStop[1]); + } } } @@ -495,8 +523,6 @@ class GradientModel extends WidgetModel { ); } - value: CanvasGradient; - static model_module = MODULE_NAME; static model_module_version = MODULE_VERSION; @@ -1077,11 +1103,11 @@ export class CanvasModel extends DOMWidgetModel { async setAttr(attr: number, value: any) { if (typeof value === 'string' && value.startsWith('IPY')) { - const widgetModel: GradientModel = await unpack_models( + const widgetModel: AsyncValueWidgetModel = await unpack_models( value, this.widget_manager ); - value = widgetModel.value; + value = await widgetModel.initialized(); } (this.ctx as any)[CanvasModel.ATTRS[attr]] = value; diff --git a/ui-tests/playwright.config.js b/ui-tests/playwright.config.js index f6e8d6d..6bbb5d6 100644 --- a/ui-tests/playwright.config.js +++ b/ui-tests/playwright.config.js @@ -8,7 +8,7 @@ module.exports = { webServer: { command: 'jlpm start', url: 'http://localhost:8888/lab', - timeout: 600000, + timeout: 1200000, reuseExistingServer: !process.env.CI }, retries: 1 diff --git a/ui-tests/tests/ipycanvas.test.ts b/ui-tests/tests/ipycanvas.test.ts index 25badf3..1154056 100644 --- a/ui-tests/tests/ipycanvas.test.ts +++ b/ui-tests/tests/ipycanvas.test.ts @@ -5,6 +5,10 @@ import { expect, IJupyterLabPageFixture, test } from '@jupyterlab/galata'; import * as path from 'path'; const klaw = require('klaw-sync'); +function delay(ms: number) { + return new Promise( resolve => setTimeout(resolve, ms) ); +} + const filterUpdateNotebooks = item => { const basename = path.basename(item.path); @@ -29,6 +33,7 @@ const testCellOutputs = async (page: IJupyterLabPageFixture, tmpPath: string) => await page.notebook.runCellByCell({ onAfterCellRun: async (cellIndex: number) => { + await delay(150); const cell = await page.notebook.getCellOutput(cellIndex); if (cell) { results.push(await cell.screenshot()); diff --git a/ui-tests/tests/ipycanvas.test.ts-snapshots/ipycanvas-ipynb-cell-36-linux.png b/ui-tests/tests/ipycanvas.test.ts-snapshots/ipycanvas-ipynb-cell-36-linux.png new file mode 100644 index 0000000..33ab77e Binary files /dev/null and b/ui-tests/tests/ipycanvas.test.ts-snapshots/ipycanvas-ipynb-cell-36-linux.png differ diff --git a/ui-tests/tests/notebooks/ipycanvas.ipynb b/ui-tests/tests/notebooks/ipycanvas.ipynb index b4bec4f..c4e955e 100644 --- a/ui-tests/tests/notebooks/ipycanvas.ipynb +++ b/ui-tests/tests/notebooks/ipycanvas.ipynb @@ -975,6 +975,20 @@ "\n", "canvas" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a5f0a7f5", + "metadata": {}, + "outputs": [], + "source": [ + "canvas = Canvas()\n", + "pattern = canvas.create_pattern(Image.from_url(\"https://jupyter.org/assets/homepage/main-logo.svg\"))\n", + "canvas.fill_style = pattern\n", + "canvas.fill_rect(0, 0, canvas.width, canvas.height)\n", + "canvas" + ] } ], "metadata": {