UNPKG

golden-layout

Version:

A multi-screen javascript Layout manager

328 lines 13.5 kB
import { ItemConfig } from '../config/config'; import { ResolvedGroundItemConfig, ResolvedHeaderedItemConfig, ResolvedItemConfig, ResolvedRootItemConfig, ResolvedStackItemConfig } from '../config/resolved-config'; import { AssertError, UnexpectedNullError } from '../errors/internal-error'; import { ItemType } from '../utils/types'; import { getElementWidthAndHeight, setElementHeight, setElementWidth } from '../utils/utils'; import { ComponentItem } from './component-item'; import { ComponentParentableItem } from './component-parentable-item'; import { ContentItem } from './content-item'; import { RowOrColumn } from './row-or-column'; /** * GroundItem is the ContentItem whose one child is the root ContentItem (Root is planted in Ground). * (Previously it was called root however this was incorrect as its child is the root item) * There is only one instance of GroundItem and it is automatically created by the Layout Manager * @internal */ export class GroundItem extends ComponentParentableItem { constructor(layoutManager, rootItemConfig, containerElement) { super(layoutManager, ResolvedGroundItemConfig.create(rootItemConfig), null, GroundItem.createElement(document)); this.isGround = true; this._childElementContainer = this.element; this._containerElement = containerElement; this._containerElement.appendChild(this.element); } init() { if (this.isInitialised === true) return; this.updateNodeSize(); for (let i = 0; i < this.contentItems.length; i++) { this._childElementContainer.appendChild(this.contentItems[i].element); } super.init(); this.initContentItems(); } /** * Loads a new Layout * Internal only. To load a new layout with API, use {@link (LayoutManager:class).loadLayout} */ loadRoot(rootItemConfig) { // Remove existing root if it exists this.clearRoot(); if (rootItemConfig !== undefined) { const rootContentItem = this.layoutManager.createAndInitContentItem(rootItemConfig, this); this.addChild(rootContentItem, 0); } } /** * Adds a ContentItem child to root ContentItem. * Internal only. To load a add with API, use {@link (LayoutManager:class).addItem} * @returns -1 if added as root otherwise index in root ContentItem's content */ addItem(itemConfig, index) { this.layoutManager.checkMinimiseMaximisedStack(); const resolvedItemConfig = ItemConfig.resolve(itemConfig); let parent; if (this.contentItems.length > 0) { parent = this.contentItems[0]; } else { parent = this; } if (parent.isComponent) { throw new Error('Cannot add item as child to ComponentItem'); } else { const contentItem = this.layoutManager.createAndInitContentItem(resolvedItemConfig, parent); index = parent.addChild(contentItem, index); return (parent === this) ? -1 : index; } } loadComponentAsRoot(itemConfig) { // Remove existing root if it exists this.clearRoot(); const resolvedItemConfig = ItemConfig.resolve(itemConfig); if (resolvedItemConfig.maximised) { throw new Error('Root Component cannot be maximised'); } else { const rootContentItem = new ComponentItem(this.layoutManager, resolvedItemConfig, this); rootContentItem.init(); this.addChild(rootContentItem, 0); } } /** * Adds a Root ContentItem. * Internal only. To replace Root ContentItem with API, use {@link (LayoutManager:class).loadLayout} */ addChild(contentItem, index) { if (this.contentItems.length > 0) { throw new Error('Ground node can only have a single child'); } else { // contentItem = this.layoutManager._$normalizeContentItem(contentItem, this); this._childElementContainer.appendChild(contentItem.element); index = super.addChild(contentItem, index); this.updateSize(); this.emitBaseBubblingEvent('stateChanged'); return index; } } /** @internal */ calculateConfigContent() { const contentItems = this.contentItems; const count = contentItems.length; const result = new Array(count); for (let i = 0; i < count; i++) { const item = contentItems[i]; const itemConfig = item.toConfig(); if (ResolvedRootItemConfig.isRootItemConfig(itemConfig)) { result[i] = itemConfig; } else { throw new AssertError('RCCC66832'); } } return result; } /** @internal */ setSize(width, height) { if (width === undefined || height === undefined) { this.updateSize(); // For backwards compatibility with v1.x API } else { setElementWidth(this.element, width); setElementHeight(this.element, height); // GroundItem can be empty if (this.contentItems.length > 0) { setElementWidth(this.contentItems[0].element, width); setElementHeight(this.contentItems[0].element, height); } this.updateContentItemsSize(); } } /** * Adds a Root ContentItem. * Internal only. To replace Root ContentItem with API, use {@link (LayoutManager:class).updateRootSize} */ updateSize() { this.updateNodeSize(); this.updateContentItemsSize(); } createSideAreas() { const areaSize = 50; const oppositeSides = GroundItem.Area.oppositeSides; const result = new Array(Object.keys(oppositeSides).length); let idx = 0; for (const key in oppositeSides) { const side = key; const area = this.getElementArea(); if (area === null) { throw new UnexpectedNullError('RCSA77553'); } else { area.side = side; if (oppositeSides[side][1] === '2') area[side] = area[oppositeSides[side]] - areaSize; else area[side] = area[oppositeSides[side]] + areaSize; area.surface = (area.x2 - area.x1) * (area.y2 - area.y1); result[idx++] = area; } } return result; } highlightDropZone(x, y, area) { this.layoutManager.tabDropPlaceholder.remove(); super.highlightDropZone(x, y, area); } onDrop(contentItem, area) { if (contentItem.isComponent) { const itemConfig = ResolvedStackItemConfig.createDefault(); // since ResolvedItemConfig.contentItems not set up, we need to add header from Component const component = contentItem; itemConfig.header = ResolvedHeaderedItemConfig.Header.createCopy(component.headerConfig); const stack = this.layoutManager.createAndInitContentItem(itemConfig, this); stack.addChild(contentItem); contentItem = stack; } if (this.contentItems.length === 0) { this.addChild(contentItem); } else { /* * If the contentItem that's being dropped is not dropped on a Stack (cases which just passed above and * which would wrap the contentItem in a Stack) we need to check whether contentItem is a RowOrColumn. * If it is, we need to re-wrap it in a Stack like it was when it was dragged by its Tab (it was dragged!). */ if (contentItem.type === ItemType.row || contentItem.type === ItemType.column) { const itemConfig = ResolvedStackItemConfig.createDefault(); const stack = this.layoutManager.createContentItem(itemConfig, this); stack.addChild(contentItem); contentItem = stack; } const type = area.side[0] == 'x' ? ItemType.row : ItemType.column; const dimension = area.side[0] == 'x' ? 'width' : 'height'; const insertBefore = area.side[1] == '2'; const column = this.contentItems[0]; if (!(column instanceof RowOrColumn) || column.type !== type) { const itemConfig = ResolvedItemConfig.createDefault(type); const rowOrColumn = this.layoutManager.createContentItem(itemConfig, this); this.replaceChild(column, rowOrColumn); rowOrColumn.addChild(contentItem, insertBefore ? 0 : undefined, true); rowOrColumn.addChild(column, insertBefore ? undefined : 0, true); column[dimension] = 50; contentItem[dimension] = 50; rowOrColumn.updateSize(); } else { const sibling = column.contentItems[insertBefore ? 0 : column.contentItems.length - 1]; column.addChild(contentItem, insertBefore ? 0 : undefined, true); sibling[dimension] *= 0.5; contentItem[dimension] = sibling[dimension]; column.updateSize(); } } } // No ContentItem can dock with groundItem. However Stack can have a GroundItem parent and Stack requires that // its parent implement dock() function. Accordingly this function is implemented but throws an exception as it should // never be called dock() { throw new AssertError('GID87731'); } // No ContentItem can dock with groundItem. However Stack can have a GroundItem parent and Stack requires that // its parent implement validateDocking() function. Accordingly this function is implemented but throws an exception as it should // never be called validateDocking() { throw new AssertError('GIVD87732'); } getAllContentItems() { const result = [this]; this.deepGetAllContentItems(this.contentItems, result); return result; } getConfigMaximisedItems() { const result = []; this.deepFilterContentItems(this.contentItems, result, (item) => { if (ContentItem.isStack(item) && item.initialWantMaximise) { return true; } else { if (ContentItem.isComponentItem(item) && item.initialWantMaximise) { return true; } else { return false; } } }); return result; } getItemsByPopInParentId(popInParentId) { const result = []; this.deepFilterContentItems(this.contentItems, result, (item) => item.popInParentIds.includes(popInParentId)); return result; } toConfig() { throw new Error('Cannot generate GroundItem config'); } // eslint-disable-next-line @typescript-eslint/no-unused-vars setActiveComponentItem(item, focus, suppressFocusEvent) { // only applicable if ComponentItem is root and then it always has focus } updateNodeSize() { const { width, height } = getElementWidthAndHeight(this._containerElement); setElementWidth(this.element, width); setElementHeight(this.element, height); /* * GroundItem can be empty */ if (this.contentItems.length > 0) { setElementWidth(this.contentItems[0].element, width); setElementHeight(this.contentItems[0].element, height); } } clearRoot() { // Remove existing root if it exists const contentItems = this.contentItems; switch (contentItems.length) { case 0: { return; } case 1: { const existingRootContentItem = contentItems[0]; existingRootContentItem.remove(); return; } default: { throw new AssertError('GILR07721'); } } } deepGetAllContentItems(content, result) { for (let i = 0; i < content.length; i++) { const contentItem = content[i]; result.push(contentItem); this.deepGetAllContentItems(contentItem.contentItems, result); } } deepFilterContentItems(content, result, checkAcceptFtn) { for (let i = 0; i < content.length; i++) { const contentItem = content[i]; if (checkAcceptFtn(contentItem)) { result.push(contentItem); } this.deepFilterContentItems(contentItem.contentItems, result, checkAcceptFtn); } } } /** @internal */ (function (GroundItem) { let Area; (function (Area) { Area.oppositeSides = { y2: 'y1', x2: 'x1', y1: 'y2', x1: 'x2', }; })(Area = GroundItem.Area || (GroundItem.Area = {})); function createElement(document) { const element = document.createElement('div'); element.classList.add("lm_goldenlayout" /* GoldenLayout */); element.classList.add("lm_item" /* Item */); element.classList.add("lm_root" /* Root */); return element; } GroundItem.createElement = createElement; })(GroundItem || (GroundItem = {})); //# sourceMappingURL=ground-item.js.map