Skip to content

Commit 3e326e2

Browse files
authored
Merge pull request #7 from DenisaCG/DocumentWidget&Toolbox
DocumentWidget & Toolbox
2 parents 070fdeb + 91c6d8b commit 3e326e2

File tree

10 files changed

+787
-315
lines changed

10 files changed

+787
-315
lines changed

binder/postBuild

100755100644
File mode changed.

package.json

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,20 @@
4747
"dependencies": {
4848
"@jupyterlab/application": "^4.0.0-alpha.4",
4949
"@jupyterlab/apputils": "^4.0.0-alpha.4",
50+
"@jupyterlab/docregistry": "^4.0.0-alpha.4",
51+
"@lumino/signaling": "^1.10.1",
5052
"@lumino/widgets": "^1.31.0",
5153
"blockly": "^7.20211209.2"
5254
},
5355
"devDependencies": {
5456
"@jupyterlab/builder": "^4.0.0-alpha.4",
55-
"@typescript-eslint/eslint-plugin": "^4.8.1",
56-
"@typescript-eslint/parser": "^4.8.1",
57-
"eslint": "^7.14.0",
58-
"eslint-config-prettier": "^6.15.0",
59-
"eslint-plugin-prettier": "^3.1.4",
57+
"@typescript-eslint/eslint-plugin": "^5.12.1",
58+
"@typescript-eslint/parser": "^5.12.1",
59+
"eslint": "^8.9.0",
60+
"eslint-config-prettier": "^8.4.0",
61+
"eslint-plugin-prettier": "^4.0.0",
6062
"npm-run-all": "^4.1.5",
61-
"prettier": "^2.1.1",
63+
"prettier": "^2.5.1",
6264
"rimraf": "^3.0.2",
6365
"typescript": "~4.5.2"
6466
},

src/factory.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {
2+
ABCWidgetFactory,
3+
DocumentRegistry,
4+
DocumentModel
5+
} from '@jupyterlab/docregistry';
6+
7+
import { BlocklyEditor, BlocklyPanel } from './widget';
8+
9+
/**
10+
* A widget factory to create new instances of ExampleDocWidget.
11+
*/
12+
export class BlocklyEditorFactory extends ABCWidgetFactory<
13+
BlocklyEditor,
14+
DocumentModel
15+
> {
16+
/**
17+
* Constructor of ExampleWidgetFactory.
18+
*
19+
* @param options Constructor options
20+
*/
21+
constructor(options: DocumentRegistry.IWidgetFactoryOptions) {
22+
super(options);
23+
}
24+
25+
/**
26+
* Create a new widget given a context.
27+
*
28+
* @param context Contains the information of the file
29+
* @returns The widget
30+
*/
31+
protected createNewWidget(
32+
context: DocumentRegistry.IContext<DocumentModel>
33+
): BlocklyEditor {
34+
return new BlocklyEditor({
35+
context,
36+
content: new BlocklyPanel(context)
37+
});
38+
}
39+
}

src/index.ts

Lines changed: 30 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,94 +4,61 @@ import {
44
ILayoutRestorer
55
} from '@jupyterlab/application';
66

7-
import {
8-
ICommandPalette,
9-
MainAreaWidget,
10-
WidgetTracker
11-
} from '@jupyterlab/apputils';
12-
13-
import { Widget } from '@lumino/widgets';
7+
import { WidgetTracker } from '@jupyterlab/apputils';
148

15-
import * as Blockly from 'blockly';
9+
import { BlocklyEditorFactory } from './factory';
1610

17-
namespace CommandIDs {
18-
export const open = 'jupyterlab-blocky:open-editor';
19-
}
11+
import { BlocklyEditor } from './widget';
2012

21-
const TOOLBOX = {
22-
kind: 'flyoutToolbox',
23-
contents: [
24-
{
25-
kind: 'block',
26-
type: 'controls_if'
27-
},
28-
{
29-
kind: 'block',
30-
type: 'controls_whileUntil'
31-
}
32-
]
33-
};
13+
/**
14+
* The name of the factory that creates the editor widgets.
15+
*/
16+
const FACTORY = 'Blockly editor';
3417

