189 lines
5.6 KiB
JavaScript
189 lines
5.6 KiB
JavaScript
"use strict";
|
|
|
|
// Box that can contain other components
|
|
Toolkit.Panel = class Panel extends Toolkit.Component {
|
|
|
|
// Object constructor
|
|
constructor(application) {
|
|
super(application, "div");
|
|
|
|
// Configure instance fields
|
|
this.application = application;
|
|
this.children = [];
|
|
this.crossAlign = "start";
|
|
this.direction = "row";
|
|
this.edge = "left";
|
|
this.hGap = "0";
|
|
this.layout = "split";
|
|
this.mainAlign = "start";
|
|
this.sizeable = false;
|
|
this.vGap = "0";
|
|
this.wrap = false;
|
|
|
|
// Configure element
|
|
this.element.style.minHeight = "0";
|
|
this.element.style.minWidth = "0";
|
|
|
|
// Configure layout
|
|
this.setSplitLayout("left", false);
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// Public Methods //////////////////////////////
|
|
|
|
// Add a component as a child of this container
|
|
add(component, index) {
|
|
|
|
// Determine the ordinal position of the element within the container
|
|
index = !(typeof index == "number") ? this.children.length :
|
|
Math.floor(Math.min(Math.max(0, index), this.children.length));
|
|
|
|
// Add the component to the container
|
|
component.parent = this;
|
|
this.children.splice(index, 0, component);
|
|
this.arrange();
|
|
}
|
|
|
|
// Create a Button and associate it with the application
|
|
newButton(options) {
|
|
return new Toolkit.Button(this.application, options);
|
|
}
|
|
|
|
// Create a MenuBar and associate it with the application
|
|
newMenuBar(options) {
|
|
return new Toolkit.MenuBar(this.application, options);
|
|
}
|
|
|
|
// Create a Panel and associate it with the application
|
|
newPanel(options) {
|
|
return new Toolkit.Panel(this.application, options);
|
|
}
|
|
|
|
// Remove a component from the container
|
|
remove(component) {
|
|
|
|
// Locate the component in the children
|
|
let index = this.children.indexOf(component);
|
|
if (index == -1)
|
|
return;
|
|
|
|
// Remove the component
|
|
component.parent = null;
|
|
component.element.remove();
|
|
this.children.splice(index, 1);
|
|
this.arrange();
|
|
}
|
|
|
|
// Configure the element with a flex layout
|
|
setFlexLayout(direction, mainAlign, crossAlign, gap, wrap) {
|
|
|
|
// Configure instance fields
|
|
this.layout = "flex";
|
|
this.crossAlign = crossAlign;
|
|
this.direction = direction;
|
|
this.mainAlign = mainAlign;
|
|
this.wrap = wrap;
|
|
|
|
// Working variables
|
|
switch (crossAlign) {
|
|
case "end" : crossAlign = "flex-end" ;
|
|
case "start": crossAlign = "flex-start";
|
|
}
|
|
switch (mainAlign) {
|
|
case "end" : mainAlign = "flex-end" ;
|
|
case "start": mainAlign = "flex-start";
|
|
}
|
|
|
|
// Configure element
|
|
this.element.style.alignItems = crossAlign;
|
|
this.element.style.display = "flex";
|
|
this.element.style.flexDirection = direction;
|
|
this.element.style.justifyContent = mainAlign;
|
|
if (direction == "column") {
|
|
this.hGap = gap;
|
|
this.element.style.rowGap = gap;
|
|
}
|
|
if (direction == "row") {
|
|
this.vGap = gap;
|
|
this.element.style.columnGap = gap;
|
|
}
|
|
if (wrap)
|
|
this.element.style.flexWrap = "wrap";
|
|
else this.element.style.removeProperty("flex-wrap");
|
|
|
|
// Manage components
|
|
this.arrange();
|
|
}
|
|
|
|
// Configure the element with a split layout
|
|
setSplitLayout(edge, sizeable) {
|
|
|
|
// Configure instance fields
|
|
this.layout = "split";
|
|
this.edge = edge;
|
|
this.sizeable = sizeable;
|
|
|
|
// Working variables
|
|
let rows = null, cols = null;
|
|
let tracks = [ "max-content", "auto" ];
|
|
if (sizeable)
|
|
tracks.splice(1, 0, "max-content");
|
|
|
|
// Processing by edge
|
|
switch (edge) {
|
|
case "bottom": tracks.reverse(); // Fallthrough
|
|
case "top" : rows = tracks.join(" "); break;
|
|
case "right" : tracks.reverse(); // Fallthrough
|
|
case "left" : cols = tracks.join(" ");
|
|
}
|
|
|
|
// Configure element
|
|
this.element.style.display = "grid";
|
|
if (cols != null)
|
|
this.element.style.gridTemplateColumns = cols;
|
|
else this.element.style.removeProperty("grid-template-columns");
|
|
if (rows != null)
|
|
this.element.style.gridTemplateRows = rows;
|
|
else this.element.style.removeProperty("grid-template-rows");
|
|
|
|
// Manage components
|
|
this.arrange();
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////// Private Methods /////////////////////////////
|
|
|
|
// Configure the panel's DOM elements
|
|
arrange() {
|
|
let components = [];
|
|
|
|
// Remove all children from the DOM
|
|
for (let comp of this.children)
|
|
comp.element.remove();
|
|
|
|
// Split layout
|
|
if (this.layout == "split") {
|
|
components.push(this.children[0]);
|
|
components.push(this.children[1]);
|
|
if (this.sizeable)
|
|
components.splice(1, 0, this.splitter);
|
|
if (this.edge == "bottom" || this.edge == "right")
|
|
components.reverse();
|
|
}
|
|
|
|
// Flex and grid layouts
|
|
else {
|
|
for (let comp of this.children)
|
|
components.push(comp);
|
|
}
|
|
|
|
// Add the resulting elements to the DOM
|
|
for (let comp of components)
|
|
if (comp)
|
|
this.element.appendChild(comp.element);
|
|
}
|
|
|
|
};
|