|
|
import dom = require("dojo/dom-construct");
|
|
|
import { argumentNotNull } from "@implab/core-amd/safe";
|
|
|
import { BuildContextBase } from "./BuildContextBase";
|
|
|
import { DojoNodePosition, isWidget } from "./traits";
|
|
|
|
|
|
// tslint:disable-next-line: class-name
|
|
|
export interface _Widget {
|
|
|
domNode: Node;
|
|
|
|
|
|
containerNode?: Node;
|
|
|
|
|
|
placeAt?(refNode: string | Node, position?: DojoNodePosition): void;
|
|
|
startup?(): void;
|
|
|
|
|
|
addChild?(widget: any, index?: number): void;
|
|
|
}
|
|
|
|
|
|
export type _WidgetCtor = new (attrs: any, srcNode?: string | Node) => _Widget;
|
|
|
|
|
|
export class WidgetContext extends BuildContextBase<Node> {
|
|
|
readonly widgetClass: _WidgetCtor;
|
|
|
|
|
|
_instance: _Widget | undefined;
|
|
|
|
|
|
constructor(widgetClass: _WidgetCtor) {
|
|
|
super();
|
|
|
argumentNotNull(widgetClass, "widgetClass");
|
|
|
|
|
|
this.widgetClass = widgetClass;
|
|
|
}
|
|
|
|
|
|
_addChild(child: any): void {
|
|
|
const instance = this._getInstance();
|
|
|
|
|
|
if (instance.addChild) {
|
|
|
if (child instanceof WidgetContext)
|
|
|
// layout containers add custom logic to addChild methods
|
|
|
instance.addChild(child.getWidgetInstance());
|
|
|
else if (isWidget(child))
|
|
|
instance.addChild(child);
|
|
|
else
|
|
|
instance.addChild(this.getChildDom(child));
|
|
|
} else {
|
|
|
if (!instance.containerNode)
|
|
|
throw new Error("The widget doesn't have neither addChild nor containerNode");
|
|
|
|
|
|
// the current widget isn't started, it's children shouldn't start too
|
|
|
dom.place(this.getChildDom(child), instance.containerNode);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
_create(attrs: object, children: any[]) {
|
|
|
this._instance = new this.widgetClass(attrs);
|
|
|
if (children)
|
|
|
children.forEach(x => this._addChild(x));
|
|
|
}
|
|
|
|
|
|
private _getInstance() {
|
|
|
if (!this._instance)
|
|
|
throw new Error("The instance of the widget isn't created");
|
|
|
return this._instance;
|
|
|
}
|
|
|
|
|
|
_getDomNode() {
|
|
|
if (!this._instance)
|
|
|
throw new Error("The instance of the widget isn't created");
|
|
|
return this._instance.domNode;
|
|
|
}
|
|
|
|
|
|
/** Overrides default placeAt implementation. Calls placeAt of the
|
|
|
* widget and then starts it.
|
|
|
*
|
|
|
* @param refNode A node or id of the node where the widget should be placed.
|
|
|
* @param position A position relative to refNode.
|
|
|
*/
|
|
|
placeAt(refNode: string | Node, position?: DojoNodePosition) {
|
|
|
this.ensureCreated();
|
|
|
const instance = this._getInstance();
|
|
|
if (typeof instance.placeAt === "function") {
|
|
|
instance.placeAt(refNode, position);
|
|
|
|
|
|
// do we need to force widget startup?
|
|
|
if (typeof instance.startup === "function")
|
|
|
instance.startup();
|
|
|
} else {
|
|
|
super.placeAt(refNode, position);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
getWidgetInstance() {
|
|
|
this.ensureCreated();
|
|
|
return this._getInstance();
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|