blob: b87aeb07cd4ba3f764c912d1497626e44711d72a [file] [log] [blame]
/*
* Copyright (c) 2014-2018 BSI Business Systems Integration AG.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BSI Business Systems Integration AG - initial API and implementation
*/
import {AbstractLayout, graphics, MenuBarLayout, scrollbars} from '../index';
export default class TreeLayout extends AbstractLayout {
constructor(tree) {
super();
this.tree = tree;
this.nodeDimensionsDirty = false;
}
layout($container) {
this._layout($container);
scrollbars.update(this.tree.$data);
}
_layout($container) {
var menuBarSize, containerSize, heightOffset,
menuBar = this.tree.menuBar,
htmlMenuBar = menuBar.htmlComp,
htmlContainer = this.tree.htmlComp;
containerSize = htmlContainer.availableSize({
exact: true
})
.subtract(htmlContainer.insets());
if (this.tree.toggleBreadcrumbStyleEnabled) {
this.tree.setBreadcrumbStyleActive(Math.floor(containerSize.width) <= this.tree.breadcrumbTogglingThreshold);
}
heightOffset = 0;
if (menuBar.$container.isVisible()) {
menuBarSize = MenuBarLayout.size(htmlMenuBar, containerSize);
htmlMenuBar.setSize(menuBarSize);
heightOffset += menuBarSize.height;
}
this._setDataHeight(heightOffset);
// recalculate ViewRangeSize before any rendering is done
this.tree.setViewRangeSize(this.tree.calculateViewRangeSize());
// Check if width has changed
this.nodeDimensionsDirty = this.nodeDimensionsDirty ||
(htmlContainer.sizeCached && htmlContainer.sizeCached.width !== htmlContainer.size().width);
if (this.nodeDimensionsDirty) {
this.nodeDimensionsDirty = false;
if (this.tree.isHorizontalScrollingEnabled()) {
// Width is only relevant if horizontal scrolling is enabled -> mark as dirty
this.tree.nodeWidthDirty = true;
this.tree.maxNodeWidth = 0;
} else {
// Nodes may contain wrapped text (with breadcrumb style-or if nodes contain html) -> update heights
this.tree.updateNodeHeights();
this.tree._renderFiller();
}
}
if (!htmlContainer.layouted) {
this.tree._renderScrollTop();
}
// Always render viewport (not only when viewRangeSize changes), because view range depends on scroll position and data height
this.tree._renderViewport();
// Render scroll top again to make sure the data is really at the correct position after rendering viewport, see tree.setScrollTop for details
if (!htmlContainer.layouted) {
this.tree._renderScrollTop();
}
}
_setDataHeight(heightOffset) {
var $data = this.tree.$data;
heightOffset += $data.cssMarginTop() + $data.cssMarginBottom();
$data.css('height', (heightOffset === 0 ? '100%' : 'calc(100% - ' + heightOffset + 'px)'));
}
preferredLayoutSize($container, options) {
// Make sure viewport is up to date before calculating pref size.
// This is necessary because the tree does not render the view port on any change (like insert or delete nodes). Instead it just invalidates the layout.
this.tree._renderViewport();
// Node dimensions were fixed when calling _renderViewport using the current size, but that size might change during layout
// Only necessary the first time it is layouted, afterwards htmlContainer.sizeCached will be set
if (!this.tree.htmlComp.layouted) {
this.nodeDimensionsDirty = true;
}
return graphics.prefSize($container, options);
}
}