blob: 9759ece6553ac0472ffd3cde23133e0c2c56ad65 [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, Dimension} from '../index';
export default class GroupLayout extends AbstractLayout {
constructor(group) {
super();
this.group = group;
}
layout($container) {
var htmlComp = this.group.htmlComp;
var containerSize = htmlComp.availableSize()
.subtract(htmlComp.insets());
var htmlHeader = this.group.htmlHeader;
var headerSize = htmlHeader.prefSize({
widthHint: containerSize.width
});
headerSize.width = containerSize.width;
headerSize = headerSize.subtract(htmlHeader.margins());
htmlHeader.setSize(headerSize);
var htmlFooter = this.group.htmlFooter;
if (htmlFooter.isVisible()) {
var footerSize = htmlFooter.prefSize({
includeMargin: false,
useCssSize: true
});
footerSize.width = containerSize.width;
htmlFooter.setSize(footerSize.subtract(htmlFooter.margins()));
}
// 1st condition: Set size only if group is expanded
// 2nd condition: There is no need to update it during the expand animation (the body will be layouted correctly before the animation starts)
// 3rd condition: When Group.setCollapsed(false) has been called an event is triggered that might causes invalidating layout on other all groups (inclusive currently expanding group).
// The body of the currently expanding group is not rendered at this time.
// 4th condition: When body is invisible by property (bodyVisible)
if (this.group.collapsed || this.group.bodyAnimating || !this.group.body.rendered || !this.group.body.isVisible()) {
return;
}
var htmlBody = this.group.body.htmlComp;
var bodySize = containerSize.subtract(htmlBody.margins());
bodySize.height -= headerSize.height;
if (htmlFooter.isVisible()) {
bodySize.height -= htmlFooter.prefSize(true).height;
}
htmlBody.setSize(bodySize);
}
invalidate(htmlSource) {
var htmlBody = this.group.body.htmlComp;
// If a child triggers a layout invalidation, the animation should be stopped and restarted because the body will likely have another height.
// This will happen for sure if a child is an image which will be loaded during the animation.
if (htmlBody && this.group.bodyAnimating && htmlSource && htmlSource.isDescendantOf(this.group.htmlComp)) {
// Stop running animation
this.group.body.$container.stop();
// Resize to new height
this.group.resizeBody();
}
}
preferredLayoutSize($container, options) {
options = options || {};
var prefSize;
var htmlComp = this.group.htmlComp;
var htmlHeader = this.group.htmlHeader;
var htmlBody = this.group.body.htmlComp;
var htmlFooter = this.group.htmlFooter;
// HeightHint not supported
options.heightHint = null;
if (this.group.bodyAnimating) {
// Return the current size when the body is collapsing or expanding
// so that the widgets on the bottom and on top move smoothly with the animation
prefSize = htmlBody.size(true);
} else if (this.group.collapsed || !this.group.body.rendered || !this.group.body.isVisible()) {
// Body may not be rendered even if collapsed is false if property has changed but _renderCollapse not called yet
// (if revalidateLayoutTree is called during collapsed property event)
prefSize = new Dimension(0, 0);
} else {
prefSize = htmlBody.prefSize(options)
.add(htmlBody.margins());
}
prefSize = prefSize.add(htmlComp.insets({
includeMargin: true
}));
prefSize.height += htmlHeader.prefSize(options)
.add(htmlHeader.margins()).height;
if (htmlFooter.isVisible()) {
prefSize.height += htmlFooter.prefSize({
includeMargin: true,
useCssSize: true
}).height;
}
return prefSize;
}
}