import { BBox, HTMLWidget, Platform, Widget } from "@hpcc-js/common";
import "../src/Border2.css";
export type OverflowT = "hidden" | "scroll" | "visible" | "auto";
export type ChartPanelSectionT = "top" | "right" | "bottom" | "left" | "center";
export class WidgetDiv {
private _div;
private _overlay: boolean = false;
private _overflowX: OverflowT = "visible";
private _overflowY: OverflowT = "visible";
private _widget: Widget;
constructor(div) {
this._div = div;
}
overlay(): boolean;
overlay(_: boolean): this;
overlay(_?: boolean): boolean | this {
if (!arguments.length) return this._overlay;
this._overlay = _;
return this;
}
overflowX(): OverflowT;
overflowX(_: OverflowT): this;
overflowX(_?: OverflowT): OverflowT | this {
if (!arguments.length) return this._overflowX;
this._overflowX = _;
this._div.style("overflow-x", _);
return this;
}
overflowY(): OverflowT;
overflowY(_: OverflowT): this;
overflowY(_?: OverflowT): OverflowT | this {
if (!arguments.length) return this._overflowY;
this._overflowY = _;
this._div.style("overflow-y", _);
return this;
}
element() {
return this._div;
}
node(): SVGElement | HTMLElement {
return this._div.node();
}
widget(): Widget;
widget(_: Widget): this;
widget(_?: Widget): Widget | this {
if (!arguments.length) return this._widget;
if (this._widget !== _) {
if (this._widget) {
this._widget.target(null);
}
this._widget = _;
if (this._widget) {
this._widget.target(this._div.node());
}
}
return this;
}
resize(size: { width: number, height: number }) {
if (this._widget) {
this._div
.style("width", `${size.width}px`)
.style("height", `${size.height}px`)
;
this._widget.resize(size);
}
return this;
}
async render(getBBox?, availableHeight?: number, availableWidth?: number): Promise {
let overflowX = this.overflowX();
if(!this.overlay() && overflowX === "visible") {
overflowX = null;
}
let overflowY = this.overflowY();
if(!this.overlay() && overflowY === "visible") {
overflowY = null;
}
this._div
.style("height", this.overlay() ? "0px" : null)
.style("overflow-x", overflowX)
.style("overflow-y", overflowY)
;
if (this._widget) {
return this._widget.renderPromise().then(w => {
if (getBBox && this._widget.visible()) {
const retVal = this._widget.getBBox();
retVal.width += 8;
if (availableHeight !== undefined && retVal.height > availableHeight) {
retVal.width += Platform.getScrollbarWidth();
}
if (availableWidth !== undefined && retVal.width > availableWidth) {
retVal.height += Platform.getScrollbarWidth();
}
if (this.overlay()) {
retVal.height = 0;
} else {
retVal.height += 4;
}
return retVal;
}
return getBBox ? { x: 0, y: 0, width: 0, height: 0 } : undefined;
});
} else {
return Promise.resolve(getBBox ? { x: 0, y: 0, width: 0, height: 0 } : undefined);
}
}
}
export class Border2 extends HTMLWidget {
protected _bodyElement;
protected _topWA: WidgetDiv;
protected _leftWA: WidgetDiv;
protected _centerWA: WidgetDiv;
protected _rightWA: WidgetDiv;
protected _bottomWA: WidgetDiv;
protected _topPrevOverflow: OverflowT;
protected _leftPrevOverflow: OverflowT;
protected _rightPrevOverflow: OverflowT;
protected _bottomPrevOverflow: OverflowT;
constructor() {
super();
this._tag = "div";
}
enter(domNode, element) {
super.enter(domNode, element);
const topElement = element.append("header");
this._bodyElement = element.append("div").attr("class", "body");
const centerElement = this._bodyElement.append("div").attr("class", "center");
const leftElement = this._bodyElement.append("div").attr("class", "lhs");
const rightElement = this._bodyElement.append("div").attr("class", "rhs");
const bottomElement = element.append("div").attr("class", "footer");
this._topWA = new WidgetDiv(topElement);
this._centerWA = new WidgetDiv(centerElement);
this._leftWA = new WidgetDiv(leftElement);
this._rightWA = new WidgetDiv(rightElement);
this._bottomWA = new WidgetDiv(bottomElement);
}
update(domNode, element) {
super.update(domNode, element);
this._topWA.element().style("display", this.showTop() ? null : "none");
this._rightWA.element().style("display", this.showRight() ? null : "none");
this._bottomWA.element().style("display", this.showBottom() ? null : "none");
this._leftWA.element().style("display", this.showLeft() ? null : "none");
if(this.topOverflowX() !== this._topWA.overflowX()) {
this._topWA.overflowX(this.topOverflowX());
}
if(this.rightOverflowX() !== this._rightWA.overflowX()) {
this._rightWA.overflowX(this.rightOverflowX());
}
if(this.bottomOverflowX() !== this._bottomWA.overflowX()) {
this._bottomWA.overflowX(this.bottomOverflowX());
}
if(this.leftOverflowX() !== this._leftWA.overflowX()) {
this._leftWA.overflowX(this.leftOverflowX());
}
if(this.topOverflowY() !== this._topWA.overflowY()) {
this._topWA.overflowY(this.topOverflowY());
}
if(this.rightOverflowY() !== this._rightWA.overflowY()) {
this._rightWA.overflowY(this.rightOverflowY());
}
if(this.bottomOverflowY() !== this._bottomWA.overflowY()) {
this._bottomWA.overflowY(this.bottomOverflowY());
}
if(this.leftOverflowY() !== this._leftWA.overflowY()) {
this._leftWA.overflowY(this.leftOverflowY());
}
this.element()
.style("width", `${this.width()}px`)
.style("height", `${this.height()}px`)
;
}
private targetNull(w?: Widget) {
if (w) {
w.target(null);
}
}
exit(domNode, element) {
this.targetNull(this.center());
this.targetNull(this.bottom());
this.targetNull(this.right());
this.targetNull(this.left());
this.targetNull(this.top());
super.exit(domNode, element);
}
swap(sectionA: ChartPanelSectionT, sectionB: ChartPanelSectionT): this {
const a = this[sectionA]();
const b = this[sectionB]();
this.targetNull(a);
this.targetNull(b);
this[`_${sectionA}WA`].widget(null);
this[`_${sectionB}WA`].widget(null);
this[sectionA](b);
this[sectionB](a);
return this;
}
render(callback?: (w: Widget) => void): this {
const retVal = super.render(w => {
if (this._topWA) {
this._topWA
.widget(this.top())
.overlay(this.topOverlay())
.render(true).then(async topBBox => {
const bottomBBox: BBox = await this._bottomWA.widget(this.bottom()).render(true, undefined, this.width()) as BBox;
const availableHeight = this.height() - (topBBox.height + bottomBBox.height);
const leftBBox: BBox = await this._leftWA.widget(this.left()).render(true, availableHeight) as BBox;
const rightBBox: BBox = await this._rightWA.widget(this.right()).render(true, availableHeight) as BBox;
if (this.bottomHeight_exists()) {
bottomBBox.height = this.bottomHeight();
}
const bodyWidth = this.width() - (leftBBox.width + rightBBox.width);
const bodyHeight = this.height() - (topBBox.height + bottomBBox.height);
const centerOverflowX = this.centerOverflowX();
const centerOverflowY = this.centerOverflowY();
const scrollCenterX = ["auto", "scroll"].indexOf(centerOverflowX) !== -1;
const scrollCenterY = ["auto", "scroll"].indexOf(centerOverflowY) !== -1;
if(scrollCenterX || scrollCenterY) {
this._centerWA
.overflowX(this.centerOverflowX())
.overflowY(this.centerOverflowY())
.widget(this.center())
.resize({
width: bodyWidth,
height: bodyHeight
})
.render()
;
}
this._bodyElement.style("height", `${bodyHeight}px`);
const promises = [
this._topWA
.overflowX(this.topOverflowX())
.overflowY(this.topOverflowY())
.resize({
width: this.width(),
height: topBBox.height
})
.render(),
this._leftWA
.overflowX(this.leftOverflowX())
.overflowY(this.leftOverflowY())
.resize({
width: leftBBox.width,
height: bodyHeight
})
.render(),
this._rightWA
.overflowX(this.rightOverflowX())
.overflowY(this.rightOverflowY())
.resize({
width: rightBBox.width,
height: bodyHeight
})
.render(),
this._centerWA
.overflowX(this.centerOverflowX())
.overflowY(this.centerOverflowY())
.widget(this.center())
.resize({
width: bodyWidth,
height: bodyHeight
})
.render(),
this._bottomWA
.overflowX(this.bottomOverflowX())
.overflowY(this.bottomOverflowY())
.resize({
width: this.width(),
height: bottomBBox.height
})
.render()
];
Promise.all(promises).then(promises => {
if (callback) {
callback(this);
}
});
})
;
} else {
if (callback) {
callback(this);
}
}
});
return retVal;
}
}
Border2.prototype._class += " layout_Border2";
export interface Border2 {
top(): Widget;
top(_: Widget): this;
topOverlay(): boolean;
topOverlay(_: boolean): this;
left(): Widget;
left(_: Widget): this;
center(): Widget;
center(_: Widget): this;
right(): Widget;
right(_: Widget): this;
bottom(): Widget;
bottom(_: Widget): this;
bottomHeight(): number;
bottomHeight(_: number): this;
bottomHeight_exists(): boolean;
topOverflowX(): OverflowT;
topOverflowX(_: OverflowT): this;
rightOverflowX(): OverflowT;
rightOverflowX(_: OverflowT): this;
bottomOverflowX(): OverflowT;
bottomOverflowX(_: OverflowT): this;
leftOverflowX(): OverflowT;
leftOverflowX(_: OverflowT): this;
centerOverflowX(): OverflowT;
centerOverflowX(_: OverflowT): this;
topOverflowY(): OverflowT;
topOverflowY(_: OverflowT): this;
rightOverflowY(): OverflowT;
rightOverflowY(_: OverflowT): this;
bottomOverflowY(): OverflowT;
bottomOverflowY(_: OverflowT): this;
leftOverflowY(): OverflowT;
leftOverflowY(_: OverflowT): this;
centerOverflowY(): OverflowT;
centerOverflowY(_: OverflowT): this;
showTop(): boolean;
showTop(_: boolean): this;
showRight(): boolean;
showRight(_: boolean): this;
showBottom(): boolean;
showBottom(_: boolean): this;
showLeft(): boolean;
showLeft(_: boolean): this;
topOverflowX_default(_: OverflowT);
rightOverflowX_default(_: OverflowT);
bottomOverflowX_default(_: OverflowT);
leftOverflowX_default(_: OverflowT);
centerOverflowX_default(_: OverflowT);
topOverflowY_default(_: OverflowT);
rightOverflowY_default(_: OverflowT);
bottomOverflowY_default(_: OverflowT);
leftOverflowY_default(_: OverflowT);
centerOverflowY_default(_: OverflowT);
}
Border2.prototype.publish("showTop", true, "boolean", "If true, top widget adapter will display");
Border2.prototype.publish("showRight", true, "boolean", "If true, right widget adapter will display");
Border2.prototype.publish("showBottom", true, "boolean", "If true, bottom widget adapter will display");
Border2.prototype.publish("showLeft", true, "boolean", "If true, left widget adapter will display");
Border2.prototype.publish("topOverflowX", "visible", "set", "Sets the overflow-x css style for the top widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("rightOverflowX", "visible", "set", "Sets the overflow-x css style for the right widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("bottomOverflowX", "visible", "set", "Sets the overflow-x css style for the bottom widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("leftOverflowX", "visible", "set", "Sets the overflow-x css style for the left widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("centerOverflowX", "visible", "set", "Sets the overflow-x css style for the center widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("topOverflowY", "visible", "set", "Sets the overflow-y css style for the top widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("rightOverflowY", "visible", "set", "Sets the overflow-y css style for the right widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("bottomOverflowY", "visible", "set", "Sets the overflow-y css style for the bottom widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("leftOverflowY", "visible", "set", "Sets the overflow-y css style for the left widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("centerOverflowY", "visible", "set", "Sets the overflow-y css style for the center widget adapter", ["hidden", "scroll", "visible", "auto"]);
Border2.prototype.publish("top", null, "widget", "Top Widget", undefined, { render: false });
Border2.prototype.publish("topOverlay", false, "boolean", "Overlay Top Widget");
Border2.prototype.publish("left", null, "widget", "Left Widget", undefined, { render: false });
Border2.prototype.publish("center", null, "widget", "Center Widget", undefined, { render: false });
Border2.prototype.publish("right", null, "widget", "Right Widget", undefined, { render: false });
Border2.prototype.publish("bottom", null, "widget", "Bottom Widget", undefined, { render: false });
Border2.prototype.publish("bottomHeight", null, "number", "Bottom Fixed Height", undefined, { optional: true });