summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Signell <artur@vaadin.com>2015-06-07 23:06:45 +0300
committerVaadin Code Review <review@vaadin.com>2015-06-12 11:51:16 +0000
commit914eafd5fe7d43290abe0b6b07678df0a8f45ee0 (patch)
treed392d772393791ee6301c6b3e4023c6868b35ef9
parent7f39ad337ec489d58cee6cb99d32f4364a93b1eb (diff)
downloadvaadin-framework-914eafd5fe7d43290abe0b6b07678df0a8f45ee0.tar.gz
vaadin-framework-914eafd5fe7d43290abe0b6b07678df0a8f45ee0.zip
Ensure GridLayout rounds available space down instead of up (#15451)
Store measured widths and heights as doubles to be able to round later Change-Id: Id0e91702dd62ba362f53317e8520f85b46f19769
-rw-r--r--client/src/com/vaadin/client/LayoutManager.java156
-rw-r--r--client/src/com/vaadin/client/MeasuredSize.java34
-rw-r--r--client/src/com/vaadin/client/WidgetUtil.java68
-rw-r--r--client/src/com/vaadin/client/ui/VGridLayout.java12
-rw-r--r--uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutFractionalSizeAndAlignment.java66
-rw-r--r--uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutFractionalSizeAndAlignmentTest.java31
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/ScrollableGridLayoutConnector.java36
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/server/ScrollableGridLayout.java34
8 files changed, 388 insertions, 49 deletions
diff --git a/client/src/com/vaadin/client/LayoutManager.java b/client/src/com/vaadin/client/LayoutManager.java
index 3f189bcea8..102e618f5e 100644
--- a/client/src/com/vaadin/client/LayoutManager.java
+++ b/client/src/com/vaadin/client/LayoutManager.java
@@ -946,7 +946,7 @@ public class LayoutManager {
* given element, provided that it has been measured. These elements are
* guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -954,6 +954,9 @@ public class LayoutManager {
*
* -1 is returned if the element has not been measured. If 0 is returned, it
* might indicate that the element is not attached to the DOM.
+ * <p>
+ * The value returned by this method is always rounded up. To get the exact
+ * outer width, use {@link #getOuterHeightDouble(Element)}
*
* @param element
* the element to get the measured size for
@@ -962,6 +965,31 @@ public class LayoutManager {
*/
public final int getOuterHeight(Element element) {
assert needsMeasure(element) : "Getting measurement for element that is not measured";
+ return (int) Math.ceil(getMeasuredSize(element, nullSize)
+ .getOuterHeight());
+ }
+
+ /**
+ * Gets the outer height (including margins, paddings and borders) of the
+ * given element, provided that it has been measured. These elements are
+ * guaranteed to be measured:
+ * <ul>
+ * <li>ManagedLayouts and their child Connectors
+ * <li>Elements for which there is at least one ElementResizeListener
+ * <li>Elements for which at least one ManagedLayout has registered a
+ * dependency
+ * </ul>
+ *
+ * -1 is returned if the element has not been measured. If 0 is returned, it
+ * might indicate that the element is not attached to the DOM.
+ *
+ * @param element
+ * the element to get the measured size for
+ * @return the measured outer height (including margins, paddings and
+ * borders) of the element in pixels.
+ */
+ public final double getOuterHeightDouble(Element element) {
+ assert needsMeasure(element) : "Getting measurement for element that is not measured";
return getMeasuredSize(element, nullSize).getOuterHeight();
}
@@ -970,7 +998,7 @@ public class LayoutManager {
* given element, provided that it has been measured. These elements are
* guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -978,6 +1006,9 @@ public class LayoutManager {
*
* -1 is returned if the element has not been measured. If 0 is returned, it
* might indicate that the element is not attached to the DOM.
+ * <p>
+ * The value returned by this method is always rounded up. To get the exact
+ * outer width, use {@link #getOuterWidthDouble(Element)}
*
* @param element
* the element to get the measured size for
@@ -986,6 +1017,31 @@ public class LayoutManager {
*/
public final int getOuterWidth(Element element) {
assert needsMeasure(element) : "Getting measurement for element that is not measured";
+ return (int) Math.ceil(getMeasuredSize(element, nullSize)
+ .getOuterWidth());
+ }
+
+ /**
+ * Gets the outer width (including margins, paddings and borders) of the
+ * given element, provided that it has been measured. These elements are
+ * guaranteed to be measured:
+ * <ul>
+ * <li>ManagedLayouts and their child Connectors
+ * <li>Elements for which there is at least one ElementResizeListener
+ * <li>Elements for which at least one ManagedLayout has registered a
+ * dependency
+ * </ul>
+ *
+ * -1 is returned if the element has not been measured. If 0 is returned, it
+ * might indicate that the element is not attached to the DOM.
+ *
+ * @param element
+ * the element to get the measured size for
+ * @return the measured outer width (including margins, paddings and
+ * borders) of the element in pixels.
+ */
+ public final double getOuterWidthDouble(Element element) {
+ assert needsMeasure(element) : "Getting measurement for element that is not measured";
return getMeasuredSize(element, nullSize).getOuterWidth();
}
@@ -994,7 +1050,7 @@ public class LayoutManager {
* given element, provided that it has been measured. These elements are
* guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1002,6 +1058,9 @@ public class LayoutManager {
*
* -1 is returned if the element has not been measured. If 0 is returned, it
* might indicate that the element is not attached to the DOM.
+ * <p>
+ * The value returned by this method is always rounded up. To get the exact
+ * outer width, use {@link #getInnerHeightDouble(Element)}
*
* @param element
* the element to get the measured size for
@@ -1010,6 +1069,31 @@ public class LayoutManager {
*/
public final int getInnerHeight(Element element) {
assert needsMeasure(element) : "Getting measurement for element that is not measured";
+ return (int) Math.ceil(getMeasuredSize(element, nullSize)
+ .getInnerHeight());
+ }
+
+ /**
+ * Gets the inner height (excluding margins, paddings and borders) of the
+ * given element, provided that it has been measured. These elements are
+ * guaranteed to be measured:
+ * <ul>
+ * <li>ManagedLayouts and their child Connectors
+ * <li>Elements for which there is at least one ElementResizeListener
+ * <li>Elements for which at least one ManagedLayout has registered a
+ * dependency
+ * </ul>
+ *
+ * -1 is returned if the element has not been measured. If 0 is returned, it
+ * might indicate that the element is not attached to the DOM.
+ *
+ * @param element
+ * the element to get the measured size for
+ * @return the measured inner height (excluding margins, paddings and
+ * borders) of the element in pixels.
+ */
+ public final double getInnerHeightDouble(Element element) {
+ assert needsMeasure(element) : "Getting measurement for element that is not measured";
return getMeasuredSize(element, nullSize).getInnerHeight();
}
@@ -1018,7 +1102,7 @@ public class LayoutManager {
* given element, provided that it has been measured. These elements are
* guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1026,6 +1110,9 @@ public class LayoutManager {
*
* -1 is returned if the element has not been measured. If 0 is returned, it
* might indicate that the element is not attached to the DOM.
+ * <p>
+ * The value returned by this method is always rounded up. To get the exact
+ * outer width, use {@link #getOuterHeightDouble(Element)}
*
* @param element
* the element to get the measured size for
@@ -1034,6 +1121,31 @@ public class LayoutManager {
*/
public final int getInnerWidth(Element element) {
assert needsMeasure(element) : "Getting measurement for element that is not measured";
+ return (int) Math.ceil(getMeasuredSize(element, nullSize)
+ .getInnerWidth());
+ }
+
+ /**
+ * Gets the inner width (excluding margins, paddings and borders) of the
+ * given element, provided that it has been measured. These elements are
+ * guaranteed to be measured:
+ * <ul>
+ * <li>ManagedLayouts and their child Connectors
+ * <li>Elements for which there is at least one ElementResizeListener
+ * <li>Elements for which at least one ManagedLayout has registered a
+ * dependency
+ * </ul>
+ *
+ * -1 is returned if the element has not been measured. If 0 is returned, it
+ * might indicate that the element is not attached to the DOM.
+ *
+ * @param element
+ * the element to get the measured size for
+ * @return the measured inner width (excluding margins, paddings and
+ * borders) of the element in pixels.
+ */
+ public final double getInnerWidthDouble(Element element) {
+ assert needsMeasure(element) : "Getting measurement for element that is not measured";
return getMeasuredSize(element, nullSize).getInnerWidth();
}
@@ -1042,7 +1154,7 @@ public class LayoutManager {
* provided that it has been measured. These elements are guaranteed to be
* measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1067,7 +1179,7 @@ public class LayoutManager {
* element, provided that it has been measured. These elements are
* guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1092,7 +1204,7 @@ public class LayoutManager {
* provided that it has been measured. These elements are guaranteed to be
* measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1116,7 +1228,7 @@ public class LayoutManager {
* Gets the top border of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1139,7 +1251,7 @@ public class LayoutManager {
* Gets the left border of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1162,7 +1274,7 @@ public class LayoutManager {
* Gets the bottom border of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1185,7 +1297,7 @@ public class LayoutManager {
* Gets the right border of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1209,7 +1321,7 @@ public class LayoutManager {
* element, provided that it has been measured. These elements are
* guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1233,7 +1345,7 @@ public class LayoutManager {
* Gets the top padding of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1256,7 +1368,7 @@ public class LayoutManager {
* Gets the left padding of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1279,7 +1391,7 @@ public class LayoutManager {
* Gets the bottom padding of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1302,7 +1414,7 @@ public class LayoutManager {
* Gets the right padding of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1325,7 +1437,7 @@ public class LayoutManager {
* Gets the top margin of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1348,7 +1460,7 @@ public class LayoutManager {
* Gets the right margin of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1371,7 +1483,7 @@ public class LayoutManager {
* Gets the bottom margin of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1394,7 +1506,7 @@ public class LayoutManager {
* Gets the left margin of the given element, provided that it has been
* measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1417,7 +1529,7 @@ public class LayoutManager {
* Gets the combined top & bottom margin of the given element, provided that
* they have been measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
@@ -1439,7 +1551,7 @@ public class LayoutManager {
* Gets the combined left & right margin of the given element, provided that
* they have been measured. These elements are guaranteed to be measured:
* <ul>
- * <li>ManagedLayotus and their child Connectors
+ * <li>ManagedLayouts and their child Connectors
* <li>Elements for which there is at least one ElementResizeListener
* <li>Elements for which at least one ManagedLayout has registered a
* dependency
diff --git a/client/src/com/vaadin/client/MeasuredSize.java b/client/src/com/vaadin/client/MeasuredSize.java
index ba8fca417b..2099008350 100644
--- a/client/src/com/vaadin/client/MeasuredSize.java
+++ b/client/src/com/vaadin/client/MeasuredSize.java
@@ -45,8 +45,8 @@ public class MeasuredSize {
}
}
- private int width = -1;
- private int height = -1;
+ private double width = -1;
+ private double height = -1;
private int[] paddings = new int[4];
private int[] borders = new int[4];
@@ -54,11 +54,11 @@ public class MeasuredSize {
private FastStringSet dependents = FastStringSet.create();
- public int getOuterHeight() {
+ public double getOuterHeight() {
return height;
}
- public int getOuterWidth() {
+ public double getOuterWidth() {
return width;
}
@@ -86,17 +86,17 @@ public class MeasuredSize {
return sizes[0] + sizes[2];
}
- public int getInnerHeight() {
+ public double getInnerHeight() {
return height - sumHeights(margins) - sumHeights(borders)
- sumHeights(paddings);
}
- public int getInnerWidth() {
+ public double getInnerWidth() {
return width - sumWidths(margins) - sumWidths(borders)
- sumWidths(paddings);
}
- public boolean setOuterHeight(int height) {
+ public boolean setOuterHeight(double height) {
if (this.height != height) {
this.height = height;
return true;
@@ -105,7 +105,7 @@ public class MeasuredSize {
}
}
- public boolean setOuterWidth(int width) {
+ public boolean setOuterWidth(double width) {
if (this.width != width) {
this.width = width;
return true;
@@ -238,20 +238,20 @@ public class MeasuredSize {
Profiler.leave("Measure borders");
Profiler.enter("Measure height");
- int requiredHeight = WidgetUtil.getRequiredHeight(element);
- int marginHeight = sumHeights(margins);
- int oldHeight = height;
- int oldWidth = width;
- if (setOuterHeight(requiredHeight + marginHeight)) {
+ double requiredHeight = WidgetUtil.getRequiredHeightDouble(element);
+ double outerHeight = requiredHeight + sumHeights(margins);
+ double oldHeight = height;
+ if (setOuterHeight(outerHeight)) {
debugSizeChange(element, "Height (outer)", oldHeight, height);
heightChanged = true;
}
Profiler.leave("Measure height");
Profiler.enter("Measure width");
- int requiredWidth = WidgetUtil.getRequiredWidth(element);
- int marginWidth = sumWidths(margins);
- if (setOuterWidth(requiredWidth + marginWidth)) {
+ double requiredWidth = WidgetUtil.getRequiredWidthDouble(element);
+ double outerWidth = requiredWidth + sumWidths(margins);
+ double oldWidth = width;
+ if (setOuterWidth(outerWidth)) {
debugSizeChange(element, "Width (outer)", oldWidth, width);
widthChanged = true;
}
@@ -270,7 +270,7 @@ public class MeasuredSize {
}
private void debugSizeChange(Element element, String sizeChangeType,
- int changedFrom, int changedTo) {
+ double changedFrom, double changedTo) {
debugSizeChange(element, sizeChangeType, String.valueOf(changedFrom),
String.valueOf(changedTo));
}
diff --git a/client/src/com/vaadin/client/WidgetUtil.java b/client/src/com/vaadin/client/WidgetUtil.java
index e89e875953..fca6fbccbc 100644
--- a/client/src/com/vaadin/client/WidgetUtil.java
+++ b/client/src/com/vaadin/client/WidgetUtil.java
@@ -541,6 +541,29 @@ public class WidgetUtil {
}
/**
+ * Gets the border-box width for the given element, i.e. element width +
+ * border + padding.
+ *
+ * @param element
+ * The element to check
+ * @return The border-box width for the element
+ */
+ public static double getRequiredWidthDouble(
+ com.google.gwt.dom.client.Element element) {
+ double reqWidth = getRequiredWidthBoundingClientRectDouble(element);
+ if (BrowserInfo.get().isIE() && !BrowserInfo.get().isIE8()) {
+ double csWidth = getRequiredWidthComputedStyleDouble(element);
+ if (csWidth > reqWidth && csWidth < (reqWidth + 1)) {
+ // IE9 rounds reqHeight to integers BUT sometimes reports wrong
+ // csHeight it seems, so we only use csHeight if it is within a
+ // rounding error
+ return csWidth;
+ }
+ }
+ return reqWidth;
+ }
+
+ /**
* Gets the border-box height for the given element, i.e. element height +
* border + padding. Always rounds up to nearest integer.
*
@@ -567,6 +590,29 @@ public class WidgetUtil {
}
/**
+ * Gets the border-box height for the given element, i.e. element height +
+ * border + padding.
+ *
+ * @param element
+ * The element to check
+ * @return The border-box height for the element
+ */
+ public static double getRequiredHeightDouble(
+ com.google.gwt.dom.client.Element element) {
+ double reqHeight = getRequiredHeightBoundingClientRectDouble(element);
+ if (BrowserInfo.get().isIE() && !BrowserInfo.get().isIE8()) {
+ double csHeight = getRequiredHeightComputedStyleDouble(element);
+ if (csHeight > reqHeight && csHeight < (reqHeight + 1)) {
+ // IE9 rounds reqHeight to integers BUT sometimes reports wrong
+ // csHeight it seems, so we only use csHeight if it is within a
+ // rounding error
+ return csHeight;
+ }
+ }
+ return reqHeight;
+ }
+
+ /**
* Calculates the width of the element's bounding rectangle.
* <p>
* In case the browser doesn't support bounding rectangles, the returned
@@ -605,34 +651,44 @@ public class WidgetUtil {
}
}-*/;
- public static native int getRequiredHeightComputedStyle(
+ public static int getRequiredHeightComputedStyle(
+ com.google.gwt.dom.client.Element element) {
+ return (int) Math.ceil(getRequiredHeightComputedStyleDouble(element));
+ }
+
+ public static native double getRequiredHeightComputedStyleDouble(
com.google.gwt.dom.client.Element element)
/*-{
var cs = element.ownerDocument.defaultView.getComputedStyle(element);
var heightPx = cs.height;
if(heightPx == 'auto'){
// Fallback for inline elements
- return @com.vaadin.client.WidgetUtil::getRequiredHeightBoundingClientRect(Lcom/google/gwt/dom/client/Element;)(element);
+ return @com.vaadin.client.WidgetUtil::getRequiredHeightBoundingClientRectDouble(Lcom/google/gwt/dom/client/Element;)(element);
}
var height = parseFloat(heightPx); // Will automatically skip "px" suffix
var border = parseFloat(cs.borderTopWidth) + parseFloat(cs.borderBottomWidth); // Will automatically skip "px" suffix
var padding = parseFloat(cs.paddingTop) + parseFloat(cs.paddingBottom); // Will automatically skip "px" suffix
- return Math.ceil(height+border+padding);
+ return height+border+padding;
}-*/;
- public static native int getRequiredWidthComputedStyle(
+ public static int getRequiredWidthComputedStyle(
+ com.google.gwt.dom.client.Element element) {
+ return (int) Math.ceil(getRequiredWidthComputedStyleDouble(element));
+ }
+
+ public static native int getRequiredWidthComputedStyleDouble(
com.google.gwt.dom.client.Element element)
/*-{
var cs = element.ownerDocument.defaultView.getComputedStyle(element);
var widthPx = cs.width;
if(widthPx == 'auto'){
// Fallback for inline elements
- return @com.vaadin.client.WidgetUtil::getRequiredWidthBoundingClientRect(Lcom/google/gwt/dom/client/Element;)(element);
+ return @com.vaadin.client.WidgetUtil::getRequiredWidthBoundingClientRectDouble(Lcom/google/gwt/dom/client/Element;)(element);
}
var width = parseFloat(widthPx); // Will automatically skip "px" suffix
var border = parseFloat(cs.borderLeftWidth) + parseFloat(cs.borderRightWidth); // Will automatically skip "px" suffix
var padding = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight); // Will automatically skip "px" suffix
- return Math.ceil(width+border+padding);
+ return width+border+padding;
}-*/;
/**
diff --git a/client/src/com/vaadin/client/ui/VGridLayout.java b/client/src/com/vaadin/client/ui/VGridLayout.java
index d1e055eb5d..0c1d4cec90 100644
--- a/client/src/com/vaadin/client/ui/VGridLayout.java
+++ b/client/src/com/vaadin/client/ui/VGridLayout.java
@@ -143,8 +143,10 @@ public class VGridLayout extends ComplexPanel {
if (!isUndefinedHeight()) {
int usedSpace = calcRowUsedSpace();
int[] actualExpandRatio = calcRowExpandRatio();
- int availableSpace = LayoutManager.get(client).getInnerHeight(
- getElement());
+ // Round down to avoid problems with fractions (100.1px available ->
+ // can use 100, not 101)
+ int availableSpace = (int) LayoutManager.get(client)
+ .getInnerHeightDouble(getElement());
int excessSpace = availableSpace - usedSpace;
int distributed = 0;
if (excessSpace > 0) {
@@ -223,8 +225,10 @@ public class VGridLayout extends ComplexPanel {
if (!isUndefinedWidth()) {
int usedSpace = calcColumnUsedSpace();
int[] actualExpandRatio = calcColumnExpandRatio();
- int availableSpace = LayoutManager.get(client).getInnerWidth(
- getElement());
+ // Round down to avoid problems with fractions (100.1px available ->
+ // can use 100, not 101)
+ int availableSpace = (int) LayoutManager.get(client)
+ .getInnerWidthDouble(getElement());
int excessSpace = availableSpace - usedSpace;
int distributed = 0;
if (excessSpace > 0) {
diff --git a/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutFractionalSizeAndAlignment.java b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutFractionalSizeAndAlignment.java
new file mode 100644
index 0000000000..32d01f9910
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutFractionalSizeAndAlignment.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.gridlayout;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.tests.widgetset.TestingWidgetSet;
+import com.vaadin.tests.widgetset.server.ScrollableGridLayout;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.GridLayout;
+
+@Widgetset(TestingWidgetSet.NAME)
+public class GridLayoutFractionalSizeAndAlignment extends AbstractTestUIWithLog {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ widthTest();
+ heightTest();
+ }
+
+ private void widthTest() {
+ final GridLayout layout = new ScrollableGridLayout(1, 1);
+ layout.setMargin(false);
+ layout.setSpacing(true);
+
+ layout.setWidth(525.04f, Unit.PIXELS);
+
+ Button button = new Button("Button");
+
+ layout.addComponent(button);
+ layout.setComponentAlignment(button, Alignment.BOTTOM_RIGHT);
+
+ addComponent(layout);
+ }
+
+ private void heightTest() {
+ final GridLayout layout = new ScrollableGridLayout(1, 1);
+ layout.setMargin(false);
+ layout.setSpacing(true);
+
+ layout.setWidth(525.04f, Unit.PIXELS);
+ layout.setHeight(525.04f, Unit.PIXELS);
+
+ Button button = new Button("Button");
+
+ layout.addComponent(button);
+ layout.setComponentAlignment(button, Alignment.BOTTOM_RIGHT);
+
+ addComponent(layout);
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutFractionalSizeAndAlignmentTest.java b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutFractionalSizeAndAlignmentTest.java
new file mode 100644
index 0000000000..b60aea49f0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/gridlayout/GridLayoutFractionalSizeAndAlignmentTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.gridlayout;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+public class GridLayoutFractionalSizeAndAlignmentTest extends MultiBrowserTest {
+
+ @Test
+ public void ensureNoScrollbarsWithAlignBottomRight() throws IOException {
+ openTestURL();
+ compareScreen("noscrollbars");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/ScrollableGridLayoutConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/ScrollableGridLayoutConnector.java
new file mode 100644
index 0000000000..d6431ac9f9
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/client/ScrollableGridLayoutConnector.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.client;
+
+import com.vaadin.client.ConnectorHierarchyChangeEvent;
+import com.vaadin.client.ui.VGridLayout;
+import com.vaadin.client.ui.gridlayout.GridLayoutConnector;
+import com.vaadin.client.ui.layout.MayScrollChildren;
+import com.vaadin.shared.ui.Connect;
+import com.vaadin.tests.widgetset.server.ScrollableGridLayout;
+
+@Connect(ScrollableGridLayout.class)
+public class ScrollableGridLayoutConnector extends GridLayoutConnector
+ implements MayScrollChildren {
+ @Override
+ public void onConnectorHierarchyChange(ConnectorHierarchyChangeEvent event) {
+ super.onConnectorHierarchyChange(event);
+
+ for (VGridLayout.Cell cell : getWidget().widgetToCell.values()) {
+ cell.slot.getWrapperElement().addClassName("v-scrollable");
+ }
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/widgetset/server/ScrollableGridLayout.java b/uitest/src/com/vaadin/tests/widgetset/server/ScrollableGridLayout.java
new file mode 100644
index 0000000000..6958172aa8
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/widgetset/server/ScrollableGridLayout.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.widgetset.server;
+
+import com.vaadin.ui.Component;
+import com.vaadin.ui.GridLayout;
+
+public class ScrollableGridLayout extends GridLayout {
+
+ public ScrollableGridLayout() {
+ super();
+ }
+
+ public ScrollableGridLayout(int columns, int rows, Component... children) {
+ super(columns, rows, children);
+ }
+
+ public ScrollableGridLayout(int columns, int rows) {
+ super(columns, rows);
+ }
+}