import { HTMLWidget, Widget } from "@hpcc-js/common";
import { DockPanel as PhosphorDockPanel, IMessageHandler, IMessageHook, Message, MessageLoop, Widget as PWidget } from "@hpcc-js/phosphor-shim";
import { select as d3Select } from "d3-selection";
import { PDockPanel } from "./PDockPanel";
import { IClosable, Msg, WidgetAdapter } from "./WidgetAdapter";
import "../src/DockPanel.css";
export class DockPanel extends HTMLWidget implements IMessageHandler, IMessageHook {
private _dock = new PDockPanel({ mode: "multiple-document" });
constructor() {
super();
this._tag = "div";
this._dock.id = "p" + this.id();
MessageLoop.installMessageHook(this, this);
}
protected getWidgetAdapter(widget: Widget): WidgetAdapter | null {
let retVal = null;
this._dock.content().some(wa => {
if (wa.widget === widget) {
retVal = wa;
return true;
}
return false;
});
return retVal;
}
addWidget(widget: Widget, title: string, location: PhosphorDockPanel.InsertMode = "split-right", refWidget?: Widget, closable?: boolean | IClosable) {
const addMode: PhosphorDockPanel.IAddOptions = { mode: location, ref: this.getWidgetAdapter(refWidget) };
const wa = new WidgetAdapter(this, widget, {}, closable);
wa.title.label = title;
wa.padding = 8;
this._dock.addWidget(wa, addMode);
this._dock.appendContent(wa);
this._dock.tabsMovable = true;
return this;
}
removeWidget(widget: Widget) {
const wa = this.getWidgetAdapter(widget);
if (wa) {
widget.target(null);
this._dock.removeContent(wa);
}
return this;
}
isVisible(widget: Widget) {
return this.getWidgetAdapter(widget).isVisible;
}
widgetAdapters(): WidgetAdapter[] {
return this._dock.content();
}
widgets(): Widget[] {
return this._dock.content().map(wa => wa.widget);
}
layout(): object;
layout(_: object): this;
layout(_?: object): object | this {
if (!arguments.length) return this._dock.saveLayout();
this._dock.restoreLayout(_ as any);
return this;
}
// Used to delay load a layout during render...
private _layoutObj: object = null;
layoutObj(_: object | null): this {
this._layoutObj = _;
return this;
}
private _pPlaceholder;
enter(domNode, element) {
super.enter(domNode, element);
this._pPlaceholder = element.append("div");
PWidget.attach(this._dock, this._pPlaceholder.node());
}
_prevHideSingleTabs;
update(domNode, element) {
super.update(domNode, element);
this._pPlaceholder
.style("width", this.width() + "px")
.style("height", this.height() + "px")
.style("overflow", "auto")
;
element.select(".p-Widget")
.style("width", this._pPlaceholder.node().clientWidth + "px")
.style("height", this.height() + "px")
;
this.widgets().forEach(w => w.render());
}
exit(domNode, element) {
super.exit(domNode, element);
}
render(callback?: (w: Widget) => void): this {
const context = this;
if (this._layoutObj !== null) {
this.layout(this._layoutObj);
this.layoutObj(null);
}
return super.render((w) => {
this._dock.content().watchRendered(this, callback);
this._dock.update();
setTimeout(() => {
const tabBars = this.element().selectAll(".p-Widget.p-TabBar.p-DockPanel-tabBar");
let refit = false;
tabBars.each(function () {
const tabBar = d3Select(this);
const tabsCount = (tabBar.node() as HTMLElement).childNodes[0].childNodes.length;
const hide = context.hideSingleTabs() && tabsCount === 1;
if (hide !== tabBar.classed("hide")) {
tabBar.classed("hide", hide);
refit = true;
}
});
if (refit) {
this._dock.fit();
}
}, 0);
});
}
refit() {
this._dock.fit();
}
// Phosphor Messaging ---
messageHook(handler: IMessageHandler, msg: Message): boolean {
if (handler === this) {
this.processMessage(msg);
}
return true;
}
_prevActive: Widget;
processMessage(msg: Message): void {
switch (msg.type) {
case "wa-activate-request":
const wa = (msg as Msg.WAActivateRequest).wa;
const widget = wa.widget;
if (this._prevActive !== widget) {
this._prevActive = widget;
this.childActivation(widget, wa);
}
break;
}
}
childActivation(w: Widget, wa: WidgetAdapter) {
}
active(): Widget {
return this._prevActive;
}
}
DockPanel.prototype._class += " phosphor_DockPanel";
export interface DockPanel {
hideSingleTabs(): boolean;
hideSingleTabs(_: boolean): this;
}
DockPanel.prototype.publish("hideSingleTabs", false, "boolean");