Skip to content

Commit c2ba661

Browse files
authored
Fix pattern from image in JupyterLab (#345)
* Fix pattern in JupyterLab * Increase test timeout * Update snapshot * Small sleep in ui tests
1 parent 1eeb4fd commit c2ba661

File tree

5 files changed

+57
-12
lines changed

5 files changed

+57
-12
lines changed

src/widget.ts

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,34 @@ export class CanvasManagerModel extends WidgetModel {
377377
static model_module_version = MODULE_VERSION;
378378
}
379379

380+
export class AsyncValueWidgetModel<ValueType> extends WidgetModel {
381+
initialize(attributes: any, options: any) {
382+
super.initialize(attributes, options);
383+
384+
this._initPromise = new Promise(resolve => {
385+
this._resolve = resolve;
386+
});
387+
}
388+
389+
async initialized(): Promise<ValueType> {
390+
return this._initPromise;
391+
}
392+
393+
set value(v: ValueType) {
394+
this._underlyingValue = v;
395+
this._resolve(v);
396+
}
397+
398+
get value(): ValueType | undefined {
399+
return this._underlyingValue;
400+
}
401+
402+
protected _underlyingValue: ValueType | undefined = undefined;
403+
404+
private _initPromise: Promise<ValueType>;
405+
private _resolve: (value: ValueType) => void;
406+
}
407+
380408
export class Path2DModel extends WidgetModel {
381409
defaults() {
382410
return {
@@ -401,7 +429,7 @@ export class Path2DModel extends WidgetModel {
401429
static model_module_version = MODULE_VERSION;
402430
}
403431

404-
export class PatternModel extends WidgetModel {
432+
export class PatternModel extends AsyncValueWidgetModel<CanvasPattern> {
405433
defaults() {
406434
return {
407435
...super.defaults(),
@@ -430,7 +458,7 @@ export class PatternModel extends WidgetModel {
430458
}
431459

432460
if (patternSource == undefined) {
433-
throw 'Could not understand the souce for the pattern';
461+
throw 'Could not understand the source for the pattern';
434462
}
435463

436464
const pattern = PatternModel.ctx.createPattern(
@@ -450,8 +478,6 @@ export class PatternModel extends WidgetModel {
450478
image: { deserialize: unpack_models as any }
451479
};
452480

453-
value: CanvasPattern;
454-
455481
static model_name = 'PatternModel';
456482
static model_module = MODULE_NAME;
457483
static model_module_version = MODULE_VERSION;
@@ -462,7 +488,7 @@ export class PatternModel extends WidgetModel {
462488
);
463489
}
464490

465-
class GradientModel extends WidgetModel {
491+
class GradientModel extends AsyncValueWidgetModel<CanvasGradient> {
466492
defaults() {
467493
return {
468494
...super.defaults(),
@@ -481,8 +507,10 @@ class GradientModel extends WidgetModel {
481507

482508
this.createGradient();
483509

484-
for (const colorStop of this.get('color_stops')) {
485-
this.value.addColorStop(colorStop[0], colorStop[1]);
510+
if (this.value) {
511+
for (const colorStop of this.get('color_stops')) {
512+
this.value.addColorStop(colorStop[0], colorStop[1]);
513+
}
486514
}
487515
}
488516

@@ -495,8 +523,6 @@ class GradientModel extends WidgetModel {
495523
);
496524
}
497525

498-
value: CanvasGradient;
499-
500526
static model_module = MODULE_NAME;
501527
static model_module_version = MODULE_VERSION;
502528

@@ -1077,11 +1103,11 @@ export class CanvasModel extends DOMWidgetModel {
10771103

10781104
async setAttr(attr: number, value: any) {
10791105
if (typeof value === 'string' && value.startsWith('IPY')) {
1080-
const widgetModel: GradientModel = await unpack_models(
1106+
const widgetModel: AsyncValueWidgetModel<any> = await unpack_models(
10811107
value,
10821108
this.widget_manager
10831109
);
1084-
value = widgetModel.value;
1110+
value = await widgetModel.initialized();
10851111
}
10861112

10871113
(this.ctx as any)[CanvasModel.ATTRS[attr]] = value;

ui-tests/playwright.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module.exports = {
88
webServer: {
99
command: 'jlpm start',
1010
url: 'http://localhost:8888/lab',
11-
timeout: 600000,
11+
timeout: 1200000,
1212
reuseExistingServer: !process.env.CI
1313
},
1414
retries: 1

ui-tests/tests/ipycanvas.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { expect, IJupyterLabPageFixture, test } from '@jupyterlab/galata';
55
import * as path from 'path';
66
const klaw = require('klaw-sync');
77

8+
function delay(ms: number) {
9+
return new Promise( resolve => setTimeout(resolve, ms) );
10+
}
11+
812

913
const filterUpdateNotebooks = item => {
1014
const basename = path.basename(item.path);
@@ -29,6 +33,7 @@ const testCellOutputs = async (page: IJupyterLabPageFixture, tmpPath: string) =>
2933

3034
await page.notebook.runCellByCell({
3135
onAfterCellRun: async (cellIndex: number) => {
36+
await delay(150);
3237
const cell = await page.notebook.getCellOutput(cellIndex);
3338
if (cell) {
3439
results.push(await cell.screenshot());
30.9 KB
Loading

ui-tests/tests/notebooks/ipycanvas.ipynb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,20 @@
975975
"\n",
976976
"canvas"
977977
]
978+
},
979+
{
980+
"cell_type": "code",
981+
"execution_count": null,
982+
"id": "a5f0a7f5",
983+
"metadata": {},
984+
"outputs": [],
985+
"source": [
986+
"canvas = Canvas()\n",
987+
"pattern = canvas.create_pattern(Image.from_url(\"https://jupyter.org/assets/homepage/main-logo.svg\"))\n",
988+
"canvas.fill_style = pattern\n",
989+
"canvas.fill_rect(0, 0, canvas.width, canvas.height)\n",
990+
"canvas"
991+
]
978992
}
979993
],
980994
"metadata": {

0 commit comments

Comments
 (0)