Skip to content

Commit 9709c86

Browse files
committed
Make the Application fully composable
1 parent 60be174 commit 9709c86

File tree

2 files changed

+60
-18
lines changed

2 files changed

+60
-18
lines changed

packages/application/src/index.ts

+36-15
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,14 @@ export class Application<T extends Widget | HTMLElement = Widget> {
5151
this.pluginRegistry.application = this;
5252

5353
// Initialize the application state.
54-
this.commands = new CommandRegistry();
55-
this.contextMenu = new ContextMenu({
54+
this.commands = options.commands ?? new CommandRegistry();
55+
const contextMenuOptions = {
5656
commands: this.commands,
5757
renderer: options.contextMenuRenderer
58-
});
58+
};
59+
this.contextMenu = options.contextMenuFactory
60+
? options.contextMenuFactory(contextMenuOptions)
61+
: new ContextMenu(contextMenuOptions);
5962
this.shell = options.shell;
6063
this._hasShellWidget = this.shell instanceof Widget;
6164
}
@@ -197,7 +200,9 @@ export class Application<T extends Widget | HTMLElement = Widget> {
197200
* If the plugin provides a service which has already been provided
198201
* by another plugin, the new service will override the old service.
199202
*/
200-
registerPlugin(plugin: IPlugin<Application<Widget | HTMLElement>, any>): void {
203+
registerPlugin(
204+
plugin: IPlugin<Application<Widget | HTMLElement>, any>
205+
): void {
201206
this.pluginRegistry.registerPlugin(plugin);
202207
}
203208

@@ -209,7 +214,9 @@ export class Application<T extends Widget | HTMLElement = Widget> {
209214
* #### Notes
210215
* This calls `registerPlugin()` for each of the given plugins.
211216
*/
212-
registerPlugins(plugins: IPlugin<Application<Widget | HTMLElement>, any>[]): void {
217+
registerPlugins(
218+
plugins: IPlugin<Application<Widget | HTMLElement>, any>[]
219+
): void {
213220
this.pluginRegistry.registerPlugins(plugins);
214221
}
215222

@@ -340,14 +347,15 @@ export class Application<T extends Widget | HTMLElement = Widget> {
340347
* A subclass may reimplement this method as needed.
341348
*/
342349
protected attachShell(id: string): void {
343-
if (this._hasShellWidget){
344-
Widget.attach(
345-
this.shell as Widget,
346-
(id && document.getElementById(id)) || document.body
347-
);} else {
350+
if (this._hasShellWidget) {
351+
Widget.attach(
352+
this.shell as Widget,
353+
(id && document.getElementById(id)) || document.body
354+
);
355+
} else {
348356
const host = (id && document.getElementById(id)) || document.body;
349-
if(!host.contains(this.shell as HTMLElement)) {
350-
host.appendChild(this.shell as HTMLElement)
357+
if (!host.contains(this.shell as HTMLElement)) {
358+
host.appendChild(this.shell as HTMLElement);
351359
}
352360
}
353361
}
@@ -426,7 +434,9 @@ export class Application<T extends Widget | HTMLElement = Widget> {
426434
* A subclass may reimplement this method as needed.
427435
*/
428436
protected evtResize(event: Event): void {
429-
if(this._hasShellWidget){(this.shell as Widget).update()}
437+
if (this._hasShellWidget) {
438+
(this.shell as Widget).update();
439+
}
430440
}
431441

432442
/**
@@ -440,13 +450,14 @@ export class Application<T extends Widget | HTMLElement = Widget> {
440450
}
441451

442452
/**
443-
* The namespace for the `Application` class statics.
453+
* The namespace for the {@link Application} class statics.
444454
*/
445455
export namespace Application {
446456
/**
447457
* An options object for creating an application.
448458
*/
449-
export interface IOptions<T extends Widget | HTMLElement> extends PluginRegistry.IOptions {
459+
export interface IOptions<T extends Widget | HTMLElement>
460+
extends PluginRegistry.IOptions {
450461
/**
451462
* The shell element to use for the application.
452463
*
@@ -455,6 +466,16 @@ export namespace Application {
455466
*/
456467
shell: T;
457468

469+
/**
470+
* A custom commands registry.
471+
*/
472+
commands?: CommandRegistry;
473+
474+
/**
475+
* A custom context menu factory.
476+
*/
477+
contextMenuFactory?: (options: ContextMenu.IOptions) => ContextMenu;
478+
458479
/**
459480
* A custom renderer for the context menu.
460481
*/

packages/application/tests/src/index.spec.ts

+24-3
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,27 @@ describe('@lumino/application', () => {
6969
expect(app.contextMenu).to.be.instanceOf(ContextMenu);
7070
expect(app.shell).to.equal(shell);
7171
});
72+
73+
it('should instantiate an application with a custom command registry', () => {
74+
const commands = new (class extends CommandRegistry {})();
75+
76+
const app = new Application({ shell: new Widget(), commands });
77+
78+
expect(app.commands).to.be.equal(commands);
79+
});
80+
81+
it('should instantiate an application with a custom context menu factory', () => {
82+
const contextMenuFactory = (options: ContextMenu.IOptions) =>
83+
new (class extends ContextMenu {})(options);
84+
85+
const app = new Application({
86+
shell: new Widget(),
87+
contextMenuFactory
88+
});
89+
90+
expect(app.contextMenu).to.be.instanceOf(ContextMenu);
91+
expect(app.contextMenu.menu.commands).to.be.equal(app.commands);
92+
});
7293
});
7394

7495
describe('#getPluginDescription', () => {
@@ -647,7 +668,7 @@ describe('@lumino/application', () => {
647668
await app.start();
648669

649670
expect(document.body.contains(shell.node)).to.be.true;
650-
})
671+
});
651672

652673
it('should attach the shell HTML element to the document body', async () => {
653674
const shell = document.createElement('div');
@@ -658,7 +679,7 @@ describe('@lumino/application', () => {
658679
await app.start();
659680

660681
expect(document.body.contains(shell)).to.be.true;
661-
})
662-
})
682+
});
683+
});
663684
});
664685
});

0 commit comments

Comments
 (0)