modules/graphics/src/main/java/javafx/scene/layout/Region.java
Print this page
@@ -75,10 +75,12 @@
import com.sun.javafx.scene.DirtyBits;
import com.sun.javafx.scene.input.PickResultChooser;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.javafx.sg.prism.NGRegion;
import com.sun.javafx.tk.Toolkit;
+import javafx.scene.Scene;
+import javafx.stage.Window;
import sun.util.logging.PlatformLogger;
import sun.util.logging.PlatformLogger.Level;
/**
* Region is the base class for all JavaFX Node-based UI Controls, and all layout containers.
@@ -206,19 +208,76 @@
double adjustWidthByMargin(double width, Insets margin) {
if (margin == null || margin == Insets.EMPTY) {
return width;
}
boolean isSnapToPixel = isSnapToPixel();
- return width - snapSpace(margin.getLeft(), isSnapToPixel) - snapSpace(margin.getRight(), isSnapToPixel);
+ return width - snapSpaceX(margin.getLeft(), isSnapToPixel) - snapSpaceX(margin.getRight(), isSnapToPixel);
}
double adjustHeightByMargin(double height, Insets margin) {
if (margin == null || margin == Insets.EMPTY) {
return height;
}
boolean isSnapToPixel = isSnapToPixel();
- return height - snapSpace(margin.getTop(), isSnapToPixel) - snapSpace(margin.getBottom(), isSnapToPixel);
+ return height - snapSpaceY(margin.getTop(), isSnapToPixel) - snapSpaceY(margin.getBottom(), isSnapToPixel);
+ }
+
+ private static final boolean snapVerbose = false;
+ private static double getSnapScaleX(Node n) {
+ final double sx = _getSnapScaleXimpl(n.getScene());
+ if (snapVerbose) System.out.println("static:"+n+" scale is "+sx);
+ return sx;
+ }
+ private static double _getSnapScaleXimpl(Scene scene) {
+ if (scene == null) return 1.0;
+ Window window = scene.getWindow();
+ if (window == null) return 1.0;
+ return window.getRenderScaleX();
+ }
+
+ private static double getSnapScaleY(Node n) {
+ double sy = _getSnapScaleYimpl(n.getScene());
+ if (snapVerbose) System.out.println("static:"+n+" scale is "+sy);
+ return sy;
+ }
+ private static double _getSnapScaleYimpl(Scene scene) {
+ if (scene == null) return 1.0;
+ Window window = scene.getWindow();
+ if (window == null) return 1.0;
+ return window.getRenderScaleY();
+ }
+
+ private double lastScaleX = -1;
+ private double getSnapScaleX() {
+ double sx = _getSnapScaleXimpl(getScene());
+ if (snapVerbose && sx != lastScaleX) {
+ System.out.println(this+" scale is "+sx);
+ lastScaleX = sx;
+ }
+ return sx;
+ }
+
+ private double lastScaleY = -1;
+ private double getSnapScaleY() {
+ double sy = _getSnapScaleYimpl(getScene());
+ if (snapVerbose && sy != lastScaleY) {
+ System.out.println(this+" scale is "+sy);
+ lastScaleY = sy;
+ }
+ return sy;
+ }
+
+ private static double scaledRound(double value, double scale) {
+ return Math.round(value * scale) / scale;
+ }
+
+ private static double scaledFloor(double value, double scale) {
+ return Math.floor(value * scale) / scale;
+ }
+
+ private static double scaledCeil(double value, double scale) {
+ return Math.ceil(value * scale) / scale;
}
/**
* If snapToPixel is true, then the value is rounded using Math.round. Otherwise,
* the value is simply returned. This method will surely be JIT'd under normal
@@ -229,43 +288,80 @@
*
* @param value The value that needs to be snapped
* @param snapToPixel Whether to snap to pixel
* @return value either as passed in or rounded based on snapToPixel
*/
- private static double snapSpace(double value, boolean snapToPixel) {
- return snapToPixel ? Math.round(value) : value;
+ private double snapSpaceX(double value, boolean snapToPixel) {
+ return snapToPixel ? scaledRound(value, getSnapScaleX()) : value;
+ }
+ private double snapSpaceY(double value, boolean snapToPixel) {
+ return snapToPixel ? scaledRound(value, getSnapScaleY()) : value;
+ }
+
+ private static double snapSpace(double value, boolean snapToPixel, double snapScale) {
+ return snapToPixel ? scaledRound(value, snapScale) : value;
}
/**
* If snapToPixel is true, then the value is ceil'd using Math.ceil. Otherwise,
* the value is simply returned.
*
* @param value The value that needs to be snapped
* @param snapToPixel Whether to snap to pixel
* @return value either as passed in or ceil'd based on snapToPixel
*/
- private static double snapSize(double value, boolean snapToPixel) {
- return snapToPixel ? Math.ceil(value) : value;
+ private double snapSizeX(double value, boolean snapToPixel) {
+ return snapToPixel ? scaledCeil(value, getSnapScaleX()) : value;
+ }
+ private double snapSizeY(double value, boolean snapToPixel) {
+ return snapToPixel ? scaledCeil(value, getSnapScaleY()) : value;
+ }
+
+ private static double snapSize(double value, boolean snapToPixel, double snapScale) {
+ return snapToPixel ? scaledCeil(value, snapScale) : value;
}
/**
* If snapToPixel is true, then the value is rounded using Math.round. Otherwise,
* the value is simply returned.
*
* @param value The value that needs to be snapped
* @param snapToPixel Whether to snap to pixel
* @return value either as passed in or rounded based on snapToPixel
*/
- private static double snapPosition(double value, boolean snapToPixel) {
- return snapToPixel ? Math.round(value) : value;
+ private double snapPositionX(double value, boolean snapToPixel) {
+ return snapToPixel ? scaledRound(value, getSnapScaleX()) : value;
+ }
+ private double snapPositionY(double value, boolean snapToPixel) {
+ return snapToPixel ? scaledRound(value, getSnapScaleY()) : value;
+ }
+
+ private static double snapPosition(double value, boolean snapToPixel, double snapScale) {
+ return snapToPixel ? scaledRound(value, snapScale) : value;
}
- private static double snapPortion(double value, boolean snapToPixel) {
- if (snapToPixel) {
- return value == 0 ? 0 :(value > 0 ? Math.max(1, Math.floor(value)) : Math.min(-1, Math.ceil(value)));
+ private double snapPortionX(double value, boolean snapToPixel) {
+ if (!snapToPixel || value == 0) return value;
+ double s = getSnapScaleX();
+ value *= s;
+ if (value > 0) {
+ value = Math.max(1, Math.floor(value));
+ } else {
+ value = Math.min(-1, Math.ceil(value));
+ }
+ return value / s;
+ }
+ private double snapPortionY(double value, boolean snapToPixel) {
+ if (!snapToPixel || value == 0) return value;
+ double s = getSnapScaleY();
+ value *= s;
+ if (value > 0) {
+ value = Math.max(1, Math.floor(value));
+ } else {
+ value = Math.min(-1, Math.ceil(value));
}
- return value;
+ return value / s;
}
double getAreaBaselineOffset(List<Node> children, Callback<Node, Insets> margins,
Function<Integer, Double> positionToWidth,
double areaHeight, boolean fillHeight) {
@@ -309,15 +405,18 @@
*/
static double getAreaBaselineOffset(List<Node> children, Callback<Node, Insets> margins,
Function<Integer, Double> positionToWidth,
double areaHeight, Function<Integer, Boolean> fillHeight, double minComplement, boolean snapToPixel) {
double b = 0;
+ double snapScaleV = 0.0;
for (int i = 0;i < children.size(); ++i) {
Node n = children.get(i);
+ // Note: all children should be coming from the same parent so they should all have the same snapScale
+ if (snapToPixel && i == 0) snapScaleV = getSnapScaleY(n.getParent());
Insets margin = margins.call(n);
- double top = margin != null? snapSpace(margin.getTop(), snapToPixel) : 0;
- double bottom = (margin != null? snapSpace(margin.getBottom(), snapToPixel) : 0);
+ double top = margin != null ? snapSpace(margin.getTop(), snapToPixel, snapScaleV) : 0;
+ double bottom = (margin != null ? snapSpace(margin.getBottom(), snapToPixel, snapScaleV) : 0);
final double bo = n.getBaselineOffset();
if (bo == BASELINE_OFFSET_SAME_AS_HEIGHT) {
double alt = -1;
if (n.getContentBias() == Orientation.HORIZONTAL) {
alt = positionToWidth.apply(i);
@@ -1555,41 +1654,125 @@
protected double computeMaxHeight(double width) {
return Double.MAX_VALUE;
}
/**
- * If this region's snapToPixel property is true, returns a value rounded
- * to the nearest pixel, else returns the same value.
+ * If this region's snapToPixel property is false, this method returns the
+ * same value, else it tries to return a value rounded to the nearest
+ * pixel, but since there is no indication if the value is a vertical
+ * or horizontal measurement then it may be snapped to the wrong pixel
+ * size metric on screens with different horizontal and vertical scales.
* @param value the space value to be snapped
* @return value rounded to nearest pixel
+ * @deprecated replaced by {@code snapSpaceX()} and {@code snapSpaceY()}
*/
+ @Deprecated
protected double snapSpace(double value) {
- return snapSpace(value, isSnapToPixel());
+ return snapSpaceX(value, isSnapToPixel());
}
/**
- * If this region's snapToPixel property is true, returns a value ceiled
- * to the nearest pixel, else returns the same value.
+ * If this region's snapToPixel property is true, returns a value rounded
+ * to the nearest pixel in the horizontal direction, else returns the
+ * same value.
+ * @param value the space value to be snapped
+ * @return value rounded to nearest pixel
+ */
+ protected double snapSpaceX(double value) {
+ return snapSpaceX(value, isSnapToPixel());
+ }
+
+ /**
+ * If this region's snapToPixel property is true, returns a value rounded
+ * to the nearest pixel in the vertical direction, else returns the
+ * same value.
+ * @param value the space value to be snapped
+ * @return value rounded to nearest pixel
+ */
+ protected double snapSpaceY(double value) {
+ return snapSpaceY(value, isSnapToPixel());
+ }
+
+ /**
+ * If this region's snapToPixel property is false, this method returns the
+ * same value, else it tries to return a value ceiled to the nearest
+ * pixel, but since there is no indication if the value is a vertical
+ * or horizontal measurement then it may be snapped to the wrong pixel
+ * size metric on screens with different horizontal and vertical scales.
* @param value the size value to be snapped
* @return value ceiled to nearest pixel
+ * @deprecated replaced by {@code snapSizeX()} and {@code snapSizeY()}
*/
+ @Deprecated
protected double snapSize(double value) {
- return snapSize(value, isSnapToPixel());
+ return snapSizeX(value, isSnapToPixel());
}
/**
- * If this region's snapToPixel property is true, returns a value rounded
- * to the nearest pixel, else returns the same value.
+ * If this region's snapToPixel property is true, returns a value ceiled
+ * to the nearest pixel in the horizontal direction, else returns the
+ * same value.
+ * @param value the size value to be snapped
+ * @return value ceiled to nearest pixel
+ */
+ protected double snapSizeX(double value) {
+ return snapSizeX(value, isSnapToPixel());
+ }
+
+ /**
+ * If this region's snapToPixel property is true, returns a value ceiled
+ * to the nearest pixel in the vertical direction, else returns the
+ * same value.
+ * @param value the size value to be snapped
+ * @return value ceiled to nearest pixel
+ */
+ protected double snapSizeY(double value) {
+ return snapSizeY(value, isSnapToPixel());
+ }
+
+ /**
+ * If this region's snapToPixel property is false, this method returns the
+ * same value, else it tries to return a value rounded to the nearest
+ * pixel, but since there is no indication if the value is a vertical
+ * or horizontal measurement then it may be snapped to the wrong pixel
+ * size metric on screens with different horizontal and vertical scales.
* @param value the position value to be snapped
* @return value rounded to nearest pixel
+ * @deprecated replaced by {@code snapPositionX()} and {@code snapPositionY()}
*/
+ @Deprecated
protected double snapPosition(double value) {
- return snapPosition(value, isSnapToPixel());
+ return snapPositionX(value, isSnapToPixel());
+ }
+
+ /**
+ * If this region's snapToPixel property is true, returns a value rounded
+ * to the nearest pixel in the horizontal direction, else returns the
+ * same value.
+ * @param value the position value to be snapped
+ * @return value rounded to nearest pixel
+ */
+ protected double snapPositionX(double value) {
+ return snapPositionX(value, isSnapToPixel());
+ }
+
+ /**
+ * If this region's snapToPixel property is true, returns a value rounded
+ * to the nearest pixel in the vertical direction, else returns the
+ * same value.
+ * @param value the position value to be snapped
+ * @return value rounded to nearest pixel
+ */
+ protected double snapPositionY(double value) {
+ return snapPositionY(value, isSnapToPixel());
}
- double snapPortion(double value) {
- return snapPortion(value, isSnapToPixel());
+ double snapPortionX(double value) {
+ return snapPortionX(value, isSnapToPixel());
+ }
+ double snapPortionY(double value) {
+ return snapPortionY(value, isSnapToPixel());
}
/**
* Utility method to get the top inset which includes padding and border
@@ -1640,191 +1823,191 @@
return computeChildMinAreaWidth(child, -1, margin, -1, false);
}
double computeChildMinAreaWidth(Node child, double baselineComplement, Insets margin, double height, boolean fillHeight) {
final boolean snap = isSnapToPixel();
- double left = margin != null? snapSpace(margin.getLeft(), snap) : 0;
- double right = margin != null? snapSpace(margin.getRight(), snap) : 0;
+ double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0;
+ double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0;
double alt = -1;
if (height != -1 && child.isResizable() && child.getContentBias() == Orientation.VERTICAL) { // width depends on height
- double top = margin != null? snapSpace(margin.getTop(), snap) : 0;
- double bottom = (margin != null? snapSpace(margin.getBottom(), snap) : 0);
+ double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0;
+ double bottom = (margin != null? snapSpaceY(margin.getBottom(), snap) : 0);
double bo = child.getBaselineOffset();
final double contentHeight = bo == BASELINE_OFFSET_SAME_AS_HEIGHT && baselineComplement != -1 ?
height - top - bottom - baselineComplement :
height - top - bottom;
if (fillHeight) {
- alt = snapSize(boundedSize(
+ alt = snapSizeY(boundedSize(
child.minHeight(-1), contentHeight,
child.maxHeight(-1)));
} else {
- alt = snapSize(boundedSize(
+ alt = snapSizeY(boundedSize(
child.minHeight(-1),
child.prefHeight(-1),
Math.min(child.maxHeight(-1), contentHeight)));
}
}
- return left + snapSize(child.minWidth(alt)) + right;
+ return left + snapSizeX(child.minWidth(alt)) + right;
}
double computeChildMinAreaHeight(Node child, Insets margin) {
return computeChildMinAreaHeight(child, -1, margin, -1);
}
double computeChildMinAreaHeight(Node child, double minBaselineComplement, Insets margin, double width) {
final boolean snap = isSnapToPixel();
- double top =margin != null? snapSpace(margin.getTop(), snap) : 0;
- double bottom = margin != null? snapSpace(margin.getBottom(), snap) : 0;
+ double top =margin != null? snapSpaceY(margin.getTop(), snap) : 0;
+ double bottom = margin != null? snapSpaceY(margin.getBottom(), snap) : 0;
double alt = -1;
if (child.isResizable() && child.getContentBias() == Orientation.HORIZONTAL) { // height depends on width
- double left = margin != null? snapSpace(margin.getLeft(), snap) : 0;
- double right = margin != null? snapSpace(margin.getRight(), snap) : 0;
- alt = snapSize(width != -1? boundedSize(child.minWidth(-1), width - left - right, child.maxWidth(-1)) :
+ double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0;
+ double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0;
+ alt = snapSizeX(width != -1? boundedSize(child.minWidth(-1), width - left - right, child.maxWidth(-1)) :
child.maxWidth(-1));
}
// For explanation, see computeChildPrefAreaHeight
if (minBaselineComplement != -1) {
double baseline = child.getBaselineOffset();
if (child.isResizable() && baseline == BASELINE_OFFSET_SAME_AS_HEIGHT) {
- return top + snapSize(child.minHeight(alt)) + bottom
+ return top + snapSizeY(child.minHeight(alt)) + bottom
+ minBaselineComplement;
} else {
return baseline + minBaselineComplement;
}
} else {
- return top + snapSize(child.minHeight(alt)) + bottom;
+ return top + snapSizeY(child.minHeight(alt)) + bottom;
}
}
double computeChildPrefAreaWidth(Node child, Insets margin) {
return computeChildPrefAreaWidth(child, -1, margin, -1, false);
}
double computeChildPrefAreaWidth(Node child, double baselineComplement, Insets margin, double height, boolean fillHeight) {
final boolean snap = isSnapToPixel();
- double left = margin != null? snapSpace(margin.getLeft(), snap) : 0;
- double right = margin != null? snapSpace(margin.getRight(), snap) : 0;
+ double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0;
+ double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0;
double alt = -1;
if (height != -1 && child.isResizable() && child.getContentBias() == Orientation.VERTICAL) { // width depends on height
- double top = margin != null? snapSpace(margin.getTop(), snap) : 0;
- double bottom = margin != null? snapSpace(margin.getBottom(), snap) : 0;
+ double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0;
+ double bottom = margin != null? snapSpaceY(margin.getBottom(), snap) : 0;
double bo = child.getBaselineOffset();
final double contentHeight = bo == BASELINE_OFFSET_SAME_AS_HEIGHT && baselineComplement != -1 ?
height - top - bottom - baselineComplement :
height - top - bottom;
if (fillHeight) {
- alt = snapSize(boundedSize(
+ alt = snapSizeY(boundedSize(
child.minHeight(-1), contentHeight,
child.maxHeight(-1)));
} else {
- alt = snapSize(boundedSize(
+ alt = snapSizeY(boundedSize(
child.minHeight(-1),
child.prefHeight(-1),
Math.min(child.maxHeight(-1), contentHeight)));
}
}
- return left + snapSize(boundedSize(child.minWidth(alt), child.prefWidth(alt), child.maxWidth(alt))) + right;
+ return left + snapSizeX(boundedSize(child.minWidth(alt), child.prefWidth(alt), child.maxWidth(alt))) + right;
}
double computeChildPrefAreaHeight(Node child, Insets margin) {
return computeChildPrefAreaHeight(child, -1, margin, -1);
}
double computeChildPrefAreaHeight(Node child, double prefBaselineComplement, Insets margin, double width) {
final boolean snap = isSnapToPixel();
- double top = margin != null? snapSpace(margin.getTop(), snap) : 0;
- double bottom = margin != null? snapSpace(margin.getBottom(), snap) : 0;
+ double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0;
+ double bottom = margin != null? snapSpaceY(margin.getBottom(), snap) : 0;
double alt = -1;
if (child.isResizable() && child.getContentBias() == Orientation.HORIZONTAL) { // height depends on width
- double left = margin != null ? snapSpace(margin.getLeft(), snap) : 0;
- double right = margin != null ? snapSpace(margin.getRight(), snap) : 0;
- alt = snapSize(boundedSize(
+ double left = margin != null ? snapSpaceX(margin.getLeft(), snap) : 0;
+ double right = margin != null ? snapSpaceX(margin.getRight(), snap) : 0;
+ alt = snapSizeX(boundedSize(
child.minWidth(-1), width != -1 ? width - left - right
: child.prefWidth(-1), child.maxWidth(-1)));
}
if (prefBaselineComplement != -1) {
double baseline = child.getBaselineOffset();
if (child.isResizable() && baseline == BASELINE_OFFSET_SAME_AS_HEIGHT) {
// When baseline is same as height, the preferred height of the node will be above the baseline, so we need to add
// the preferred complement to it
- return top + snapSize(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom
+ return top + snapSizeY(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom
+ prefBaselineComplement;
} else {
// For all other Nodes, it's just their baseline and the complement.
// Note that the complement already contain the Node's preferred (or fixed) height
return top + baseline + prefBaselineComplement + bottom;
}
} else {
- return top + snapSize(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom;
+ return top + snapSizeY(boundedSize(child.minHeight(alt), child.prefHeight(alt), child.maxHeight(alt))) + bottom;
}
}
double computeChildMaxAreaWidth(Node child, double baselineComplement, Insets margin, double height, boolean fillHeight) {
double max = child.maxWidth(-1);
if (max == Double.MAX_VALUE) {
return max;
}
final boolean snap = isSnapToPixel();
- double left = margin != null? snapSpace(margin.getLeft(), snap) : 0;
- double right = margin != null? snapSpace(margin.getRight(), snap) : 0;
+ double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0;
+ double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0;
double alt = -1;
if (height != -1 && child.isResizable() && child.getContentBias() == Orientation.VERTICAL) { // width depends on height
- double top = margin != null? snapSpace(margin.getTop(), snap) : 0;
- double bottom = (margin != null? snapSpace(margin.getBottom(), snap) : 0);
+ double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0;
+ double bottom = (margin != null? snapSpaceY(margin.getBottom(), snap) : 0);
double bo = child.getBaselineOffset();
final double contentHeight = bo == BASELINE_OFFSET_SAME_AS_HEIGHT && baselineComplement != -1 ?
height - top - bottom - baselineComplement :
height - top - bottom;
if (fillHeight) {
- alt = snapSize(boundedSize(
+ alt = snapSizeY(boundedSize(
child.minHeight(-1), contentHeight,
child.maxHeight(-1)));
} else {
- alt = snapSize(boundedSize(
+ alt = snapSizeY(boundedSize(
child.minHeight(-1),
child.prefHeight(-1),
Math.min(child.maxHeight(-1), contentHeight)));
}
max = child.maxWidth(alt);
}
// if min > max, min wins, so still need to call boundedSize()
- return left + snapSize(boundedSize(child.minWidth(alt), max, Double.MAX_VALUE)) + right;
+ return left + snapSizeX(boundedSize(child.minWidth(alt), max, Double.MAX_VALUE)) + right;
}
double computeChildMaxAreaHeight(Node child, double maxBaselineComplement, Insets margin, double width) {
double max = child.maxHeight(-1);
if (max == Double.MAX_VALUE) {
return max;
}
final boolean snap = isSnapToPixel();
- double top = margin != null? snapSpace(margin.getTop(), snap) : 0;
- double bottom = margin != null? snapSpace(margin.getBottom(), snap) : 0;
+ double top = margin != null? snapSpaceY(margin.getTop(), snap) : 0;
+ double bottom = margin != null? snapSpaceY(margin.getBottom(), snap) : 0;
double alt = -1;
if (child.isResizable() && child.getContentBias() == Orientation.HORIZONTAL) { // height depends on width
- double left = margin != null? snapSpace(margin.getLeft(), snap) : 0;
- double right = margin != null? snapSpace(margin.getRight(), snap) : 0;
- alt = snapSize(width != -1? boundedSize(child.minWidth(-1), width - left - right, child.maxWidth(-1)) :
+ double left = margin != null? snapSpaceX(margin.getLeft(), snap) : 0;
+ double right = margin != null? snapSpaceX(margin.getRight(), snap) : 0;
+ alt = snapSizeX(width != -1? boundedSize(child.minWidth(-1), width - left - right, child.maxWidth(-1)) :
child.minWidth(-1));
max = child.maxHeight(alt);
}
// For explanation, see computeChildPrefAreaHeight
if (maxBaselineComplement != -1) {
double baseline = child.getBaselineOffset();
if (child.isResizable() && baseline == BASELINE_OFFSET_SAME_AS_HEIGHT) {
- return top + snapSize(boundedSize(child.minHeight(alt), child.maxHeight(alt), Double.MAX_VALUE)) + bottom
+ return top + snapSizeY(boundedSize(child.minHeight(alt), child.maxHeight(alt), Double.MAX_VALUE)) + bottom
+ maxBaselineComplement;
} else {
return top + baseline + maxBaselineComplement + bottom;
}
} else {
// if min > max, min wins, so still need to call boundedSize()
- return top + snapSize(boundedSize(child.minHeight(alt), max, Double.MAX_VALUE)) + bottom;
+ return top + snapSizeY(boundedSize(child.minHeight(alt), max, Double.MAX_VALUE)) + bottom;
}
}
/* Max of children's minimum area widths */
@@ -1950,21 +2133,21 @@
double maxBelow = 0;
for (int i = 0, maxPos = children.size(); i < maxPos; i++) {
final Node child = children.get(i);
final double childWidth = Double.isNaN(singleChildWidth) ? childWidths[i] : singleChildWidth;
Insets margin = childMargins.call(child);
- final double top = margin != null? snapSpace(margin.getTop()) : 0;
- final double bottom = margin != null? snapSpace(margin.getBottom()) : 0;
+ final double top = margin != null? snapSpaceY(margin.getTop()) : 0;
+ final double bottom = margin != null? snapSpaceY(margin.getBottom()) : 0;
final double baseline = child.getBaselineOffset();
- final double childHeight = minimum? snapSize(child.minHeight(childWidth)) : snapSize(child.prefHeight(childWidth));
+ final double childHeight = minimum? snapSizeY(child.minHeight(childWidth)) : snapSizeY(child.prefHeight(childWidth));
if (baseline == BASELINE_OFFSET_SAME_AS_HEIGHT) {
maxAbove = Math.max(maxAbove, childHeight + top);
} else {
maxAbove = Math.max(maxAbove, baseline + top);
maxBelow = Math.max(maxBelow,
- snapSpace(minimum?snapSize(child.minHeight(childWidth)) : snapSize(child.prefHeight(childWidth))) -
+ snapSpaceY(minimum?snapSizeY(child.minHeight(childWidth)) : snapSizeY(child.prefHeight(childWidth))) -
baseline + bottom);
}
}
return maxAbove + maxBelow; //remind(aim): ceil this value?
} else {
@@ -2060,16 +2243,18 @@
* @since JavaFX 8.0
*/
public static void positionInArea(Node child, double areaX, double areaY, double areaWidth, double areaHeight,
double areaBaselineOffset, Insets margin, HPos halignment, VPos valignment, boolean isSnapToPixel) {
Insets childMargin = margin != null? margin : Insets.EMPTY;
+ double snapScaleX = isSnapToPixel ? getSnapScaleX(child) : 1.0;
+ double snapScaleY = isSnapToPixel ? getSnapScaleY(child) : 1.0;
position(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset,
- snapSpace(childMargin.getTop(), isSnapToPixel),
- snapSpace(childMargin.getRight(), isSnapToPixel),
- snapSpace(childMargin.getBottom(), isSnapToPixel),
- snapSpace(childMargin.getLeft(), isSnapToPixel),
+ snapSpace(childMargin.getTop(), isSnapToPixel, snapScaleY),
+ snapSpace(childMargin.getRight(), isSnapToPixel, snapScaleX),
+ snapSpace(childMargin.getBottom(), isSnapToPixel, snapScaleY),
+ snapSpace(childMargin.getLeft(), isSnapToPixel, snapScaleX),
halignment, valignment, isSnapToPixel);
}
/**
* Utility method which lays out the child within an area of this
@@ -2294,36 +2479,39 @@
double areaBaselineOffset,
Insets margin, boolean fillWidth, boolean fillHeight,
HPos halignment, VPos valignment, boolean isSnapToPixel) {
Insets childMargin = margin != null ? margin : Insets.EMPTY;
+ double snapScaleX = isSnapToPixel ? getSnapScaleX(child) : 1.0;
+ double snapScaleY = isSnapToPixel ? getSnapScaleY(child) : 1.0;
- double top = snapSpace(childMargin.getTop(), isSnapToPixel);
- double bottom = snapSpace(childMargin.getBottom(), isSnapToPixel);
- double left = snapSpace(childMargin.getLeft(), isSnapToPixel);
- double right = snapSpace(childMargin.getRight(), isSnapToPixel);
+ double top = snapSpace(childMargin.getTop(), isSnapToPixel, snapScaleY);
+ double bottom = snapSpace(childMargin.getBottom(), isSnapToPixel, snapScaleY);
+ double left = snapSpace(childMargin.getLeft(), isSnapToPixel, snapScaleX);
+ double right = snapSpace(childMargin.getRight(), isSnapToPixel, snapScaleX);
if (valignment == VPos.BASELINE) {
double bo = child.getBaselineOffset();
if (bo == BASELINE_OFFSET_SAME_AS_HEIGHT) {
if (child.isResizable()) {
// Everything below the baseline is like an "inset". The Node with BASELINE_OFFSET_SAME_AS_HEIGHT cannot
// be resized to this area
- bottom += snapSpace(areaHeight - areaBaselineOffset, isSnapToPixel);
+ bottom += snapSpace(areaHeight - areaBaselineOffset, isSnapToPixel, snapScaleY);
} else {
- top = snapSpace(areaBaselineOffset - child.getLayoutBounds().getHeight(), isSnapToPixel);
+ top = snapSpace(areaBaselineOffset - child.getLayoutBounds().getHeight(), isSnapToPixel, snapScaleY);
}
} else {
- top = snapSpace(areaBaselineOffset - bo, isSnapToPixel);
+ top = snapSpace(areaBaselineOffset - bo, isSnapToPixel, snapScaleY);
}
}
if (child.isResizable()) {
Vec2d size = boundedNodeSizeWithBias(child, areaWidth - left - right, areaHeight - top - bottom,
fillWidth, fillHeight, TEMP_VEC2D);
- child.resize(snapSize(size.x, isSnapToPixel),snapSize(size.y, isSnapToPixel));
+ child.resize(snapSize(size.x, isSnapToPixel, snapScaleX),
+ snapSize(size.y, isSnapToPixel, snapScaleX));
}
position(child, areaX, areaY, areaWidth, areaHeight, areaBaselineOffset,
top, right, bottom, left, halignment, valignment, isSnapToPixel);
}
@@ -2344,12 +2532,16 @@
}
} else {
yoffset = topMargin + computeYOffset(areaHeight - topMargin - bottomMargin,
child.getLayoutBounds().getHeight(), vpos);
}
- final double x = snapPosition(areaX + xoffset, isSnapToPixel);
- final double y = snapPosition(areaY + yoffset, isSnapToPixel);
+ double x = areaX + xoffset;
+ double y = areaY + yoffset;
+ if (isSnapToPixel) {
+ x = snapPosition(x, true, getSnapScaleX(child));
+ y = snapPosition(y, true, getSnapScaleY(child));
+ }
child.relocate(x,y);
}
/**************************************************************************