From b3e6edc9634f444ccece00e200cb51eee7994d75 Mon Sep 17 00:00:00 2001 From: Henrik Paul Date: Mon, 8 Dec 2014 01:02:29 +0200 Subject: [PATCH] Columns can now have subpixel accuracy widths (#13334) Change-Id: I1d16260be7b15c9fbdbfdd8f51e50e9f34e96272 --- .../client/ui/grid/ColumnConfiguration.java | 7 +- .../com/vaadin/client/ui/grid/Escalator.java | 88 +- .../vaadin/client/ui/grid/FlyweightCell.java | 4 +- .../vaadin/client/ui/grid/FlyweightRow.java | 6 +- .../src/com/vaadin/client/ui/grid/Grid.java | 23 +- .../com/vaadin/client/ui/grid/GridUtil.java | 25 +- .../client/ui/grid/ScrollbarBundle.java | 32 +- server/src/com/vaadin/ui/Grid.java | 7 +- .../server/component/grid/GridColumns.java | 10 +- .../shared/ui/grid/GridColumnState.java | 4 +- .../grid/basicfeatures/GridBasicFeatures.java | 11 + .../basicfeatures/GridBasicFeatures.java.orig | 922 ++++++++++++++++++ .../widgetset/client/grid/EscalatorProxy.java | 6 +- 13 files changed, 1040 insertions(+), 105 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java.orig diff --git a/client/src/com/vaadin/client/ui/grid/ColumnConfiguration.java b/client/src/com/vaadin/client/ui/grid/ColumnConfiguration.java index 6c304ddaea..88f07e023f 100644 --- a/client/src/com/vaadin/client/ui/grid/ColumnConfiguration.java +++ b/client/src/com/vaadin/client/ui/grid/ColumnConfiguration.java @@ -123,7 +123,7 @@ public interface ColumnConfiguration { * @throws IllegalArgumentException * if index is not a valid column index */ - public void setColumnWidth(int index, int px) + public void setColumnWidth(int index, double px) throws IllegalArgumentException; /** @@ -136,7 +136,7 @@ public interface ColumnConfiguration { * @throws IllegalArgumentException * if index is not a valid column index */ - public int getColumnWidth(int index) throws IllegalArgumentException; + public double getColumnWidth(int index) throws IllegalArgumentException; /** * Returns the actual width of a column. @@ -147,7 +147,8 @@ public interface ColumnConfiguration { * @throws IllegalArgumentException * if index is not a valid column index */ - public int getColumnWidthActual(int index) throws IllegalArgumentException; + public double getColumnWidthActual(int index) + throws IllegalArgumentException; /** * Refreshes a range of rows in the current row containers in each Escalator diff --git a/client/src/com/vaadin/client/ui/grid/Escalator.java b/client/src/com/vaadin/client/ui/grid/Escalator.java index 1bbcaaf166..3ea7d94282 100644 --- a/client/src/com/vaadin/client/ui/grid/Escalator.java +++ b/client/src/com/vaadin/client/ui/grid/Escalator.java @@ -744,7 +744,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker */ public void recalculateScrollbarsForVirtualViewport() { int scrollContentHeight = body.calculateEstimatedTotalRowHeight(); - int scrollContentWidth = columnConfiguration.calculateRowWidth(); + double scrollContentWidth = columnConfiguration.calculateRowWidth(); double tableWrapperHeight = heightOfEscalator; double tableWrapperWidth = widthOfEscalator; @@ -789,11 +789,11 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker */ double prevScrollPos = horizontalScrollbar.getScrollPos(); - int unfrozenPixels = columnConfiguration + double unfrozenPixels = columnConfiguration .getCalculatedColumnsWidth(Range.between( columnConfiguration.getFrozenColumnCount(), columnConfiguration.getColumnCount())); - int frozenPixels = scrollContentWidth - unfrozenPixels; + double frozenPixels = scrollContentWidth - unfrozenPixels; double hScrollOffsetWidth = tableWrapperWidth - frozenPixels; horizontalScrollbar.setOffsetSize(hScrollOffsetWidth); horizontalScrollbar.setScrollSize(unfrozenPixels); @@ -1034,19 +1034,19 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker * structure effectively means that scrollLeft also ignores the * frozen columns. */ - final int frozenPixels = columnConfiguration + final double frozenPixels = columnConfiguration .getCalculatedColumnsWidth(Range.withLength(0, columnConfiguration.frozenColumns)); - final int targetStartPx = columnConfiguration + final double targetStartPx = columnConfiguration .getCalculatedColumnsWidth(Range.withLength(0, columnIndex)) - frozenPixels; - final int targetEndPx = targetStartPx + final double targetEndPx = targetStartPx + columnConfiguration.getColumnWidthActual(columnIndex); final double viewportStartPx = getScrollLeft(); double viewportEndPx = viewportStartPx - + getElement().getOffsetWidth() - frozenPixels; + + getPreciseWidth(getElement()) - frozenPixels; if (verticalScrollbar.showsScrollHandle()) { viewportEndPx -= Util.getNativeScrollbarSize(); } @@ -1399,7 +1399,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker tr.addClassName(getStylePrimaryName() + "-row"); for (int col = 0; col < columnConfiguration.getColumnCount(); col++) { - final int colWidth = columnConfiguration + final double colWidth = columnConfiguration .getColumnWidthActual(col); final TableCellElement cellElem = createCellElement( rowHeight, colWidth); @@ -1542,11 +1542,11 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker * @return a set-up empty cell element */ public TableCellElement createCellElement(final int height, - final int width) { + final double colWidth) { final TableCellElement cellElem = TableCellElement.as(DOM .createElement(getCellElementTagName())); cellElem.getStyle().setHeight(height, Unit.PX); - cellElem.getStyle().setWidth(width, Unit.PX); + cellElem.getStyle().setWidth(colWidth, Unit.PX); cellElem.addClassName(getStylePrimaryName() + "-cell"); return cellElem; } @@ -1640,7 +1640,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker final int rowHeight = getDefaultRowHeight(); for (FlyweightCell cell : cells) { - final int colWidth = columnConfiguration + final double colWidth = columnConfiguration .getColumnWidthActual(cell.getColumn()); final TableCellElement cellElem = createCellElement(rowHeight, colWidth); @@ -1706,16 +1706,16 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker * the index of the column to inspect * @return the pixel width of the widest element in the indicated column */ - public int calculateMaxColWidth(int index) { + public double calculateMaxColWidth(int index) { TableRowElement row = TableRowElement.as(root .getFirstChildElement()); - int maxWidth = 0; + double maxWidth = 0; while (row != null) { final TableCellElement cell = row.getCells().getItem(index); final boolean isVisible = !cell.getStyle().getDisplay() .equals(Display.NONE.getCssName()); if (isVisible) { - maxWidth = Math.max(maxWidth, cell.getScrollWidth()); + maxWidth = Math.max(maxWidth, getPreciseWidth(cell)); } row = TableRowElement.as(row.getNextSiblingElement()); } @@ -1732,8 +1732,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker Element cell = row.getFirstChildElement(); int columnIndex = 0; while (cell != null) { - final int width = getCalculatedColumnWidthWithColspan(cell, - columnIndex); + final double width = getCalculatedColumnWidthWithColspan( + cell, columnIndex); /* * TODO Should Escalator implement ProvidesResize at some @@ -1750,7 +1750,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker reapplyRowWidths(); } - private int getCalculatedColumnWidthWithColspan(final Element cell, + private double getCalculatedColumnWidthWithColspan(final Element cell, final int columnIndex) { final int colspan = cell.getPropertyInt(FlyweightCell.COLSPAN_ATTR); Range spannedColumns = Range.withLength(columnIndex, colspan); @@ -1775,7 +1775,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker * cells within. */ protected void reapplyRowWidths() { - int rowWidth = columnConfiguration.calculateRowWidth(); + double rowWidth = columnConfiguration.calculateRowWidth(); com.google.gwt.dom.client.Element row = root.getFirstChildElement(); while (row != null) { @@ -1957,8 +1957,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker return new Cell(domRowIndex, domColumnIndex, cellElement); } - int getMaxCellWidth(int colIndex) throws IllegalArgumentException { - int maxCellWidth = -1; + double getMaxCellWidth(int colIndex) throws IllegalArgumentException { + double maxCellWidth = -1; assert isAttached() : "Can't measure max width of cell, since Escalator is not attached to the DOM."; @@ -1988,7 +1988,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker cellClone.getStyle().clearWidth(); rowElement.insertBefore(cellClone, cellOriginal); - maxCellWidth = Math.max(cellClone.getOffsetWidth(), + maxCellWidth = Math.max(getPreciseWidth(cellClone), maxCellWidth); cellClone.removeFromParent(); } @@ -3684,8 +3684,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker public class Column { private static final int DEFAULT_COLUMN_WIDTH_PX = 100; - private int definedWidth = -1; - private int calculatedWidth = DEFAULT_COLUMN_WIDTH_PX; + private double definedWidth = -1; + private double calculatedWidth = DEFAULT_COLUMN_WIDTH_PX; private boolean measuringRequested = false; /** @@ -3695,7 +3695,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker */ private boolean widthHasBeenFinalized = false; - public void setWidth(int px) { + public void setWidth(double px) { definedWidth = px; if (px < 0) { @@ -3713,7 +3713,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker } } - public int getDefinedWidth() { + public double getDefinedWidth() { return definedWidth; } @@ -3723,7 +3723,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker * @return the width in pixels in the DOM. Returns -1 if the column * needs measuring, but has not been yet measured */ - public int getCalculatedWidth() { + public double getCalculatedWidth() { /* * This might return an untrue value (e.g. during init/onload), * since we haven't had a proper chance to actually calculate @@ -3777,7 +3777,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker * * @see #getCalculatedColumnWidths() */ - private int[] widthsArray = null; + private double[] widthsArray = null; /** * {@inheritDoc} @@ -3884,7 +3884,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker * * @return the width of a row, in pixels */ - public int calculateRowWidth() { + public double calculateRowWidth() { return getCalculatedColumnsWidth(Range.between(0, getColumnCount())); } @@ -3966,12 +3966,12 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker } // Adjust scrollbar - int pixelsToInsertedColumn = columnConfiguration + double pixelsToInsertedColumn = columnConfiguration .getCalculatedColumnsWidth(Range.withLength(0, index)); final boolean columnsWereAddedToTheLeftOfViewport = scroller.lastScrollLeft > pixelsToInsertedColumn; if (columnsWereAddedToTheLeftOfViewport) { - int insertedColumnsWidth = columnConfiguration + double insertedColumnsWidth = columnConfiguration .getCalculatedColumnsWidth(Range.withLength(index, numberOfColumns)); horizontalScrollbar.setScrollPos(scroller.lastScrollLeft @@ -4042,7 +4042,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker } @Override - public void setColumnWidth(int index, int px) + public void setColumnWidth(int index, double px) throws IllegalArgumentException { checkValidColumnIndex(index); @@ -4069,25 +4069,25 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker } @Override - public int getColumnWidth(int index) throws IllegalArgumentException { + public double getColumnWidth(int index) throws IllegalArgumentException { checkValidColumnIndex(index); return columns.get(index).getDefinedWidth(); } @Override - public int getColumnWidthActual(int index) { + public double getColumnWidthActual(int index) { return columns.get(index).getCalculatedWidth(); } - private int getMaxCellWidth(int colIndex) + private double getMaxCellWidth(int colIndex) throws IllegalArgumentException { - int headerWidth = header.getMaxCellWidth(colIndex); - int bodyWidth = body.getMaxCellWidth(colIndex); - int footerWidth = footer.getMaxCellWidth(colIndex); + double headerWidth = header.getMaxCellWidth(colIndex); + double bodyWidth = body.getMaxCellWidth(colIndex); + double footerWidth = footer.getMaxCellWidth(colIndex); - int maxWidth = Math.max(headerWidth, + double maxWidth = Math.max(headerWidth, Math.max(bodyWidth, footerWidth)); - assert maxWidth > 0 : "Got a negative max width for a column, which should be impossible."; + assert maxWidth >= 0 : "Got a negative max width for a column, which should be impossible."; return maxWidth; } @@ -4099,7 +4099,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker * @return the total width of the columns in the given * columns */ - int getCalculatedColumnsWidth(final Range columns) { + double getCalculatedColumnsWidth(final Range columns) { /* * This is an assert instead of an exception, since this is an * internal method. @@ -4110,17 +4110,17 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker + ", but was given :" + columns; - int sum = 0; + double sum = 0; for (int i = columns.getStart(); i < columns.getEnd(); i++) { - int columnWidthActual = getColumnWidthActual(i); + double columnWidthActual = getColumnWidthActual(i); sum += columnWidthActual; } return sum; } - int[] getCalculatedColumnWidths() { + double[] getCalculatedColumnWidths() { if (widthsArray == null || widthsArray.length != getColumnCount()) { - widthsArray = new int[getColumnCount()]; + widthsArray = new double[getColumnCount()]; for (int i = 0; i < columns.size(); i++) { widthsArray[i] = columns.get(i).getCalculatedWidth(); } diff --git a/client/src/com/vaadin/client/ui/grid/FlyweightCell.java b/client/src/com/vaadin/client/ui/grid/FlyweightCell.java index adcca1b630..fe826b16c3 100644 --- a/client/src/com/vaadin/client/ui/grid/FlyweightCell.java +++ b/client/src/com/vaadin/client/ui/grid/FlyweightCell.java @@ -169,8 +169,8 @@ public class FlyweightCell { final int cellsToTheRight = currentIterator.rawPeekNext( numberOfCells - 1).size(); - final int selfWidth = row.getColumnWidth(column); - int widthsOfColumnsToTheRight = 0; + final double selfWidth = row.getColumnWidth(column); + double widthsOfColumnsToTheRight = 0; for (int i = 0; i < cellsToTheRight; i++) { widthsOfColumnsToTheRight += row.getColumnWidth(column + i + 1); } diff --git a/client/src/com/vaadin/client/ui/grid/FlyweightRow.java b/client/src/com/vaadin/client/ui/grid/FlyweightRow.java index 0e9c6ad955..9f913f5cd1 100644 --- a/client/src/com/vaadin/client/ui/grid/FlyweightRow.java +++ b/client/src/com/vaadin/client/ui/grid/FlyweightRow.java @@ -140,10 +140,10 @@ class FlyweightRow implements Row { private int row; private TableRowElement element; - private int[] columnWidths = null; + private double[] columnWidths = null; private final List cells = new ArrayList(); - void setup(final TableRowElement e, final int row, int[] columnWidths) { + void setup(final TableRowElement e, final int row, double[] columnWidths) { element = e; this.row = row; this.columnWidths = columnWidths; @@ -285,7 +285,7 @@ class FlyweightRow implements Row { + "has been stored and accessed."; } - int getColumnWidth(int column) { + double getColumnWidth(int column) { assertSetup(); return columnWidths[column]; } diff --git a/client/src/com/vaadin/client/ui/grid/Grid.java b/client/src/com/vaadin/client/ui/grid/Grid.java index c6d7e22d3b..80ecc9a9e9 100644 --- a/client/src/com/vaadin/client/ui/grid/Grid.java +++ b/client/src/com/vaadin/client/ui/grid/Grid.java @@ -1875,7 +1875,7 @@ public class Grid extends ResizeComposite implements } @Override - public GridColumn setWidth(int pixels) { + public GridColumn setWidth(double pixels) { if (pixels != getWidth() && initDone) { throw new UnsupportedOperationException("The selection " + "column cannot be modified after init"); @@ -2208,8 +2208,11 @@ public class Grid extends ResizeComposite implements */ private boolean visible = true; - /** Width of column in pixels as {@link #setWidth(int)} has been called */ - private int widthUser = GridColumnState.DEFAULT_COLUMN_WIDTH_PX; + /** + * Width of column in pixels as {@link #setWidth(double)} has been + * called + */ + private double widthUser = GridColumnState.DEFAULT_COLUMN_WIDTH_PX; /** * Renderer for rendering a value into the cell @@ -2387,7 +2390,7 @@ public class Grid extends ResizeComposite implements * the width in pixels or negative for auto sizing * @return the column itself */ - public GridColumn setWidth(int pixels) { + public GridColumn setWidth(double pixels) { widthUser = pixels; if (pixels < 0) { setWidthAutodetect(); @@ -2409,14 +2412,14 @@ public class Grid extends ResizeComposite implements */ } - private void setWidthAbsolute(int pixels) { + private void setWidthAbsolute(double pixels) { asyncAutodetectWidth.stop(); if (grid != null) { setWidthForce(pixels); } } - private void setWidthForce(int pixels) { + private void setWidthForce(double pixels) { int index = grid.columns.indexOf(this); ColumnConfiguration conf = grid.escalator.getColumnConfiguration(); conf.setColumnWidth(index, pixels); @@ -2426,14 +2429,14 @@ public class Grid extends ResizeComposite implements * Returns the pixel width of the column as given by the user. *

* Note: If a negative value was given to - * {@link #setWidth(int)}, that same negative value is returned here. + * {@link #setWidth(double)}, that same negative value is returned here. * * @return pixel width of the column, or a negative number if the column * width has been automatically calculated. - * @see #setWidth(int) + * @see #setWidth(double) * @see #getWidthActual() */ - public int getWidth() { + public double getWidth() { return widthUser; } @@ -2445,7 +2448,7 @@ public class Grid extends ResizeComposite implements * * @return pixel width of the column. */ - public int getWidthActual() { + public double getWidthActual() { return grid.escalator.getColumnConfiguration() .getColumnWidthActual(grid.columns.indexOf(this)); } diff --git a/client/src/com/vaadin/client/ui/grid/GridUtil.java b/client/src/com/vaadin/client/ui/grid/GridUtil.java index 0eed0e98b5..8dc0822d9d 100644 --- a/client/src/com/vaadin/client/ui/grid/GridUtil.java +++ b/client/src/com/vaadin/client/ui/grid/GridUtil.java @@ -16,7 +16,6 @@ package com.vaadin.client.ui.grid; import com.google.gwt.dom.client.Element; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.Util; @@ -28,9 +27,18 @@ import com.vaadin.client.Util; */ public class GridUtil { + /** + * The allowed value inaccuracy when comparing two double-typed pixel + * values. + *

+ * Since we're comparing pixels on a screen, epsilon must be less than 1. + * 0.49 was deemed a perfectly fine and beautifully round number. + */ + public static final double PIXEL_EPSILON = 0.49d; + /** * Returns the cell the given element belongs to. - * + * * @param grid * the grid instance that is queried * @param e @@ -78,4 +86,17 @@ public class GridUtil { widget.@com.google.gwt.user.client.ui.Widget::setParent(Lcom/google/gwt/user/client/ui/Widget;)(parent); }-*/; + /** + * Compares two double values with the error margin of + * {@link #PIXEL_EPSILON} (i.e. {@value #PIXEL_EPSILON}) + * + * @param num1 + * the first value for which to compare equality + * @param num2 + * the second value for which to compare equality + */ + public static boolean pixelValuesEqual(final double num1, final double num2) { + return Math.abs(num1 - num2) <= PIXEL_EPSILON; + } + } diff --git a/client/src/com/vaadin/client/ui/grid/ScrollbarBundle.java b/client/src/com/vaadin/client/ui/grid/ScrollbarBundle.java index a2df48e6c6..7d6d050e64 100644 --- a/client/src/com/vaadin/client/ui/grid/ScrollbarBundle.java +++ b/client/src/com/vaadin/client/ui/grid/ScrollbarBundle.java @@ -178,15 +178,6 @@ abstract class ScrollbarBundle { */ private static final int OSX_INVISIBLE_SCROLLBAR_FAKE_SIZE_PX = 13; - /** - * The allowed value inaccuracy when comparing two double-typed pixel - * values. - *

- * Since we're comparing pixels on a screen, epsilon must be less than 1. - * 0.49 was deemed a perfectly fine and beautifully round number. - */ - private static final double PIXEL_EPSILON = 0.49d; - /** * A representation of a single vertical scrollbar. * @@ -211,7 +202,7 @@ abstract class ScrollbarBundle { } @Override - protected void internalSetScrollSize(int px) { + protected void internalSetScrollSize(double px) { scrollSizeElement.getStyle().setHeight(px, Unit.PX); } @@ -280,7 +271,7 @@ abstract class ScrollbarBundle { } @Override - protected void internalSetScrollSize(int px) { + protected void internalSetScrollSize(double px) { scrollSizeElement.getStyle().setWidth(px, Unit.PX); } @@ -451,7 +442,7 @@ abstract class ScrollbarBundle { double oldScrollPos = scrollPos; scrollPos = Math.max(0, Math.min(maxScrollPos, truncate(px))); - if (!pixelValuesEqual(oldScrollPos, scrollPos)) { + if (!GridUtil.pixelValuesEqual(oldScrollPos, scrollPos)) { if (isInvisibleScrollbar) { invisibleScrollbarTemporaryResizer.show(); } @@ -533,7 +524,7 @@ abstract class ScrollbarBundle { * the new size of {@link #scrollSizeElement} in the dimension * this scrollbar is representing */ - protected abstract void internalSetScrollSize(int px); + protected abstract void internalSetScrollSize(double px); /** * Sets the amount of pixels the scrollbar needs to be able to scroll @@ -549,7 +540,7 @@ abstract class ScrollbarBundle { * through */ public final void setScrollSize(double px) { - internalSetScrollSize(toInt32(Math.max(0, truncate(px)))); + internalSetScrollSize(Math.max(0, px)); forceScrollbar(showsScrollHandle()); recalculateMaxScrollPos(); fireVisibilityChangeIfNeeded(); @@ -718,19 +709,6 @@ abstract class ScrollbarBundle { return val | 0; }-*/; - /** - * Compares two double values with the error margin of - * {@link #PIXEL_EPSILON} (i.e. {@value #PIXEL_EPSILON}) - * - * @param num1 - * the first value for which to compare equality - * @param num2 - * the second value for which to compare equality - */ - private static boolean pixelValuesEqual(final double num1, final double num2) { - return Math.abs(num1 - num2) <= PIXEL_EPSILON; - } - /** * Locks or unlocks the scrollbar bundle. *

diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index 838829b9cc..d0485c3d68 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -64,7 +64,6 @@ import com.vaadin.event.SortOrderChangeEvent.SortOrderChangeListener; import com.vaadin.event.SortOrderChangeEvent.SortOrderChangeNotifier; import com.vaadin.server.AbstractClientConnector; import com.vaadin.server.AbstractExtension; -import com.vaadin.server.ClientConnector; import com.vaadin.server.ErrorHandler; import com.vaadin.server.ErrorMessage; import com.vaadin.server.JsonCodec; @@ -1643,7 +1642,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, * @throws IllegalStateException * if the column is no longer attached to any grid */ - public int getWidth() throws IllegalStateException { + public double getWidth() throws IllegalStateException { checkColumnIsAttached(); return state.width; } @@ -1660,7 +1659,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, * @throws IllegalArgumentException * thrown if pixel width is less than zero */ - public Column setWidth(int pixelWidth) throws IllegalStateException, + public Column setWidth(double pixelWidth) throws IllegalStateException, IllegalArgumentException { checkColumnIsAttached(); if (pixelWidth < 0) { @@ -2518,7 +2517,7 @@ public class Grid extends AbstractComponent implements SelectionChangeNotifier, * * @return unmodifiable copy of current columns in visual order */ - public Collection getColumns() { + public List getColumns() { List columns = new ArrayList(); for (String columnId : getState(false).columnOrder) { columns.add(getColumnByColumnId(columnId)); diff --git a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java index 366176c3fa..1204b1e396 100644 --- a/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java +++ b/server/tests/src/com/vaadin/tests/server/component/grid/GridColumns.java @@ -100,18 +100,18 @@ public class GridColumns { .getCell("column1").getText()); column.setWidth(100); - assertEquals(100, column.getWidth()); - assertEquals(column.getWidth(), getColumnState("column1").width); + assertEquals(100, column.getWidth(), 0.49d); + assertEquals(column.getWidth(), getColumnState("column1").width, 0.49d); try { column.setWidth(-1); fail("Setting width to -1 should throw exception"); } catch (IllegalArgumentException iae) { - + // expected } - assertEquals(100, column.getWidth()); - assertEquals(100, getColumnState("column1").width); + assertEquals(100, column.getWidth(), 0.49d); + assertEquals(100, getColumnState("column1").width, 0.49d); } @Test diff --git a/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java index 751b262570..65a5ed625d 100644 --- a/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java +++ b/shared/src/com/vaadin/shared/ui/grid/GridColumnState.java @@ -28,7 +28,7 @@ import com.vaadin.shared.Connector; */ public class GridColumnState implements Serializable { - public static final int DEFAULT_COLUMN_WIDTH_PX = -1; + public static final double DEFAULT_COLUMN_WIDTH_PX = -1; /** * Id used by grid connector to map server side column with client side @@ -40,7 +40,7 @@ public class GridColumnState implements Serializable { * Column width in pixels. Default column width is * {@value #DEFAULT_COLUMN_WIDTH_PX}. */ - public int width = DEFAULT_COLUMN_WIDTH_PX; + public double width = DEFAULT_COLUMN_WIDTH_PX; /** * The connector for the renderer used to render the cells in this column. diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java index 043ff2e2e0..e61edb4e65 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -538,6 +538,17 @@ public class GridBasicFeatures extends AbstractComponentTest { } }, -1, c); + createClickAction("25.5px", "Column " + c + " Width", + new Command() { + @Override + @SuppressWarnings("boxing") + public void execute(Grid grid, Void value, + Object columnIndex) { + grid.getColumns().get((Integer) columnIndex) + .setWidth(25.5); + } + }, null, c); + for (int w = 50; w < 300; w += 50) { createClickAction(w + "px", "Column " + c + " Width", new Command() { diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java.orig b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java.orig new file mode 100644 index 0000000000..5d7fa04e94 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java.orig @@ -0,0 +1,922 @@ +/* + * 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.grid.basicfeatures; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Random; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.fieldgroup.FieldGroup.CommitException; +import com.vaadin.data.sort.Sort; +import com.vaadin.data.sort.SortOrder; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.event.SortOrderChangeEvent; +import com.vaadin.event.SortOrderChangeEvent.SortOrderChangeListener; +import com.vaadin.shared.ui.grid.GridStaticCellType; +import com.vaadin.shared.ui.grid.HeightMode; +import com.vaadin.shared.ui.grid.SortDirection; +import com.vaadin.tests.components.AbstractComponentTest; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Grid.CellStyleGenerator; +import com.vaadin.ui.Grid.Column; +import com.vaadin.ui.Grid.FooterCell; +import com.vaadin.ui.Grid.HeaderCell; +import com.vaadin.ui.Grid.HeaderRow; +import com.vaadin.ui.Grid.MultiSelectionModel; +import com.vaadin.ui.Grid.SelectionMode; +<<<<<<< HEAD +import com.vaadin.ui.renderer.DateRenderer; +import com.vaadin.ui.renderer.HtmlRenderer; +import com.vaadin.ui.renderer.NumberRenderer; +======= +import com.vaadin.ui.components.grid.SortOrderChangeEvent; +import com.vaadin.ui.components.grid.SortOrderChangeListener; +import com.vaadin.ui.components.grid.renderers.DateRenderer; +import com.vaadin.ui.components.grid.renderers.HtmlRenderer; +import com.vaadin.ui.components.grid.renderers.NumberRenderer; +import com.vaadin.ui.components.grid.selection.MultiSelectionModel; +import com.vaadin.ui.components.grid.sort.Sort; +import com.vaadin.ui.components.grid.sort.SortOrder; +>>>>>>> Columns can now have subpixel accuracy widths (#13334) + +/** + * Tests the basic features like columns, footers and headers + * + * @since + * @author Vaadin Ltd + */ +public class GridBasicFeatures extends AbstractComponentTest { + + private static final int MANUALLY_FORMATTED_COLUMNS = 5; + public static final int COLUMNS = 12; + public static final int ROWS = 1000; + + private int columnGroupRows = 0; + private IndexedContainer ds; + private Grid grid; + + @Override + @SuppressWarnings("unchecked") + protected Grid constructComponent() { + + // Build data source + ds = new IndexedContainer() { + @Override + public List getItemIds(int startIndex, int numberOfIds) { + log("Requested items " + startIndex + " - " + + (startIndex + numberOfIds)); + return super.getItemIds(startIndex, numberOfIds); + } + }; + + { + int col = 0; + for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; col++) { + ds.addContainerProperty(getColumnProperty(col), String.class, + ""); + } + + ds.addContainerProperty(getColumnProperty(col++), Integer.class, + Integer.valueOf(0)); + ds.addContainerProperty(getColumnProperty(col++), Date.class, + new Date()); + ds.addContainerProperty(getColumnProperty(col++), String.class, ""); + + // Random numbers + ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0); + ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0); + + } + + { + Random rand = new Random(); + rand.setSeed(13334); + long timestamp = 0; + for (int row = 0; row < ROWS; row++) { + Item item = ds.addItem(Integer.valueOf(row)); + int col = 0; + for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; col++) { + item.getItemProperty(getColumnProperty(col)).setValue( + "(" + row + ", " + col + ")"); + } + item.getItemProperty(getColumnProperty(1)).setReadOnly(true); + + item.getItemProperty(getColumnProperty(col++)).setValue( + Integer.valueOf(row)); + item.getItemProperty(getColumnProperty(col++)).setValue( + new Date(timestamp)); + timestamp += 91250000; // a bit over a day, just to get + // variation + item.getItemProperty(getColumnProperty(col++)).setValue( + "" + row + ""); + + // Random numbers + item.getItemProperty(getColumnProperty(col++)).setValue( + rand.nextInt()); + // Random between 0 - 5 to test multisorting + item.getItemProperty(getColumnProperty(col++)).setValue( + rand.nextInt(5)); + } + } + + // Create grid + Grid grid = new Grid(ds); + + { + int col = grid.getContainerDataSource().getContainerPropertyIds() + .size() + - MANUALLY_FORMATTED_COLUMNS; + grid.getColumn(getColumnProperty(col++)).setRenderer( + new NumberRenderer(new DecimalFormat("0,000.00", + DecimalFormatSymbols.getInstance(new Locale("fi", + "FI"))))); + grid.getColumn(getColumnProperty(col++)).setRenderer( + new DateRenderer(new SimpleDateFormat("dd.MM.yy HH:mm"))); + grid.getColumn(getColumnProperty(col++)).setRenderer( + new HtmlRenderer()); + grid.getColumn(getColumnProperty(col++)).setRenderer( + new NumberRenderer()); + grid.getColumn(getColumnProperty(col++)).setRenderer( + new NumberRenderer()); + } + + // Create footer + grid.appendFooterRow(); + grid.setFooterVisible(false); + + // Add footer values (header values are automatically created) + for (int col = 0; col < COLUMNS; col++) { + grid.getFooterRow(0).getCell(getColumnProperty(col)) + .setText("Footer " + col); + } + + // Set varying column widths + for (int col = 0; col < COLUMNS; col++) { + grid.getColumn(getColumnProperty(col)).setWidth(100 + col * 50); + } + + grid.addSortOrderChangeListener(new SortOrderChangeListener() { + @Override + public void sortOrderChange(SortOrderChangeEvent event) { + + log("SortOrderChangeEvent: isUserOriginated? " + + event.isUserOriginated()); + } + }); + + grid.setSelectionMode(SelectionMode.NONE); + + grid.setPropertyEditable(getColumnProperty(3), false); + + createGridActions(); + + createColumnActions(); + + createPropertyActions(); + + createHeaderActions(); + + createFooterActions(); + + createRowActions(); + + createEditorRowActions(); + + addHeightActions(); + + createClickAction("Column 1 starts with \"(23\"", "Filter", + new Command() { + @Override + public void execute(Grid grid, Void value, Object data) { + ds.addContainerFilter(new Filter() { + + @Override + public boolean passesFilter(Object itemId, Item item) + throws UnsupportedOperationException { + return item.getItemProperty("Column 1") + .getValue().toString() + .startsWith("(23"); + } + + @Override + public boolean appliesToProperty(Object propertyId) { + return propertyId.equals("Column 1"); + } + }); + } + }, null); + + this.grid = grid; + return grid; + } + + protected void createGridActions() { + LinkedHashMap primaryStyleNames = new LinkedHashMap(); + primaryStyleNames.put("v-grid", "v-grid"); + primaryStyleNames.put("v-escalator", "v-escalator"); + primaryStyleNames.put("my-grid", "my-grid"); + + createMultiClickAction("Primary style name", "State", + primaryStyleNames, new Command() { + + @Override + public void execute(Grid grid, String value, Object data) { + grid.setPrimaryStyleName(value); + + } + }, primaryStyleNames.get("v-grid")); + + LinkedHashMap selectionModes = new LinkedHashMap(); + selectionModes.put("single", SelectionMode.SINGLE); + selectionModes.put("multi", SelectionMode.MULTI); + selectionModes.put("none", SelectionMode.NONE); + createSelectAction("Selection mode", "State", selectionModes, "none", + new Command() { + @Override + public void execute(Grid grid, SelectionMode selectionMode, + Object data) { + grid.setSelectionMode(selectionMode); + } + }); + + LinkedHashMap selectionLimits = new LinkedHashMap(); + selectionLimits.put("2", Integer.valueOf(2)); + selectionLimits.put("1000", Integer.valueOf(1000)); + selectionLimits.put("Integer.MAX_VALUE", + Integer.valueOf(Integer.MAX_VALUE)); + createSelectAction("Selection limit", "State", selectionLimits, "1000", + new Command() { + @Override + public void execute(Grid grid, Integer limit, Object data) { + if (!(grid.getSelectionModel() instanceof MultiSelectionModel)) { + grid.setSelectionMode(SelectionMode.MULTI); + } + + ((MultiSelectionModel) grid.getSelectionModel()) + .setSelectionLimit(limit.intValue()); + } + }); + + LinkedHashMap> sortableProperties = new LinkedHashMap>(); + for (Object propertyId : ds.getSortableContainerPropertyIds()) { + sortableProperties.put(propertyId + ", ASC", Sort.by(propertyId) + .build()); + sortableProperties.put(propertyId + ", DESC", + Sort.by(propertyId, SortDirection.DESCENDING).build()); + } + createSelectAction("Sort by column", "State", sortableProperties, + "Column 9, ascending", new Command>() { + @Override + public void execute(Grid grid, List sortOrder, + Object data) { + grid.setSortOrder(sortOrder); + } + }); + + createBooleanAction("Reverse Grid Columns", "State", false, + new Command() { + + @Override + public void execute(Grid c, Boolean value, Object data) { + List ids = new ArrayList(); + ids.addAll(ds.getContainerPropertyIds()); + if (!value) { + c.setColumnOrder(ids.toArray()); + } else { + Object[] idsArray = new Object[ids.size()]; + for (int i = 0; i < ids.size(); ++i) { + idsArray[i] = ids.get((ids.size() - 1) - i); + } + c.setColumnOrder(idsArray); + } + } + }); + + LinkedHashMap styleGenerators = new LinkedHashMap(); + styleGenerators.put("None", null); + styleGenerators.put("Row only", new CellStyleGenerator() { + @Override + public String getStyle(Grid grid, Object itemId, Object propertyId) { + if (propertyId == null) { + return "row" + itemId; + } else { + return null; + } + } + }); + styleGenerators.put("Cell only", new CellStyleGenerator() { + @Override + public String getStyle(Grid grid, Object itemId, Object propertyId) { + if (propertyId == null) { + return null; + } else { + return propertyId.toString().replace(' ', '-'); + } + } + }); + styleGenerators.put("Combined", new CellStyleGenerator() { + @Override + public String getStyle(Grid grid, Object itemId, Object propertyId) { + int rowIndex = ((Integer) itemId).intValue(); + if (propertyId == null) { + if (rowIndex % 4 == 0) { + return null; + } else { + return "row" + itemId; + } + } else { + if (rowIndex % 4 == 1) { + return null; + } else if (rowIndex % 4 == 3 + && "Column 1".equals(propertyId)) { + return null; + } + return propertyId.toString().replace(' ', '_'); + } + } + }); + createSelectAction("Style generator", "State", styleGenerators, "None", + new Command() { + @Override + public void execute(Grid grid, + CellStyleGenerator generator, Object data) { + grid.setCellStyleGenerator(generator); + } + }); + + LinkedHashMap frozenOptions = new LinkedHashMap(); + for (int i = -1; i <= COLUMNS; i++) { + frozenOptions.put(String.valueOf(i), Integer.valueOf(i)); + } + createSelectAction("Frozen column count", "State", frozenOptions, "0", + new Command() { + @Override + public void execute(Grid c, Integer value, Object data) { + c.setFrozenColumnCount(value.intValue()); + } + }); + } + + protected void createHeaderActions() { + createCategory("Header", null); + + createBooleanAction("Visible", "Header", true, + new Command() { + + @Override + public void execute(Grid grid, Boolean value, Object data) { + grid.setHeaderVisible(value); + } + }); + + LinkedHashMap defaultRows = new LinkedHashMap(); + defaultRows.put("Top", "Top"); + defaultRows.put("Bottom", "Bottom"); + defaultRows.put("Unset", "Unset"); + + createMultiClickAction("Default row", "Header", defaultRows, + new Command() { + + @Override + public void execute(Grid grid, String value, Object data) { + HeaderRow defaultRow = null; + if (value.equals("Top")) { + defaultRow = grid.getHeaderRow(0); + } else if (value.equals("Bottom")) { + defaultRow = grid.getHeaderRow(grid + .getHeaderRowCount() - 1); + } + grid.setDefaultHeaderRow(defaultRow); + } + + }, defaultRows.get("Top")); + + createClickAction("Prepend row", "Header", new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.prependHeaderRow(); + } + + }, null); + createClickAction("Append row", "Header", new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.appendHeaderRow(); + } + + }, null); + + createClickAction("Remove top row", "Header", + new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.removeHeaderRow(0); + } + + }, null); + createClickAction("Remove bottom row", "Header", + new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.removeHeaderRow(grid.getHeaderRowCount() - 1); + } + + }, null); + } + + protected void createFooterActions() { + createCategory("Footer", null); + + createBooleanAction("Visible", "Footer", false, + new Command() { + + @Override + public void execute(Grid grid, Boolean value, Object data) { + grid.setFooterVisible(value); + } + }); + + createClickAction("Prepend row", "Footer", new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.prependFooterRow(); + } + + }, null); + createClickAction("Append row", "Footer", new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.appendFooterRow(); + } + + }, null); + + createClickAction("Remove top row", "Footer", + new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.removeFooterRow(0); + } + + }, null); + createClickAction("Remove bottom row", "Footer", + new Command() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.removeFooterRow(grid.getFooterRowCount() - 1); + } + + }, null); + } + + protected void createColumnActions() { + createCategory("Columns", null); + + for (int c = 0; c < COLUMNS; c++) { + final int index = c; + createCategory(getColumnProperty(c), "Columns"); + + createClickAction("Add / Remove", getColumnProperty(c), + new Command() { + + @Override + public void execute(Grid grid, String value, Object data) { + String columnProperty = getColumnProperty((Integer) data); + if (grid.getColumn(columnProperty) == null) { + grid.addColumn(columnProperty); + } else { + grid.removeColumn(columnProperty); + } + } + }, null, c); + + createBooleanAction("Sortable", getColumnProperty(c), true, + new Command() { + + @Override + public void execute(Grid grid, Boolean value, + Object columnIndex) { + Object propertyId = getColumnProperty((Integer) columnIndex); + Column column = grid.getColumn(propertyId); + column.setSortable(value); + } + }, c); + + createCategory("Column " + c + " Width", getColumnProperty(c)); + + createClickAction("Auto", "Column " + c + " Width", + new Command() { + + @Override + public void execute(Grid grid, Integer value, + Object columnIndex) { + Object propertyId = getColumnProperty((Integer) columnIndex); + Column column = grid.getColumn(propertyId); + column.setWidthUndefined(); + } + }, -1, c); + + createClickAction("25.5px", "Column " + c + " Width", + new Command() { + @Override + @SuppressWarnings("boxing") + public void execute(Grid grid, Void value, + Object columnIndex) { + grid.getColumns().get((Integer) columnIndex) + .setWidth(25.5); + } + }, null, c); + + for (int w = 50; w < 300; w += 50) { + createClickAction(w + "px", "Column " + c + " Width", + new Command() { + + @Override + public void execute(Grid grid, Integer value, + Object columnIndex) { + Object propertyId = getColumnProperty((Integer) columnIndex); + Column column = grid.getColumn(propertyId); + column.setWidth(value); + } + }, w, c); + } + + LinkedHashMap defaultRows = new LinkedHashMap(); + defaultRows.put("Text Header", GridStaticCellType.TEXT); + defaultRows.put("Html Header ", GridStaticCellType.HTML); + defaultRows.put("Widget Header", GridStaticCellType.WIDGET); + + createMultiClickAction("Header Type", getColumnProperty(c), + defaultRows, new Command() { + + @Override + public void execute(Grid grid, + GridStaticCellType value, Object columnIndex) { + final Object propertyId = getColumnProperty((Integer) columnIndex); + final HeaderCell cell = grid.getDefaultHeaderRow() + .getCell(propertyId); + switch (value) { + case TEXT: + cell.setText("Text Header"); + break; + case HTML: + cell.setHtml("HTML Header"); + break; + case WIDGET: + cell.setComponent(new Button("Button Header", + new ClickListener() { + + @Override + public void buttonClick( + ClickEvent event) { + log("Button clicked!"); + } + })); + default: + break; + } + } + + }, c); + + defaultRows = new LinkedHashMap(); + defaultRows.put("Text Footer", GridStaticCellType.TEXT); + defaultRows.put("Html Footer", GridStaticCellType.HTML); + defaultRows.put("Widget Footer", GridStaticCellType.WIDGET); + + createMultiClickAction("Footer Type", getColumnProperty(c), + defaultRows, new Command() { + + @Override + public void execute(Grid grid, + GridStaticCellType value, Object columnIndex) { + final Object propertyId = getColumnProperty((Integer) columnIndex); + final FooterCell cell = grid.getFooterRow(0) + .getCell(propertyId); + switch (value) { + case TEXT: + cell.setText("Text Footer"); + break; + case HTML: + cell.setHtml("HTML Footer"); + break; + case WIDGET: + cell.setComponent(new Button("Button Footer", + new ClickListener() { + + @Override + public void buttonClick( + ClickEvent event) { + log("Button clicked!"); + } + })); + default: + break; + } + } + + }, c); + } + } + + private static String getColumnProperty(int c) { + return "Column " + c; + } + + protected void createPropertyActions() { + createCategory("Properties", null); + + createBooleanAction("Prepend property", "Properties", false, + new Command() { + private final Object propertyId = new Object(); + + @Override + public void execute(Grid c, Boolean enable, Object data) { + if (enable.booleanValue()) { + ds.addContainerProperty(propertyId, String.class, + "property value"); + grid.getColumn(propertyId).setHeaderCaption( + "new property"); + grid.setColumnOrder(propertyId); + } else { + ds.removeContainerProperty(propertyId); + } + } + }, null); + } + + protected void createRowActions() { + createCategory("Body rows", null); + + class NewRowCommand implements Command { + private final int index; + + public NewRowCommand() { + this(0); + } + + public NewRowCommand(int index) { + this.index = index; + } + + @Override + public void execute(Grid c, String value, Object data) { + Item item = ds.addItemAt(index, new Object()); + for (int i = 0; i < COLUMNS; i++) { + Class type = ds.getType(getColumnProperty(i)); + if (String.class.isAssignableFrom(type)) { + Property itemProperty = getProperty(item, i); + itemProperty.setValue("newcell: " + i); + } else if (Integer.class.isAssignableFrom(type)) { + Property itemProperty = getProperty(item, i); + itemProperty.setValue(Integer.valueOf(i)); + } else { + // let the default value be taken implicitly. + } + } + } + + private Property getProperty(Item item, int i) { + @SuppressWarnings("unchecked") + Property itemProperty = item + .getItemProperty(getColumnProperty(i)); + return itemProperty; + } + } + final NewRowCommand newRowCommand = new NewRowCommand(); + + createClickAction("Add 18 rows", "Body rows", + new Command() { + @Override + public void execute(Grid c, String value, Object data) { + for (int i = 0; i < 18; i++) { + newRowCommand.execute(c, value, data); + } + } + }, null); + + createClickAction("Add first row", "Body rows", newRowCommand, null); + + createClickAction("Add second row", "Body rows", new NewRowCommand(1), + null); + + createClickAction("Remove first row", "Body rows", + new Command() { + @Override + public void execute(Grid c, String value, Object data) { + Object firstItemId = ds.getIdByIndex(0); + ds.removeItem(firstItemId); + } + }, null); + + createClickAction("Remove 18 first rows", "Body rows", + new Command() { + @Override + public void execute(Grid c, String value, Object data) { + for (int i = 0; i < 18; i++) { + Object firstItemId = ds.getIdByIndex(0); + ds.removeItem(firstItemId); + } + } + }, null); + + createClickAction("Modify first row (getItemProperty)", "Body rows", + new Command() { + @SuppressWarnings("unchecked") + @Override + public void execute(Grid c, String value, Object data) { + Object firstItemId = ds.getIdByIndex(0); + Item item = ds.getItem(firstItemId); + for (int i = 0; i < COLUMNS; i++) { + Property property = item + .getItemProperty(getColumnProperty(i)); + if (property.getType().equals(String.class)) { + ((Property) property) + .setValue("modified: " + i); + } + } + } + }, null); + + createClickAction("Modify first row (getContainerProperty)", + "Body rows", new Command() { + @SuppressWarnings("unchecked") + @Override + public void execute(Grid c, String value, Object data) { + Object firstItemId = ds.getIdByIndex(0); + for (Object containerPropertyId : ds + .getContainerPropertyIds()) { + Property property = ds.getContainerProperty( + firstItemId, containerPropertyId); + if (property.getType().equals(String.class)) { + ((Property) property) + .setValue("modified: " + + containerPropertyId); + } + } + } + }, null); + + createBooleanAction("Select first row", "Body rows", false, + new Command() { + @Override + public void execute(Grid grid, Boolean select, Object data) { + final Object firstItemId = grid + .getContainerDataSource().firstItemId(); + if (select.booleanValue()) { + grid.select(firstItemId); + } else { + grid.deselect(firstItemId); + } + } + }); + + createClickAction("Remove all rows", "Body rows", + new Command() { + @SuppressWarnings("unchecked") + @Override + public void execute(Grid c, String value, Object data) { + ds.removeAllItems(); + } + }, null); + } + + protected void createEditorRowActions() { + createBooleanAction("Enabled", "Editor row", false, + new Command() { + @Override + public void execute(Grid c, Boolean value, Object data) { + c.setEditorRowEnabled(value); + } + }); + + createClickAction("Edit item 5", "Editor row", + new Command() { + @Override + public void execute(Grid c, String value, Object data) { + c.editItem(5); + } + }, null); + + createClickAction("Edit item 100", "Editor row", + new Command() { + @Override + public void execute(Grid c, String value, Object data) { + c.editItem(100); + } + }, null); + createClickAction("Save", "Editor row", new Command() { + @Override + public void execute(Grid c, String value, Object data) { + try { + c.saveEditorRow(); + } catch (CommitException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + }, null); + createClickAction("Cancel edit", "Editor row", + new Command() { + @Override + public void execute(Grid c, String value, Object data) { + c.cancelEditorRow(); + } + }, null); + } + + @SuppressWarnings("boxing") + protected void addHeightActions() { + createCategory("Height by Rows", "Size"); + + createBooleanAction("HeightMode Row", "Size", false, + new Command() { + @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); + } + + Command sizeCommand = new Command() { + @Override + public void execute(Grid grid, String height, Object data) { + grid.setHeight(height); + } + }; + + createCategory("Height", "Size"); + // header 20px + scrollbar 16px = 36px baseline + createClickAction("86px (no drag scroll select)", "Height", + sizeCommand, "86px"); + createClickAction("96px (drag scroll select limit)", "Height", + sizeCommand, "96px"); + createClickAction("106px (drag scroll select enabled)", "Height", + sizeCommand, "106px"); + } + + private void addActionForHeightByRows(final Double i) { + DecimalFormat df = new DecimalFormat("0.00"); + createClickAction(df.format(i) + " rows", "Height by Rows", + new Command() { + @Override + public void execute(Grid c, String value, Object data) { + c.setHeightByRows(i); + } + }, null); + } + + @Override + protected Integer getTicketNumber() { + return 12829; + } + + @Override + protected Class getTestClass() { + return Grid.class; + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java index f1d64a50e7..88ad1fcd5a 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java @@ -65,18 +65,18 @@ public class EscalatorProxy extends Escalator { } @Override - public void setColumnWidth(int index, int px) + public void setColumnWidth(int index, double px) throws IllegalArgumentException { columnConfiguration.setColumnWidth(index, px); } @Override - public int getColumnWidth(int index) throws IllegalArgumentException { + public double getColumnWidth(int index) throws IllegalArgumentException { return columnConfiguration.getColumnWidth(index); } @Override - public int getColumnWidthActual(int index) + public double getColumnWidthActual(int index) throws IllegalArgumentException { return columnConfiguration.getColumnWidthActual(index); } -- 2.39.5