Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add documentation for widget manager & open handler #8644

Merged
merged 1 commit into from
Oct 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 42 additions & 9 deletions packages/core/src/browser/widget-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,28 @@ import { ILogger, Emitter, Event, ContributionProvider, MaybePromise, WaitUntilE

/* eslint-disable @typescript-eslint/no-explicit-any */
export const WidgetFactory = Symbol('WidgetFactory');

/**
* `OpenHandler` should be implemented to provide a new opener.
* A {@link WidgetFactory} is used to create new widgets. Factory-specific information (options) can be passed as serializable JSON data.
* The common {@link WidgetManager} collects `WidgetFactory` contributions and delegates to the corresponding factory when
* a widget should be created or restored. To identify widgets the `WidgetManager` uses a description composed of the factory id and the options.
* The `WidgetFactory` does support both, synchronous and asynchronous widget creation.
*
* ### Example usage
*
* ```typescript
* export class MyWidget extends BaseWidget {
* }
*
* @injectable()
* export class MyWidgetFactory implements WidgetFactory {
* id = 'myWidgetFactory';
*
* createWidget(): MaybePromise<Widget> {
* return new MyWidget();
* }
* }
* ```
*/
export interface WidgetFactory {

Expand All @@ -31,8 +51,10 @@ export interface WidgetFactory {
readonly id: string;

/**
* Creates a widget and attaches it to the application shell.
* @param options serializable JSON data.
* Creates a widget using the given options.
* @param options factory specific information as serializable JSON data.
*
* @returns the newly created widget or a promise of the widget
*/
createWidget(options?: any): MaybePromise<Widget>;
}
Expand Down Expand Up @@ -82,7 +104,9 @@ export interface DidCreateWidgetEvent {
}

/**
* Creates and manages widgets.
* The {@link WidgetManager} is the common component responsible for creating and managing widgets. Additional widget factories
* can be registered by using the {@link WidgetFactory} contribution point. To identify a widget, created by a factory, the factory id and
* the creation options are used. This key is commonly referred to as `description` of the widget.
*/
@injectable()
export class WidgetManager {
Expand All @@ -106,13 +130,14 @@ export class WidgetManager {
readonly onWillCreateWidget: Event<WillCreateWidgetEvent> = this.onWillCreateWidgetEmitter.event;

protected readonly onDidCreateWidgetEmitter = new Emitter<DidCreateWidgetEvent>();

readonly onDidCreateWidget: Event<DidCreateWidgetEvent> = this.onDidCreateWidgetEmitter.event;

/**
* Get the list of widgets created for the given factory id.
* Get the list of widgets created by the given widget factory.
* @param factoryId the widget factory id.
*
* @returns the list of widgets created for the given factory id.
* @returns the list of widgets created by the factory with the given id.
*/
getWidgets(factoryId: string): Widget[] {
const result: Widget[] = [];
Expand All @@ -125,7 +150,9 @@ export class WidgetManager {
}

/**
* Try and get the widget.
* Try to get the existing widget for the given description.
* @param factoryId The widget factory id.
* @param options The widget factory specific information.
*
* @returns the widget if available, else `undefined`.
*/
Expand All @@ -140,8 +167,10 @@ export class WidgetManager {

/**
* Get the widget for the given description.
* @param factoryId The widget factory id.
* @param options The widget factory specific information.
*
* @returns a promise resolving to the widget if available, else `undefined.
* @returns a promise resolving to the widget if available, else `undefined`.
*/
async getWidget<T extends Widget>(factoryId: string, options?: any): Promise<T | undefined> {
const key = this.toKey({ factoryId, options });
Expand All @@ -159,7 +188,11 @@ export class WidgetManager {
}

/**
* Creates or returns the widget for the given description.
* Creates a new widget or returns the existing widget for the given description.
* @param factoryId the widget factory id.
* @param options the widget factory specific information.
*
* @returns a promise resolving to the widget.
*/
async getOrCreateWidget<T extends Widget>(factoryId: string, options?: any): Promise<T> {
const key = this.toKey({ factoryId, options });
Expand Down
35 changes: 29 additions & 6 deletions packages/core/src/browser/widget-open-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ import { OpenHandler, OpenerOptions } from './opener-service';
import { WidgetManager } from './widget-manager';

export type WidgetOpenMode = 'open' | 'reveal' | 'activate';

/**
* `WidgetOpenerOptions` define serializable generic options used by the {@link WidgetOpenHandler}.
*/
export interface WidgetOpenerOptions extends OpenerOptions {
/**
* Whether the widget should be only opened, revealed or activated.
* Determines whether the widget should be only opened, revealed or activated.
* By default is `activate`.
*/
mode?: WidgetOpenMode;
Expand All @@ -37,6 +39,9 @@ export interface WidgetOpenerOptions extends OpenerOptions {
widgetOptions?: ApplicationShell.WidgetOptions;
}

/**
* Generic base class for {@link OpenHandler}s that are opening a widget for a given {@link URI}.
*/
@injectable()
export abstract class WidgetOpenHandler<W extends BaseWidget> implements OpenHandler {

Expand Down Expand Up @@ -74,7 +79,11 @@ export abstract class WidgetOpenHandler<W extends BaseWidget> implements OpenHan

/**
* Open a widget for the given uri and options.
* Reject if the given options is not an widget options or a widget cannot be opened.
* Reject if the given options are not widget options or a widget cannot be opened.
* @param uri the uri of the resource that should be opened.
* @param options the widget opener options.
*
* @returns promise of the widget that resolves when the widget has been opened.
*/
async open(uri: URI, options?: WidgetOpenerOptions): Promise<W> {
const widget = await this.getOrCreateWidget(uri, options);
Expand All @@ -97,7 +106,10 @@ export abstract class WidgetOpenHandler<W extends BaseWidget> implements OpenHan
}

/**
* Return an existing widget for the given uri.
* Tries to get an existing widget for the given uri.
* @param uri the uri of the widget.
*
* @returns a promise that resolves to the existing widget or `undefined` if no widget for the given uri exists.
*/
getByUri(uri: URI): Promise<W | undefined> {
return this.getWidget(uri);
Expand All @@ -106,14 +118,19 @@ export abstract class WidgetOpenHandler<W extends BaseWidget> implements OpenHan
/**
* Return an existing widget for the given uri or creates a new one.
*
* It does not open a widget, use `open` instead.
* It does not open a widget, use {@link WidgetOpenHandler#open} instead.
* @param uri uri of the widget.
*
* @returns a promise of the existing or newly created widget.
*/
getOrCreateByUri(uri: URI): Promise<W> {
return this.getOrCreateWidget(uri);
}

/**
* All opened widgets.
* Retrieves all open widgets that have been opened by this handler.
*
* @returns all open widgets for this open handler.
*/
get all(): W[] {
return this.widgetManager.getWidgets(this.id) as W[];
Expand All @@ -131,6 +148,12 @@ export abstract class WidgetOpenHandler<W extends BaseWidget> implements OpenHan

protected abstract createWidgetOptions(uri: URI, options?: WidgetOpenerOptions): Object;

/**
* Closes all widgets that have been opened by this open handler.
* @param options the close options that should be applied to all widgets.
*
* @returns a promise of all closed widgets that resolves after they have been closed.
*/
async closeAll(options?: ApplicationShell.CloseOptions): Promise<W[]> {
const closed = await Promise.all(this.all.map(widget => this.shell.closeWidget(widget.id, options)));
return closed.filter(widget => !!widget) as W[];
Expand Down