3518
/**
3619
* Initialization data for the jupyterlab-blocky extension.
3720
*/
3821
const plugin: JupyterFrontEndPlugin<void> = {
3922
id: 'jupyterlab-blocky:plugin',
4023
autoStart: true,
41-
requires: [ICommandPalette, ILayoutRestorer],
42-
activate: (
43-
app: JupyterFrontEnd,
44-
palette: ICommandPalette,
45-
restorer: ILayoutRestorer
46-
) => {
24+
requires: [ILayoutRestorer],
25+
activate: (app: JupyterFrontEnd, restorer: ILayoutRestorer) => {
4726
console.log('JupyterLab extension jupyterlab-blocky is activated!');
4827

49-
let editorPanel: MainAreaWidget | null = null;
50-
5128
// Namespace for the tracker
52-
const namespace = 'documents-example';
29+
const namespace = 'jupyterlab-blocky';
30+
5331
// Creating the tracker for the document
54-
const tracker = new WidgetTracker<MainAreaWidget>({ namespace });
32+
const tracker = new WidgetTracker<BlocklyEditor>({ namespace });
5533

5634
// Handle state restoration.
5735
if (restorer) {
5836
// When restoring the app, if the document was open, reopen it
5937
restorer.restore(tracker, {
60-
command: CommandIDs.open,
61-
name: widget => ''
38+
command: 'docmanager:open',
39+
args: widget => ({ path: widget.context.path, factory: FACTORY }),
40+
name: widget => widget.context.path
6241
});
6342
}
6443

65-
app.commands.addCommand(CommandIDs.open, {
66-
label: 'Open Blockly Editor',
67-
caption: 'Open Blockly Editor',
68-
isEnabled: () => true,
69-
execute: () => {
70-
const content = new Widget();
71-
content.id = 'jp-Blockly-container';
72-
editorPanel = new MainAreaWidget({ content });
73-
editorPanel.title.label = 'Blockly Editor';
74-
75-
editorPanel.disposed.connect(() => {
76-
editorPanel = null;
77-
workspace.dispose();
78-
});
79-
80-
app.shell.add(editorPanel, 'main');
81-
82-
const workspace = Blockly.inject(content.node, {
83-
toolbox: TOOLBOX
84-
});
85-
console.debug('Blockly:', workspace);
86-
}
44+
// Creating the widget factory to register it so the document manager knows about
45+
// our new DocumentWidget
46+
const widgetFactory = new BlocklyEditorFactory({
47+
name: FACTORY,
48+
modelName: 'text',
49+
fileTypes: ['json']
8750
});
8851

89-
if (palette) {
90-
palette.addItem({
91-
command: CommandIDs.open,
92-
category: 'Blockly Editor'
52+
// Add the widget to the tracker when it's created
53+
widgetFactory.widgetCreated.connect((sender, widget) => {
54+
// Notify the instance tracker if restore data needs to update.
55+
widget.context.pathChanged.connect(() => {
56+
tracker.save(widget);
9357
});
94-
}
58+
tracker.add(widget);
59+
});
60+
// Registering the widget factory
61+
app.docRegistry.addWidgetFactory(widgetFactory);
9562
}
9663
};
9764

src/layout.ts

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { Layout, Widget } from '@lumino/widgets';
2+
3+
import { PartialJSONValue } from '@lumino/coreutils';
4+
5+
import { IIterator, ArrayIterator } from '@lumino/algorithm';
6+
7+
import { Message } from '@lumino/messaging';
8+
9+
import * as Blockly from 'blockly';
10+
11+
import { TOOLBOX } from './utils';
12+
13+
/**
14+
* A blockly layout to host the Blockly editor.
15+
*/
16+
export class BlocklyLayout extends Layout {
17+
private _workspace: Blockly.WorkspaceSvg;
18+
private _host: HTMLElement;
19+
20+
/**
21+
* Construct a `BlocklyLayout`.
22+
*
23+
*/
24+
constructor() {
25+
super();
26+
console.debug('[BlocklyLayout]');
27+
28+
// Creating the container for the Blockly editor
29+
this._host = document.createElement('div');
30+
this._host.className = 'grid-stack';
31+
}
32+
33+
get workspace(): PartialJSONValue {
34+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
35+
// @ts-ignore
36+
return Blockly.serialization.workspaces.save(this._workspace);
37+
}
38+
39+
set workspace(workspace: PartialJSONValue) {
40+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
41+
// @ts-ignore
42+
Blockly.serialization.workspaces.load(workspace, this._workspace);
43+
}
44+
45+
/**
46+
* Dispose of the resources held by the widget.
47+
*/
48+
dispose(): void {
49+
this._workspace.dispose();
50+
super.dispose();
51+
}
52+
53+
/**
54+
* Init the blockly layout
55+
*/
56+
init(): void {
57+
super.init();
58+
console.debug('[BlocklyLayout] init');
59+
// Add the blockly container into the DOM
60+
this.parent!.node.appendChild(this._host);
61+
}
62+
63+
/**
64+
* Create an iterator over the widgets in the layout.
65+
*/
66+
iter(): IIterator<Widget> {
67+
return new ArrayIterator([]);
68+
}
69+
70+
/**
71+
* Remove a widget from the layout.
72+
*
73+
* @param widget - The `widget` to remove.
74+
*/
75+
removeWidget(widget: Widget): void {
76+
return;
77+
}
78+
79+
/**
80+
* Handle `update-request` messages sent to the widget.
81+
*/
82+
protected onUpdateRequest(msg: Message): void {
83+
console.debug('[BlocklyLayout] onUpdateRequest');
84+
// TODO: write the resize logic
85+
}
86+
87+
/**
88+
* Handle `resize-request` messages sent to the widget.
89+
*/
90+
protected onResize(msg: Message): void {
91+
console.debug('[BlocklyLayout] onResize');
92+
// TODO: write the resize logic
93+
const rect = this.parent.node.getBoundingClientRect();
94+
this._host.style.width = rect.width + 'px';
95+
this._host.style.height = rect.height + 'px';
96+
Blockly.svgResize(this._workspace);
97+
}
98+
99+
/**
100+
* Handle `fit-request` messages sent to the widget.
101+
*/
102+
protected onFitRequest(msg: Message): void {
103+
console.debug('[BlocklyLayout] onFitRequest');
104+
// TODO: write the resize logic
105+
//
106+
}
107+
108+
/**
109+
* Handle `after-attach` messages sent to the widget.
110+
*/
111+
protected onAfterAttach(msg: Message): void {
112+
console.debug('[BlocklyLayout] onAfterAttach');
113+
this._workspace = Blockly.inject(this._host, {
114+
toolbox: TOOLBOX
115+
});
116+
}
117+
118+
/**
119+
* Handle `after-show` messages sent to the widget.
120+
*/
121+
protected onAfterShow(msg: Message): void {
122+
console.debug('[BlocklyLayout] onAfterShow');
123+
}
124+
}

0 commit comments

Comments
 (0)