aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHenrik Paul <henrik@vaadin.com>2014-03-18 16:36:10 +0200
committerLeif Åstrand <leif@vaadin.com>2014-03-19 09:48:46 +0000
commit9b510d35a7ec6b1a9504343b2620110b77d4e5c3 (patch)
tree9d14304ee02cebf2db72d21432fd67c0161a7591
parentead73d97e402eea6a78c6f0a7e5cacf0bd9a0982 (diff)
downloadvaadin-framework-9b510d35a7ec6b1a9504343b2620110b77d4e5c3.tar.gz
vaadin-framework-9b510d35a7ec6b1a9504343b2620110b77d4e5c3.zip
Adds setHeightByRow support to Grid (#13297)
Change-Id: I67f1bfb476a8af28c0ea1a03758684ca42d1ba48
-rw-r--r--client/src/com/vaadin/client/ui/grid/Escalator.java176
-rw-r--r--client/src/com/vaadin/client/ui/grid/Grid.java87
-rw-r--r--client/src/com/vaadin/client/ui/grid/GridConnector.java14
-rw-r--r--client/src/com/vaadin/client/ui/grid/ScrollbarBundle.java93
-rw-r--r--server/src/com/vaadin/ui/components/grid/Grid.java99
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/GridState.java24
-rw-r--r--shared/src/com/vaadin/shared/ui/grid/HeightMode.java42
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridBasicFeatures.java39
8 files changed, 565 insertions, 9 deletions
diff --git a/client/src/com/vaadin/client/ui/grid/Escalator.java b/client/src/com/vaadin/client/ui/grid/Escalator.java
index 6112d6b139..b0d1047ff4 100644
--- a/client/src/com/vaadin/client/ui/grid/Escalator.java
+++ b/client/src/com/vaadin/client/ui/grid/Escalator.java
@@ -54,6 +54,8 @@ import com.vaadin.client.ui.grid.PositionFunction.TranslatePosition;
import com.vaadin.client.ui.grid.PositionFunction.WebkitTranslate3DPosition;
import com.vaadin.client.ui.grid.ScrollbarBundle.HorizontalScrollbarBundle;
import com.vaadin.client.ui.grid.ScrollbarBundle.VerticalScrollbarBundle;
+import com.vaadin.shared.ui.grid.GridState;
+import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.shared.ui.grid.Range;
import com.vaadin.shared.ui.grid.ScrollDestination;
import com.vaadin.shared.util.SharedUtil;
@@ -1762,12 +1764,14 @@ public class Escalator extends Widget {
public void insertRows(int index, int numberOfRows) {
super.insertRows(index, numberOfRows);
recalculateElementSizes();
+ applyHeightByRows();
}
@Override
public void removeRows(int index, int numberOfRows) {
super.removeRows(index, numberOfRows);
recalculateElementSizes();
+ applyHeightByRows();
}
@Override
@@ -3497,6 +3501,14 @@ public class Escalator extends Widget {
/** The cached height of the escalator, in pixels. */
private double heightOfEscalator;
+ /** The height of Escalator in terms of body rows. */
+ private double heightByRows = GridState.DEFAULT_HEIGHT_BY_ROWS;
+
+ /** The height of Escalator, as defined by {@link #setHeight(String)} */
+ private String heightByCss = "";
+
+ private HeightMode heightMode = HeightMode.CSS;
+
private static native double getPreciseWidth(Element element)
/*-{
if (element.getBoundingClientRect) {
@@ -3531,10 +3543,23 @@ public class Escalator extends Widget {
setElement(root);
root.appendChild(verticalScrollbar.getElement());
- root.appendChild(horizontalScrollbar.getElement());
verticalScrollbar.setScrollbarThickness(Util.getNativeScrollbarSize());
+
+ root.appendChild(horizontalScrollbar.getElement());
horizontalScrollbar
.setScrollbarThickness(Util.getNativeScrollbarSize());
+ horizontalScrollbar
+ .addVisibilityHandler(new ScrollbarBundle.VisibilityHandler() {
+ @Override
+ public void visibilityChanged(
+ ScrollbarBundle.VisibilityChangeEvent event) {
+ /*
+ * We either lost or gained a scrollbar. In any case, we
+ * need to change the height, if it's defined by rows.
+ */
+ applyHeightByRows();
+ }
+ });
tableWrapper = DOM.createDiv();
@@ -3692,10 +3717,6 @@ public class Escalator extends Widget {
return columnConfiguration;
}
- /*
- * TODO remove method once RequiresResize and the Vaadin layoutmanager
- * listening mechanisms are implemented (https://trello.com/c/r3Kh0Kfy)
- */
@Override
public void setWidth(final String width) {
super.setWidth(width != null && !width.isEmpty() ? width
@@ -3703,12 +3724,28 @@ public class Escalator extends Widget {
recalculateElementSizes();
}
- /*
- * TODO remove method once RequiresResize and the Vaadin layoutmanager
- * listening mechanisms are implemented (https://trello.com/c/r3Kh0Kfy)
+ /**
+ * {@inheritDoc}
+ * <p>
+ * If Escalator is currently not in {@link HeightMode#CSS}, the given value
+ * is remembered, and applied once the mode is applied.
+ *
+ * @see #setHeightMode(HeightMode)
*/
@Override
- public void setHeight(final String height) {
+ public void setHeight(String height) {
+ /*
+ * TODO remove method once RequiresResize and the Vaadin layoutmanager
+ * listening mechanisms are implemented
+ */
+
+ heightByCss = height;
+ if (getHeightMode() == HeightMode.CSS) {
+ setHeightInternal(height);
+ }
+ }
+
+ private void setHeightInternal(final String height) {
final int escalatorRowsBefore = body.visualRowOrder.size();
super.setHeight(height != null && !height.isEmpty() ? height
@@ -4039,4 +4076,125 @@ public class Escalator extends Widget {
body.setStylePrimaryName(style);
footer.setStylePrimaryName(style);
}
+
+ /**
+ * Sets the number of rows that should be visible in Escalator's body, while
+ * {@link #getHeightMode()} is {@link HeightMode#ROW}.
+ * <p>
+ * If Escalator is currently not in {@link HeightMode#ROW}, the given value
+ * is remembered, and applied once the mode is applied.
+ *
+ * @param rows
+ * the number of rows that should be visible in Escalator's body
+ * @throws IllegalArgumentException
+ * if {@code rows} is zero or less
+ * @throws IllegalArgumentException
+ * if {@code rows} is {@link Double#isInifinite(double)
+ * infinite}
+ * @throws IllegalArgumentException
+ * if {@code rows} is {@link Double#isNaN(double) NaN}.
+ * @see #setHeightMode(HeightMode)
+ */
+ public void setHeightByRows(double rows) throws IllegalArgumentException {
+ if (rows <= 0) {
+ throw new IllegalArgumentException(
+ "The number of rows must be a positive number.");
+ } else if (Double.isInfinite(rows)) {
+ throw new IllegalArgumentException(
+ "The number of rows must be finite.");
+ } else if (Double.isNaN(rows)) {
+ throw new IllegalArgumentException("The number must not be NaN.");
+ }
+
+ heightByRows = rows;
+ applyHeightByRows();
+ }
+
+ /**
+ * Gets the amount of rows in Escalator's body that are shown, while
+ * {@link #getHeightMode()} is {@link HeightMode#ROW}.
+ * <p>
+ * By default, it is {@value #DEFAULT_HEIGHT_BY_ROWS}.
+ *
+ * @return the amount of rows that are being shown in Escalator's body
+ * @see #setHeightByRows(double)
+ */
+ public double getHeightByRows() {
+ return heightByRows;
+ }
+
+ /**
+ * Reapplies the row-based height of the Grid, if Grid currently should
+ * define its height that way.
+ */
+ private void applyHeightByRows() {
+ if (heightMode != HeightMode.ROW) {
+ return;
+ }
+
+ double headerHeight = header.heightOfSection;
+ double footerHeight = footer.heightOfSection;
+ double bodyHeight = body.getDefaultRowHeight() * heightByRows;
+ double scrollbar = horizontalScrollbar.showsScrollHandle() ? horizontalScrollbar
+ .getScrollbarThickness() : 0;
+
+ double totalHeight = headerHeight + bodyHeight + scrollbar
+ + footerHeight;
+ setHeightInternal(totalHeight + "px");
+ }
+
+ /**
+ * Defines the mode in which the Escalator widget's height is calculated.
+ * <p>
+ * If {@link HeightMode#CSS} is given, Escalator will respect the values
+ * given via {@link #setHeight(String)}, and behave as a traditional Widget.
+ * <p>
+ * If {@link HeightMode#ROW} is given, Escalator will make sure that the
+ * {@link #getBody() body} will display as many rows as
+ * {@link #getHeightByRows()} defines. <em>Note:</em> If headers/footers are
+ * inserted or removed, the widget will resize itself to still display the
+ * required amount of rows in its body. It also takes the horizontal
+ * scrollbar into account.
+ *
+ * @param heightMode
+ * the mode in to which Escalator should be set
+ */
+ public void setHeightMode(HeightMode heightMode) {
+ /*
+ * This method is a workaround for the fact that Vaadin re-applies
+ * widget dimensions (height/width) on each state change event. The
+ * original design was to have setHeight an setHeightByRow be equals,
+ * and whichever was called the latest was considered in effect.
+ *
+ * But, because of Vaadin always calling setHeight on the widget, this
+ * approach doesn't work.
+ */
+
+ if (heightMode != this.heightMode) {
+ this.heightMode = heightMode;
+
+ switch (this.heightMode) {
+ case CSS:
+ setHeight(heightByCss);
+ break;
+ case ROW:
+ setHeightByRows(heightByRows);
+ break;
+ default:
+ throw new IllegalStateException("Unimplemented feaure "
+ + "- unknown HeightMode: " + this.heightMode);
+ }
+ }
+ }
+
+ /**
+ * Returns the current {@link HeightMode} the Escalator is in.
+ * <p>
+ * Defaults to {@link HeightMode#CSS}.
+ *
+ * @return the current HeightMode
+ */
+ public HeightMode getHeightMode() {
+ return heightMode;
+ }
}
diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java
index 02aa194655..ba953c62be 100644
--- a/client/src/com/vaadin/client/ui/grid/Grid.java
+++ b/client/src/com/vaadin/client/ui/grid/Grid.java
@@ -30,6 +30,7 @@ import com.vaadin.client.data.DataChangeHandler;
import com.vaadin.client.data.DataSource;
import com.vaadin.client.ui.grid.renderers.TextRenderer;
import com.vaadin.shared.ui.grid.GridConstants;
+import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.shared.ui.grid.ScrollDestination;
import com.vaadin.shared.util.SharedUtil;
@@ -1116,6 +1117,14 @@ public class Grid<T> extends Composite {
return null;
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * <em>Note:</em> This method will change the widget's size in the browser
+ * only if {@link #getHeightMode()} returns {@link HeightMode#CSS}.
+ *
+ * @see #setHeightMode(HeightMode)
+ */
@Override
public void setHeight(String height) {
escalator.setHeight(height);
@@ -1315,4 +1324,82 @@ public class Grid<T> extends Composite {
return Logger.getLogger(Grid.class.getName());
}
+ /**
+ * Sets the number of rows that should be visible in Grid's body, while
+ * {@link #getHeightMode()} is {@link HeightMode#ROW}.
+ * <p>
+ * If Grid is currently not in {@link HeightMode#ROW}, the given value is
+ * remembered, and applied once the mode is applied.
+ *
+ * @param rows
+ * The height in terms of number of rows displayed in Grid's
+ * body. If Grid doesn't contain enough rows, white space is
+ * displayed instead.
+ * @throws IllegalArgumentException
+ * if {@code rows} is zero or less
+ * @throws IllegalArgumentException
+ * if {@code rows} is {@link Double#isInifinite(double)
+ * infinite}
+ * @throws IllegalArgumentException
+ * if {@code rows} is {@link Double#isNaN(double) NaN}
+ *
+ * @see #setHeightMode(HeightMode)
+ */
+ public void setHeightByRows(double rows) throws IllegalArgumentException {
+ escalator.setHeightByRows(rows);
+ }
+
+ /**
+ * Gets the amount of rows in Grid's body that are shown, while
+ * {@link #getHeightMode()} is {@link HeightMode#ROW}.
+ * <p>
+ * By default, it is {@value Escalator#DEFAULT_HEIGHT_BY_ROWS}.
+ *
+ * @return the amount of rows that should be shown in Grid's body, while in
+ * {@link HeightMode#ROW}.
+ * @see #setHeightByRows(double)
+ */
+ public double getHeightByRows() {
+ return escalator.getHeightByRows();
+ }
+
+ /**
+ * Defines the mode in which the Grid widget's height is calculated.
+ * <p>
+ * If {@link HeightMode#CSS} is given, Grid will respect the values given
+ * via {@link #setHeight(String)}, and behave as a traditional Widget.
+ * <p>
+ * If {@link HeightMode#ROW} is given, Grid will make sure that the body
+ * will display as many rows as {@link #getHeightByRows()} defines.
+ * <em>Note:</em> If headers/footers are inserted or removed, the widget
+ * will resize itself to still display the required amount of rows in its
+ * body. It also takes the horizontal scrollbar into account.
+ *
+ * @param heightMode
+ * the mode in to which Grid should be set
+ */
+ public void setHeightMode(HeightMode heightMode) {
+ /*
+ * This method is a workaround for the fact that Vaadin re-applies
+ * widget dimensions (height/width) on each state change event. The
+ * original design was to have setHeight an setHeightByRow be equals,
+ * and whichever was called the latest was considered in effect.
+ *
+ * But, because of Vaadin always calling setHeight on the widget, this
+ * approach doesn't work.
+ */
+
+ escalator.setHeightMode(heightMode);
+ }
+
+ /**
+ * Returns the current {@link HeightMode} the Grid is in.
+ * <p>
+ * Defaults to {@link HeightMode#CSS}.
+ *
+ * @return the current HeightMode
+ */
+ public HeightMode getHeightMode() {
+ return escalator.getHeightMode();
+ }
}
diff --git a/client/src/com/vaadin/client/ui/grid/GridConnector.java b/client/src/com/vaadin/client/ui/grid/GridConnector.java
index f86c6c420d..e862097009 100644
--- a/client/src/com/vaadin/client/ui/grid/GridConnector.java
+++ b/client/src/com/vaadin/client/ui/grid/GridConnector.java
@@ -167,6 +167,20 @@ public class GridConnector extends AbstractComponentConnector {
getWidget().setLastFrozenColumn(null);
}
}
+
+ /*
+ * @DelegateToWidget annotation doesn't work because of
+ * http://dev.vaadin.com/ticket/12900. Remove manual code and uncomment
+ * annotations at GridState once fixed.
+ */
+
+ if (stateChangeEvent.hasPropertyChanged("heightByRows")) {
+ getWidget().setHeightByRows(getState().heightByRows);
+ }
+
+ if (stateChangeEvent.hasPropertyChanged("heightMode")) {
+ getWidget().setHeightMode(getState().heightMode);
+ }
}
/**
diff --git a/client/src/com/vaadin/client/ui/grid/ScrollbarBundle.java b/client/src/com/vaadin/client/ui/grid/ScrollbarBundle.java
index b9267178c1..21935df4e6 100644
--- a/client/src/com/vaadin/client/ui/grid/ScrollbarBundle.java
+++ b/client/src/com/vaadin/client/ui/grid/ScrollbarBundle.java
@@ -19,6 +19,10 @@ package com.vaadin.client.ui.grid;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Unit;
+import com.google.gwt.event.shared.EventHandler;
+import com.google.gwt.event.shared.GwtEvent;
+import com.google.gwt.event.shared.HandlerManager;
+import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
/**
@@ -33,6 +37,57 @@ import com.google.gwt.user.client.DOM;
abstract class ScrollbarBundle {
/**
+ * A means to listen to when the scrollbar handle in a
+ * {@link ScrollbarBundle} either appears or is removed.
+ */
+ public interface VisibilityHandler extends EventHandler {
+ /**
+ * This method is called whenever the scrollbar handle's visibility is
+ * changed in a {@link ScrollbarBundle}.
+ *
+ * @param event
+ * the {@link VisibilityChangeEvent}
+ */
+ void visibilityChanged(VisibilityChangeEvent event);
+ }
+
+ public static class VisibilityChangeEvent extends
+ GwtEvent<VisibilityHandler> {
+ public static final Type<VisibilityHandler> TYPE = new Type<ScrollbarBundle.VisibilityHandler>() {
+ @Override
+ public String toString() {
+ return "VisibilityChangeEvent";
+ }
+ };
+
+ private final boolean isScrollerVisible;
+
+ private VisibilityChangeEvent(boolean isScrollerVisible) {
+ this.isScrollerVisible = isScrollerVisible;
+ }
+
+ /**
+ * Checks whether the scroll handle is currently visible or not
+ *
+ * @return <code>true</code> if the scroll handle is currently visible.
+ * <code>false</code> if not.
+ */
+ public boolean isScrollerVisible() {
+ return isScrollerVisible;
+ }
+
+ @Override
+ public Type<VisibilityHandler> getAssociatedType() {
+ return TYPE;
+ }
+
+ @Override
+ protected void dispatch(VisibilityHandler handler) {
+ handler.visibilityChanged(this);
+ }
+ }
+
+ /**
* The pixel size for OSX's invisible scrollbars.
* <p>
* Touch devices don't show a scrollbar at all, so the scrollbar size is
@@ -178,6 +233,12 @@ abstract class ScrollbarBundle {
private int scrollPos = 0;
private int maxScrollPos = 0;
+ private boolean scrollHandleIsVisible = false;
+
+ /** @deprecarted access via {@link #getHandlerManager()} instead. */
+ @Deprecated
+ private HandlerManager handlerManager;
+
private ScrollbarBundle() {
root.appendChild(scrollSizeElement);
}
@@ -233,6 +294,7 @@ abstract class ScrollbarBundle {
internalSetOffsetSize(px);
forceScrollbar(showsScrollHandle());
recalculateMaxScrollPos();
+ fireVisibilityChangeIfNeeded();
}
/**
@@ -309,6 +371,7 @@ abstract class ScrollbarBundle {
internalSetScrollSize(px);
forceScrollbar(showsScrollHandle());
recalculateMaxScrollPos();
+ fireVisibilityChangeIfNeeded();
}
/**
@@ -400,4 +463,34 @@ abstract class ScrollbarBundle {
private final void updateScrollPosFromDom() {
scrollPos = internalGetScrollPos();
}
+
+ protected HandlerManager getHandlerManager() {
+ if (handlerManager == null) {
+ handlerManager = new HandlerManager(this);
+ }
+ return handlerManager;
+ }
+
+ /**
+ * Adds handler for the scrollbar handle visibility.
+ *
+ * @param handler
+ * the {@link VisibilityHandler} to add
+ * @return {@link HandlerRegistration} used to remove the handler
+ */
+ public HandlerRegistration addVisibilityHandler(
+ final VisibilityHandler handler) {
+ return getHandlerManager().addHandler(VisibilityChangeEvent.TYPE,
+ handler);
+ }
+
+ private void fireVisibilityChangeIfNeeded() {
+ final boolean oldHandleIsVisible = scrollHandleIsVisible;
+ scrollHandleIsVisible = showsScrollHandle();
+ if (oldHandleIsVisible != scrollHandleIsVisible) {
+ final VisibilityChangeEvent event = new VisibilityChangeEvent(
+ scrollHandleIsVisible);
+ getHandlerManager().fireEvent(event);
+ }
+ }
}
diff --git a/server/src/com/vaadin/ui/components/grid/Grid.java b/server/src/com/vaadin/ui/components/grid/Grid.java
index 4126ec6d93..7544f2b497 100644
--- a/server/src/com/vaadin/ui/components/grid/Grid.java
+++ b/server/src/com/vaadin/ui/components/grid/Grid.java
@@ -48,6 +48,7 @@ import com.vaadin.shared.ui.grid.GridServerRpc;
import com.vaadin.shared.ui.grid.GridState;
import com.vaadin.shared.ui.grid.Range;
import com.vaadin.shared.ui.grid.ScrollDestination;
+import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.Component;
@@ -858,4 +859,102 @@ public class Grid extends AbstractComponent {
GridClientRpc clientRPC = getRpcProxy(GridClientRpc.class);
clientRPC.scrollToEnd();
}
+
+ /**
+ * Sets the number of rows that should be visible in Grid's body, while
+ * {@link #getHeightMode()} is {@link HeightMode#ROW}.
+ * <p>
+ * If Grid is currently not in {@link HeightMode#ROW}, the given value is
+ * remembered, and applied once the mode is applied.
+ *
+ * @param rows
+ * The height in terms of number of rows displayed in Grid's
+ * body. If Grid doesn't contain enough rows, white space is
+ * displayed instead. If <code>null</code> is given, then Grid's
+ * height is undefined
+ * @throws IllegalArgumentException
+ * if {@code rows} is zero or less
+ * @throws IllegalArgumentException
+ * if {@code rows} is {@link Double#isInifinite(double)
+ * infinite}
+ * @throws IllegalArgumentException
+ * if {@code rows} is {@link Double#isNaN(double) NaN}
+ */
+ public void setHeightByRows(double rows) {
+ if (rows <= 0.0d) {
+ throw new IllegalArgumentException(
+ "More than zero rows must be shown.");
+ } else if (Double.isInfinite(rows)) {
+ throw new IllegalArgumentException(
+ "Grid doesn't support infinite heights");
+ } else if (Double.isNaN(rows)) {
+ throw new IllegalArgumentException("NaN is not a valid row count");
+ }
+
+ getState().heightByRows = rows;
+ }
+
+ /**
+ * Gets the amount of rows in Grid's body that are shown, while
+ * {@link #getHeightMode()} is {@link HeightMode#ROW}.
+ *
+ * @return the amount of rows that are being shown in Grid's body
+ * @see #setHeightByRows(double)
+ */
+ public double getHeightByRows() {
+ return getState(false).heightByRows;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * <em>Note:</em> This method will change the widget's size in the browser
+ * only if {@link #getHeightMode()} returns {@link HeightMode#CSS}.
+ *
+ * @see #setHeightMode(HeightMode)
+ */
+ @Override
+ public void setHeight(float height, Unit unit) {
+ super.setHeight(height, unit);
+ }
+
+ /**
+ * Defines the mode in which the Grid widget's height is calculated.
+ * <p>
+ * If {@link HeightMode#CSS} is given, Grid will respect the values given
+ * via a {@code setHeight}-method, and behave as a traditional Component.
+ * <p>
+ * If {@link HeightMode#ROW} is given, Grid will make sure that the body
+ * will display as many rows as {@link #getHeightByRows()} defines.
+ * <em>Note:</em> If headers/footers are inserted or removed, the widget
+ * will resize itself to still display the required amount of rows in its
+ * body. It also takes the horizontal scrollbar into account.
+ *
+ * @param heightMode
+ * the mode in to which Grid should be set
+ */
+ public void setHeightMode(HeightMode heightMode) {
+ /*
+ * This method is a workaround for the fact that Vaadin re-applies
+ * widget dimensions (height/width) on each state change event. The
+ * original design was to have setHeight an setHeightByRow be equals,
+ * and whichever was called the latest was considered in effect.
+ *
+ * But, because of Vaadin always calling setHeight on the widget, this
+ * approach doesn't work.
+ */
+
+ getState().heightMode = heightMode;
+ }
+
+ /**
+ * Returns the current {@link HeightMode} the Grid is in.
+ * <p>
+ * Defaults to {@link HeightMode#CSS}.
+ *
+ * @return the current HeightMode
+ */
+ public HeightMode getHeightMode() {
+ return getState(false).heightMode;
+ }
}
diff --git a/shared/src/com/vaadin/shared/ui/grid/GridState.java b/shared/src/com/vaadin/shared/ui/grid/GridState.java
index 93e602a539..8fdd8c8ec5 100644
--- a/shared/src/com/vaadin/shared/ui/grid/GridState.java
+++ b/shared/src/com/vaadin/shared/ui/grid/GridState.java
@@ -28,6 +28,14 @@ import com.vaadin.shared.AbstractComponentState;
* @author Vaadin Ltd
*/
public class GridState extends AbstractComponentState {
+
+ /**
+ * The default value for height-by-rows for both GWT widgets
+ * {@link com.vaadin.ui.components.grid Grid} and
+ * {@link com.vaadin.client.ui.grid.Escalator Escalator}
+ */
+ public static final double DEFAULT_HEIGHT_BY_ROWS = 10.0d;
+
{
// FIXME Grid currently does not support undefined size
width = "400px";
@@ -61,4 +69,20 @@ public class GridState extends AbstractComponentState {
*/
public String lastFrozenColumnId = null;
+ /** The height of the Grid in terms of body rows. */
+ // @DelegateToWidget
+ /*
+ * Annotation doesn't work because of http://dev.vaadin.com/ticket/12900.
+ * Remove manual code from Connector once fixed
+ */
+ public double heightByRows = DEFAULT_HEIGHT_BY_ROWS;
+
+ /** The mode by which Grid defines its height. */
+ // @DelegateToWidget
+ /*
+ * Annotation doesn't work because of http://dev.vaadin.com/ticket/12900.
+ * Remove manual code from Connector once fixed
+ */
+ public HeightMode heightMode = HeightMode.CSS;
+
}
diff --git a/shared/src/com/vaadin/shared/ui/grid/HeightMode.java b/shared/src/com/vaadin/shared/ui/grid/HeightMode.java
new file mode 100644
index 0000000000..0146e53e73
--- /dev/null
+++ b/shared/src/com/vaadin/shared/ui/grid/HeightMode.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2013 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.shared.ui.grid;
+
+/**
+ * The modes for height calculation that are supported by Grid (
+ * {@link com.vaadin.client.ui.grid.Grid client} and
+ * {@link com.vaadin.ui.components.grid.Grid server}) /
+ * {@link com.vaadin.client.ui.grid.Escalator Escalator}.
+ *
+ * @since 7.2
+ * @author Vaadin Ltd
+ * @see com.vaadin.client.ui.grid.Grid#setHeightMode(HeightMode)
+ * @see com.vaadin.ui.components.grid.Grid#setHeightMode(HeightMode)
+ * @see com.vaadin.client.ui.grid.Escalator#setHeightMode(HeightMode)
+ */
+public enum HeightMode {
+ /**
+ * The height of the Component or Widget is defined by a CSS-like value.
+ * (e.g. "100px", "50em" or "25%")
+ */
+ CSS,
+
+ /**
+ * The height of the Component or Widget in question is defined by a number
+ * of rows.
+ */
+ ROW;
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/GridBasicFeatures.java
index c28feb8d10..0faabff88a 100644
--- a/uitest/src/com/vaadin/tests/components/grid/GridBasicFeatures.java
+++ b/uitest/src/com/vaadin/tests/components/grid/GridBasicFeatures.java
@@ -15,11 +15,13 @@
*/
package com.vaadin.tests.components.grid;
+import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import com.vaadin.data.Item;
import com.vaadin.data.util.IndexedContainer;
+import com.vaadin.shared.ui.grid.HeightMode;
import com.vaadin.tests.components.AbstractComponentTest;
import com.vaadin.ui.components.grid.ColumnGroup;
import com.vaadin.ui.components.grid.ColumnGroupRow;
@@ -86,6 +88,8 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
createRowActions();
+ addHeightByRowActions();
+
return grid;
}
@@ -330,6 +334,41 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}, null);
}
+ @SuppressWarnings("boxing")
+ protected void addHeightByRowActions() {
+ createCategory("Height by Rows", "Size");
+
+ createBooleanAction("HeightMode Row", "Size", false,
+ new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid c, Boolean heightModeByRows,
+ Object data) {
+ c.setHeightMode(heightModeByRows ? HeightMode.ROW
+ : HeightMode.CSS);
+ }
+ }, null);
+
+ addActionForHeightByRows(1d / 3d);
+ addActionForHeightByRows(2d / 3d);
+
+ for (double i = 1; i < 5; i++) {
+ addActionForHeightByRows(i);
+ addActionForHeightByRows(i + 1d / 3d);
+ addActionForHeightByRows(i + 2d / 3d);
+ }
+ }
+
+ private void addActionForHeightByRows(final Double i) {
+ DecimalFormat df = new DecimalFormat("0.00");
+ createClickAction(df.format(i) + " rows", "Height by Rows",
+ new Command<Grid, String>() {
+ @Override
+ public void execute(Grid c, String value, Object data) {
+ c.setHeightByRows(i);
+ }
+ }, null);
+ }
+
@Override
protected Integer getTicketNumber() {
return 12829;