package loon.component.layout;
import loon.VerticalAlign;
import loon.geom.SizeValue;
import loon.utils.TArray;
public class HorizontalLayout extends LayoutManager {
public final static HorizontalLayout at(){
return new HorizontalLayout();
}
public final void layoutElements(final LayoutPort root,
final LayoutPort... children) {
if (isInvalid(root, children)) {
return;
}
int rootBoxX = getRootBoxX(root);
int rootBoxY = getRootBoxY(root);
int rootBoxWidth = getRootBoxWidth(root);
int rootBoxHeight = getRootBoxHeight(root);
int getX = rootBoxX;
for (int i = 0; i < children.length; i++) {
LayoutPort current = children[i];
BoxSize box = current.getBox();
LayoutConstraints boxConstraints = current.getBoxConstraints();
int elementWidth;
if (boxConstraints.getWidth() != null
&& boxConstraints.getWidth().hasHeightSuffix()) {
int elementHeight = processHeightConstraint(rootBoxHeight, box,
boxConstraints, 0);
if (_allow) {
box.setHeight(elementHeight);
}
elementWidth = calcElementWidth(
new TArray<LayoutPort>(children), rootBoxWidth,
boxConstraints, elementHeight);
if (_allow) {
box.setWidth(elementWidth);
}
} else if (hasHeightConstraint(boxConstraints)
&& boxConstraints.getHeight().hasWidthSuffix()) {
elementWidth = calcElementWidth(
new TArray<LayoutPort>(children), rootBoxWidth,
boxConstraints, 0);
if (_allow) {
box.setWidth(elementWidth);
}
int elementHeight = processHeightConstraint(rootBoxHeight, box,
boxConstraints, elementWidth);
if (_allow) {
box.setHeight(elementHeight);
}
} else {
elementWidth = calcElementWidth(
new TArray<LayoutPort>(children), rootBoxWidth,
boxConstraints, 0);
if (_allow) {
box.setWidth(elementWidth);
}
int elementHeight = processHeightConstraint(rootBoxHeight, box,
boxConstraints, 0);
if (_allow) {
box.setHeight(elementHeight);
}
}
box.setY(processVerticalAlignment(rootBoxY, rootBoxHeight, box,
boxConstraints));
box.setX(getX);
getX += elementWidth;
}
}
private int processHeightConstraint(final int rootBoxHeight,
final BoxSize box, final LayoutConstraints constraint,
final int elementWidth) {
if (hasHeightConstraint(constraint)) {
if (constraint.getHeight().hasWidthSuffix()) {
return constraint.getHeight().getValueAsInt(elementWidth);
}
return constraint.getHeight().getValueAsInt(rootBoxHeight);
} else {
return rootBoxHeight;
}
}
private boolean hasHeightConstraint(final LayoutConstraints constraint) {
return constraint != null && constraint.getHeight() != null
&& !constraint.getHeight().hasWildcard();
}
private int calcElementWidth(final TArray<LayoutPort> children,
final int rootBoxWidth, final LayoutConstraints boxConstraints,
final int elementHeight) {
if (boxConstraints.getWidth() != null) {
int h = (int) boxConstraints.getWidth().getValue(rootBoxWidth);
if (boxConstraints.getWidth().hasHeightSuffix()) {
h = (int) boxConstraints.getWidth().getValue(elementHeight);
}
if (h != -1) {
return h;
}
}
return getMaxNonFixedWidth(children, rootBoxWidth);
}
private int processVerticalAlignment(final int rootBoxY,
final int rootBoxHeight, final BoxSize box,
final LayoutConstraints boxConstraints) {
if (VerticalAlign.CENTER.equals(boxConstraints.getVerticalAlign())) {
return (int) (rootBoxY + ((rootBoxHeight - box.getHeight()) / 2));
} else if (VerticalAlign.TOP.equals(boxConstraints.getVerticalAlign())) {
return rootBoxY;
} else if (VerticalAlign.BOTTOM.equals(boxConstraints
.getVerticalAlign())) {
return (int) (rootBoxY + (rootBoxHeight - box.getHeight()));
} else {
return rootBoxY;
}
}
private int getMaxNonFixedWidth(final TArray<LayoutPort> elements,
final int parentWidth) {
int maxFixedWidth = 0;
int fixedCount = 0;
for (int i = 0; i < elements.size; i++) {
LayoutPort p = elements.get(i);
LayoutConstraints original = p.getBoxConstraints();
if (original.getWidth() != null) {
if (original.getWidth().isPercentOrPixel()) {
maxFixedWidth += original.getWidth().getValue(parentWidth);
fixedCount++;
}
}
}
int notFixedCount = elements.size - fixedCount;
if (notFixedCount > 0) {
return (parentWidth - maxFixedWidth) / notFixedCount;
} else {
return (parentWidth - maxFixedWidth);
}
}
public final SizeValue calculateConstraintWidth(final LayoutPort root,
final TArray<LayoutPort> children) {
return null;
}
public final SizeValue calculateConstraintHeight(final LayoutPort root,
final TArray<LayoutPort> children) {
int newHeight = 0;
for (LayoutPort e : children) {
int partHeight = e.getBoxConstraints().getHeight().getValueAsInt(0)
- e.getBoxConstraints().getPaddingTop()
.getValueAsInt(root.getBox().getHeight())
- e.getBoxConstraints().getPaddingBottom()
.getValueAsInt(root.getBox().getHeight());
if (partHeight > newHeight) {
newHeight = partHeight;
}
}
return new SizeValue(newHeight + "px");
}
private boolean isInvalid(final LayoutPort root,
final LayoutPort... children) {
return root == null || children == null || children.length == 0;
}
private int getRootBoxX(final LayoutPort root) {
return (int) (root.getBox().getX() + root.getBoxConstraints()
.getPaddingLeft().getValueAsInt(root.getBox().getWidth()));
}
private int getRootBoxY(final LayoutPort root) {
return (int) (root.getBox().getY() + root.getBoxConstraints()
.getPaddingTop().getValueAsInt(root.getBox().getHeight()));
}
private int getRootBoxWidth(final LayoutPort root) {
return (int) (root.getBox().getWidth()
- root.getBoxConstraints().getPaddingLeft()
.getValueAsInt(root.getBox().getWidth()) - root
.getBoxConstraints().getPaddingRight()
.getValueAsInt(root.getBox().getWidth()));
}
private int getRootBoxHeight(final LayoutPort root) {
return (int) (root.getBox().getHeight()
- root.getBoxConstraints().getPaddingTop()
.getValueAsInt(root.getBox().getHeight()) - root
.getBoxConstraints().getPaddingBottom()
.getValueAsInt(root.getBox().getHeight()));
}
}