diff --git a/javafx-ui-common/src/javafx/scene/layout/BorderPane.java b/javafx-ui-common/src/javafx/scene/layout/BorderPane.java --- a/javafx-ui-common/src/javafx/scene/layout/BorderPane.java +++ b/javafx-ui-common/src/javafx/scene/layout/BorderPane.java @@ -26,6 +26,7 @@ package javafx.scene.layout; +import java.util.ArrayList; import java.util.List; import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectPropertyBase; @@ -587,8 +588,12 @@ topHeight = Math.min(topHeight, insideHeight); layoutInArea(t, insideX, insideY, insideWidth, topHeight, 0/*ignore baseline*/, topMargin, + true,true, alignment != null? alignment.getHpos() : HPos.LEFT, - alignment != null? alignment.getVpos() : VPos.TOP); + alignment != null? alignment.getVpos() : VPos.TOP, + isSnapToPixel(), + false, + false); } if (b != null) { @@ -597,38 +602,54 @@ layoutInArea(b, insideX, insideY + insideHeight - bottomHeight, insideWidth, bottomHeight, 0/*ignore baseline*/, bottomMargin, + true,true, alignment != null? alignment.getHpos() : HPos.LEFT, - alignment != null? alignment.getVpos() : VPos.BOTTOM); + alignment != null? alignment.getVpos() : VPos.BOTTOM, + isSnapToPixel(), + false, + false); } if (l != null) { Pos alignment = getAlignment(l); leftWidth = Math.min(leftWidth, insideWidth); - layoutInArea(l, insideX, insideY + topHeight, + Region.layoutInArea(l, insideX, insideY + topHeight, leftWidth, insideHeight - topHeight - bottomHeight, 0/*ignore baseline*/, leftMargin, + true,true, alignment != null? alignment.getHpos() : HPos.LEFT, - alignment != null? alignment.getVpos() : VPos.TOP); + alignment != null? alignment.getVpos() : VPos.TOP, + isSnapToPixel(), + false, + false); } if (r != null) { Pos alignment = getAlignment(r); rightWidth = Math.min(rightWidth, insideWidth - leftWidth); - layoutInArea(r, insideX + insideWidth - rightWidth, insideY + topHeight, + Region.layoutInArea(r, insideX + insideWidth - rightWidth, insideY + topHeight, rightWidth, insideHeight - topHeight - bottomHeight, 0/*ignore baseline*/, rightMargin, + true,true, alignment != null? alignment.getHpos() : HPos.RIGHT, - alignment != null? alignment.getVpos() : VPos.TOP); + alignment != null? alignment.getVpos() : VPos.TOP, + isSnapToPixel(), + false, + false); } if (c != null) { Pos alignment = getAlignment(c); - layoutInArea(c, insideX + leftWidth, insideY + topHeight, + Region.layoutInArea(c, insideX + leftWidth, insideY + topHeight, insideWidth - leftWidth - rightWidth, insideHeight - topHeight - bottomHeight, 0/*ignore baseline*/, getNodeMargin(c), + true,true, alignment != null? alignment.getHpos() : HPos.CENTER, - alignment != null? alignment.getVpos() : VPos.CENTER); + alignment != null? alignment.getVpos() : VPos.CENTER, + isSnapToPixel(), + false, + false); } } @@ -831,29 +852,42 @@ **************************************************************************/ private final class BorderPositionProperty extends ObjectPropertyBase { - private Node oldValue = null; private String propertyName; - + BorderPositionProperty(String propertyName) { this.propertyName = propertyName; } @Override protected void invalidated() { - final List children = getChildren(); - - if (oldValue != null) { - children.remove(oldValue); + getChildren().setAll(noneNullNodes()); + } + + private List noneNullNodes() { + List l = new ArrayList<>(5); + + if( getCenter() != null ) { + l.add(getCenter()); } - - final Node _value = get(); - this.oldValue = _value; - - if (_value != null) { - children.add(_value); + + if( getRight() != null ) { + l.add(getRight()); } + + if( getLeft() != null ) { + l.add(getLeft()); + } + + if( getBottom() != null ) { + l.add(getBottom()); + } + if( getTop() != null ) { + l.add(getTop()); + } + + return l; } - + @Override public Object getBean() { return BorderPane.this; diff --git a/javafx-ui-common/src/javafx/scene/layout/Region.java b/javafx-ui-common/src/javafx/scene/layout/Region.java --- a/javafx-ui-common/src/javafx/scene/layout/Region.java +++ b/javafx-ui-common/src/javafx/scene/layout/Region.java @@ -247,30 +247,48 @@ } static double computeXOffset(double width, double contentWidth, HPos hpos) { + return computeXOffset(width, contentWidth, hpos, true); + } + + static double computeXOffset(double width, double contentWidth, HPos hpos, boolean allowNegative) { + final double rv; switch(hpos) { case LEFT: - return 0; + rv = 0; + break; case CENTER: - return (width - contentWidth) / 2; + rv = (width - contentWidth) / 2; + break; case RIGHT: - return width - contentWidth; + rv = width - contentWidth; + break; default: throw new AssertionError("Unhandled hPos"); } + return allowNegative ? rv : Math.max(0, rv); } static double computeYOffset(double height, double contentHeight, VPos vpos) { + return computeYOffset(height, contentHeight, vpos, true); + } + + static double computeYOffset(double height, double contentHeight, VPos vpos, boolean allowNegative) { + final double rv; switch(vpos) { case BASELINE: case TOP: - return 0; + rv = 0; + break; case CENTER: - return (height - contentHeight) / 2; + rv = (height - contentHeight) / 2; + break; case BOTTOM: - return height - contentHeight; + rv = height - contentHeight; + break; default: throw new AssertionError("Unhandled vPos"); } + return allowNegative ? rv : Math.max(0,rv); } static double[] createDoubleArray(int length, double value) { @@ -1598,7 +1616,7 @@ snapSpace(childMargin.getRight(), isSnapToPixel), snapSpace(childMargin.getBottom(), isSnapToPixel), snapSpace(childMargin.getLeft(), isSnapToPixel), - halignment, valignment, isSnapToPixel); + halignment, valignment, isSnapToPixel,true,true); } /** @@ -1764,14 +1782,14 @@ double areaBaselineOffset, Insets margin, boolean fillWidth, boolean fillHeight, HPos halignment, VPos valignment) { - layoutInArea(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset, margin, fillWidth, fillHeight, halignment, valignment, isSnapToPixel()); + layoutInArea(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset, margin, fillWidth, fillHeight, halignment, valignment, isSnapToPixel(), true, true); } - + public static void layoutInArea(Node child, double areaX, double areaY, double areaWidth, double areaHeight, double areaBaselineOffset, Insets margin, boolean fillWidth, boolean fillHeight, - HPos halignment, VPos valignment, boolean isSnapToPixel) { + HPos halignment, VPos valignment, boolean isSnapToPixel, boolean allowNegativeX, boolean allowNegativeY) { Insets childMargin = margin != null? margin : Insets.EMPTY; double top = snapSpace(childMargin.getTop(), isSnapToPixel); @@ -1796,7 +1814,6 @@ child.minHeight(-1), fillHeight? innerAreaHeight : Math.min(innerAreaHeight,child.prefHeight(-1)), child.maxHeight(-1)); - } else if (bias == Orientation.HORIZONTAL) { childWidth = boundedSize( child.minWidth(-1), fillWidth? innerAreaWidth : @@ -1820,20 +1837,20 @@ child.resize(snapSize(childWidth, isSnapToPixel),snapSize(childHeight, isSnapToPixel)); } position(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset, - top, right, bottom, left, halignment, valignment, isSnapToPixel); + top, right, bottom, left, halignment, valignment, isSnapToPixel,allowNegativeX,allowNegativeY); } private static void position(Node child, double areaX, double areaY, double areaWidth, double areaHeight, double areaBaselineOffset, double topMargin, double rightMargin, double bottomMargin, double leftMargin, - HPos hpos, VPos vpos, boolean isSnapToPixel) { + HPos hpos, VPos vpos, boolean isSnapToPixel, boolean allowNegativeX, boolean allowNegativeY) { final double xoffset = leftMargin + computeXOffset(areaWidth - leftMargin - rightMargin, - child.getLayoutBounds().getWidth(), hpos); + child.getLayoutBounds().getWidth(), hpos,allowNegativeX); final double yoffset = topMargin + (vpos == VPos.BASELINE? areaBaselineOffset - child.getBaselineOffset() : computeYOffset(areaHeight - topMargin - bottomMargin, - child.getLayoutBounds().getHeight(), vpos)); + child.getLayoutBounds().getHeight(), vpos,allowNegativeY)); // do not snap position if child is not resizable because it can cause gaps final double x = child.isResizable()? snapPosition(areaX + xoffset, isSnapToPixel) : areaX + xoffset; final double y = child.isResizable()? snapPosition(areaY + yoffset, isSnapToPixel) : areaY + yoffset;