SelectionColumns do that now automatically. Colspanned cells get ignored Change-Id: Ie427ba8df43ad84786c381def8cec216297feb06tags/7.4.0.beta1
@@ -126,19 +126,6 @@ public interface ColumnConfiguration { | |||
public void setColumnWidth(int index, int px) | |||
throws IllegalArgumentException; | |||
/** | |||
* Sets the column width to as wide as the widest currently visible content | |||
* in that column. | |||
* | |||
* @param index | |||
* the index of the column for which to calculate the width. | |||
* @throws IllegalArgumentException | |||
* if {@code index} is not a valid column index, or if any cell | |||
* in the given column is a part of a colspan range | |||
*/ | |||
public void setColumnWidthToContent(int index) | |||
throws IllegalArgumentException; | |||
/** | |||
* Returns the user-defined width of a column. | |||
* |
@@ -1087,8 +1087,48 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
} | |||
} | |||
protected abstract class AbstractRowContainer implements RowContainer { | |||
private class ColumnAutoWidthAssignScheduler { | |||
private boolean isScheduled = false; | |||
private final ScheduledCommand widthCommand = new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
if (!isScheduled) { | |||
return; | |||
} | |||
isScheduled = false; | |||
ColumnConfigurationImpl cc = columnConfiguration; | |||
for (int col = 0; col < cc.getColumnCount(); col++) { | |||
ColumnConfigurationImpl.Column column = cc.columns.get(col); | |||
if (!column.isWidthFinalized()) { | |||
cc.setColumnWidth(col, -1); | |||
column.widthIsFinalized(); | |||
} | |||
} | |||
} | |||
}; | |||
/** | |||
* Calculates the widths of all uncalculated cells once the javascript | |||
* execution is done. | |||
* <p> | |||
* This method makes sure that any duplicate requests in the same cycle | |||
* are ignored. | |||
*/ | |||
public void reschedule() { | |||
if (!isScheduled) { | |||
isScheduled = true; | |||
Scheduler.get().scheduleFinally(widthCommand); | |||
} | |||
} | |||
public void cancel() { | |||
isScheduled = false; | |||
} | |||
} | |||
protected abstract class AbstractRowContainer implements RowContainer { | |||
private EscalatorUpdater updater = EscalatorUpdater.NULL; | |||
private int rows; | |||
@@ -1304,6 +1344,19 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
*/ | |||
if (isAttached()) { | |||
paintInsertRows(index, numberOfRows); | |||
if (rows == numberOfRows) { | |||
/* | |||
* We are inserting the first rows in this container. We | |||
* potentially need to autocalculate the widths for the | |||
* cells for the first time. | |||
* | |||
* To make sure that can take the entire dataset into | |||
* account, we'll do this deferredly, so that each container | |||
* section gets populated before we start calculating. | |||
*/ | |||
columnAutoWidthAssignScheduler.reschedule(); | |||
} | |||
} | |||
} | |||
@@ -1907,6 +1960,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
int getMaxCellWidth(int colIndex) throws IllegalArgumentException { | |||
int maxCellWidth = -1; | |||
assert isAttached() : "Can't measure max width of cell, since Escalator is not attached to the DOM."; | |||
NodeList<TableRowElement> rows = root.getRows(); | |||
for (int row = 0; row < rows.getLength(); row++) { | |||
TableRowElement rowElement = rows.getItem(row); | |||
@@ -1914,8 +1969,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
colIndex); | |||
if (cellIsPartOfSpan(cellOriginal)) { | |||
throw new IllegalArgumentException("Encountered a column " | |||
+ "spanned cell in column " + colIndex + "."); | |||
continue; | |||
} | |||
/* | |||
@@ -3632,18 +3686,86 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
private int definedWidth = -1; | |||
private int calculatedWidth = DEFAULT_COLUMN_WIDTH_PX; | |||
private boolean measuringRequested = false; | |||
/** | |||
* If a column has been created (either via insertRow or | |||
* insertColumn), it will be given an arbitrary width, and only then | |||
* a width will be defined. | |||
*/ | |||
private boolean widthHasBeenFinalized = false; | |||
public void setWidth(int px) { | |||
definedWidth = px; | |||
calculatedWidth = (px >= 0) ? px : DEFAULT_COLUMN_WIDTH_PX; | |||
if (px < 0) { | |||
if (isAttached()) { | |||
calculateWidth(); | |||
} else { | |||
/* | |||
* the column's width is calculated at Escalator.onLoad | |||
* via measureIfNeeded! | |||
*/ | |||
measuringRequested = true; | |||
} | |||
} else { | |||
calculatedWidth = px; | |||
} | |||
} | |||
public int getDefinedWidth() { | |||
return definedWidth; | |||
} | |||
/** | |||
* Returns the actual width in the DOM. | |||
* | |||
* @return the width in pixels in the DOM. Returns -1 if the column | |||
* needs measuring, but has not been yet measured | |||
*/ | |||
public int getCalculatedWidth() { | |||
return calculatedWidth; | |||
/* | |||
* This might return an untrue value (e.g. during init/onload), | |||
* since we haven't had a proper chance to actually calculate | |||
* widths yet. | |||
* | |||
* This is fixed during Escalator.onLoad, by the call to | |||
* "measureIfNeeded", which fixes "everything". | |||
*/ | |||
if (!measuringRequested) { | |||
return calculatedWidth; | |||
} else { | |||
return -1; | |||
} | |||
} | |||
/** | |||
* Checks if the column needs measuring, and then measures it. | |||
* <p> | |||
* Called by {@link Escalator#onLoad()}. | |||
*/ | |||
public boolean measureAndSetWidthIfNeeded() { | |||
assert isAttached() : "Column.measureIfNeeded() was called even though Escalator was not attached!"; | |||
if (measuringRequested) { | |||
measuringRequested = false; | |||
setWidth(definedWidth); | |||
return true; | |||
} | |||
return false; | |||
} | |||
private void calculateWidth() { | |||
calculatedWidth = getMaxCellWidth(columns.indexOf(this)); | |||
} | |||
public void widthIsFinalized() { | |||
columnAutoWidthAssignScheduler.cancel(); | |||
widthHasBeenFinalized = true; | |||
} | |||
public boolean isWidthFinalized() { | |||
return widthHasBeenFinalized; | |||
} | |||
} | |||
@@ -3834,6 +3956,15 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
body.paintInsertColumns(index, numberOfColumns, frozen); | |||
footer.paintInsertColumns(index, numberOfColumns, frozen); | |||
// fix autowidth | |||
if (header.getRowCount() > 0 || body.getRowCount() > 0 | |||
|| footer.getRowCount() > 0) { | |||
for (int col = index; col < index + numberOfColumns; col++) { | |||
getColumnConfiguration().setColumnWidth(col, -1); | |||
columnConfiguration.columns.get(col).widthIsFinalized(); | |||
} | |||
} | |||
// Adjust scrollbar | |||
int pixelsToInsertedColumn = columnConfiguration | |||
.getCalculatedColumnsWidth(Range.withLength(0, index)); | |||
@@ -3916,6 +4047,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
checkValidColumnIndex(index); | |||
columns.get(index).setWidth(px); | |||
columns.get(index).widthIsFinalized(); | |||
widthsArray = null; | |||
/* | |||
@@ -3947,33 +4079,16 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
return columns.get(index).getCalculatedWidth(); | |||
} | |||
@Override | |||
public void setColumnWidthToContent(int index) | |||
throws IllegalArgumentException { | |||
if (index < 0 || index >= getColumnCount()) { | |||
throw new IllegalArgumentException(index | |||
+ " is not a valid index for a column"); | |||
} | |||
int maxWidth = getMaxCellWidth(index); | |||
if (maxWidth == -1) { | |||
return; | |||
} | |||
setCalculatedColumnWidth(index, maxWidth); | |||
header.reapplyColumnWidths(); | |||
footer.reapplyColumnWidths(); | |||
body.reapplyColumnWidths(); | |||
} | |||
private int getMaxCellWidth(int colIndex) | |||
throws IllegalArgumentException { | |||
int headerWidth = header.getMaxCellWidth(colIndex); | |||
int bodyWidth = body.getMaxCellWidth(colIndex); | |||
int footerWidth = footer.getMaxCellWidth(colIndex); | |||
return Math.max(headerWidth, Math.max(bodyWidth, footerWidth)); | |||
int maxWidth = Math.max(headerWidth, | |||
Math.max(bodyWidth, footerWidth)); | |||
assert maxWidth > 0 : "Got a negative max width for a column, which should be impossible."; | |||
return maxWidth; | |||
} | |||
/** | |||
@@ -3997,16 +4112,12 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
int sum = 0; | |||
for (int i = columns.getStart(); i < columns.getEnd(); i++) { | |||
sum += getColumnWidthActual(i); | |||
int columnWidthActual = getColumnWidthActual(i); | |||
sum += columnWidthActual; | |||
} | |||
return sum; | |||
} | |||
void setCalculatedColumnWidth(int index, int width) { | |||
columns.get(index).calculatedWidth = width; | |||
widthsArray = null; | |||
} | |||
int[] getCalculatedColumnWidths() { | |||
if (widthsArray == null || widthsArray.length != getColumnCount()) { | |||
widthsArray = new int[getColumnCount()]; | |||
@@ -4136,6 +4247,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
} | |||
}; | |||
private final ColumnAutoWidthAssignScheduler columnAutoWidthAssignScheduler = new ColumnAutoWidthAssignScheduler(); | |||
private static native double getPreciseWidth(Element element) | |||
/*-{ | |||
if (element.getBoundingClientRect) { | |||
@@ -4257,6 +4370,19 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
* rows. | |||
*/ | |||
boolean columnsChanged = false; | |||
for (ColumnConfigurationImpl.Column column : columnConfiguration.columns) { | |||
boolean columnChanged = column.measureAndSetWidthIfNeeded(); | |||
if (columnChanged) { | |||
columnsChanged = true; | |||
} | |||
} | |||
if (columnsChanged) { | |||
header.reapplyColumnWidths(); | |||
body.reapplyColumnWidths(); | |||
footer.reapplyColumnWidths(); | |||
} | |||
scroller.attachScrollListener(verticalScrollbar.getElement()); | |||
scroller.attachScrollListener(horizontalScrollbar.getElement()); | |||
scroller.attachMousewheelListener(getElement()); | |||
@@ -4694,50 +4820,6 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
return null; | |||
} | |||
/** | |||
* Forces the escalator to recalculate the widths of its columns. | |||
* <p> | |||
* All columns that haven't been assigned an explicit width will be resized | |||
* to fit all currently visible contents. | |||
* | |||
* @see ColumnConfiguration#setColumnWidth(int, int) | |||
*/ | |||
public void calculateColumnWidths() { | |||
boolean widthsHaveChanged = false; | |||
for (int colIndex = 0; colIndex < columnConfiguration.getColumnCount(); colIndex++) { | |||
if (columnConfiguration.getColumnWidth(colIndex) >= 0) { | |||
continue; | |||
} | |||
final int oldColumnWidth = columnConfiguration | |||
.getColumnWidthActual(colIndex); | |||
int maxColumnWidth = 0; | |||
maxColumnWidth = Math.max(maxColumnWidth, | |||
header.calculateMaxColWidth(colIndex)); | |||
maxColumnWidth = Math.max(maxColumnWidth, | |||
body.calculateMaxColWidth(colIndex)); | |||
maxColumnWidth = Math.max(maxColumnWidth, | |||
footer.calculateMaxColWidth(colIndex)); | |||
Logger.getLogger("Escalator.calculateColumnWidths").info( | |||
"#" + colIndex + ": " + maxColumnWidth + "px"); | |||
if (oldColumnWidth != maxColumnWidth) { | |||
columnConfiguration.setCalculatedColumnWidth(colIndex, | |||
maxColumnWidth); | |||
widthsHaveChanged = true; | |||
} | |||
} | |||
if (widthsHaveChanged) { | |||
header.reapplyColumnWidths(); | |||
body.reapplyColumnWidths(); | |||
footer.reapplyColumnWidths(); | |||
recalculateElementSizes(); | |||
} | |||
} | |||
@Override | |||
public void setStylePrimaryName(String style) { | |||
super.setStylePrimaryName(style); | |||
@@ -4954,7 +5036,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker | |||
@Override | |||
public boolean isWorkPending() { | |||
return body.domSorter.waiting; | |||
return body.domSorter.waiting | |||
|| columnAutoWidthAssignScheduler.isScheduled; | |||
} | |||
@Override |
@@ -91,6 +91,7 @@ import com.vaadin.client.ui.grid.sort.Sort; | |||
import com.vaadin.client.ui.grid.sort.SortEvent; | |||
import com.vaadin.client.ui.grid.sort.SortHandler; | |||
import com.vaadin.client.ui.grid.sort.SortOrder; | |||
import com.vaadin.shared.ui.grid.GridColumnState; | |||
import com.vaadin.shared.ui.grid.GridConstants; | |||
import com.vaadin.shared.ui.grid.GridStaticCellType; | |||
import com.vaadin.shared.ui.grid.HeightMode; | |||
@@ -1494,6 +1495,9 @@ public class Grid<T> extends ResizeComposite implements | |||
}); | |||
header.getDefaultRow().getCell(this).setWidget(checkBox); | |||
} | |||
setWidth(-1); | |||
initDone = true; | |||
} | |||
@@ -1775,15 +1779,66 @@ public class Grid<T> extends ResizeComposite implements | |||
} | |||
} | |||
private final class AsyncWidthAutodetectRunner { | |||
private static final int POLLING_PERIOD_MS = 50; | |||
private final Timer timer = new Timer() { | |||
@Override | |||
public void run() { | |||
/* Detaching the column from the grid should've cancelled */ | |||
assert grid != null : "Column was detached from Grid before width autodetection completed"; | |||
/* | |||
* setting a positive value for the width should've | |||
* cancelled | |||
*/ | |||
assert widthUser < 0 : "User defined width is not negative (to indicate autodetection) anymore!"; | |||
if (!grid.dataIsBeingFetched) { | |||
setWidthForce(widthUser); | |||
} else { | |||
timer.schedule(POLLING_PERIOD_MS); | |||
return; | |||
} | |||
} | |||
}; | |||
/** | |||
* Schedules an width autodetection. | |||
* <p> | |||
* It's not done immediately in case we're retrieving some lazy | |||
* data, that will affect the appropriate width of the cells. | |||
*/ | |||
public void reschedule() { | |||
/* | |||
* Check immediately. This will be _actually_ rescheduled if | |||
* things don't work out. Otherwise, autodetectionage will | |||
* happen. | |||
*/ | |||
timer.schedule(0); | |||
} | |||
public void stop() { | |||
timer.cancel(); | |||
} | |||
public boolean isRunning() { | |||
return timer.isRunning(); | |||
} | |||
} | |||
/** | |||
* the column is associated with | |||
*/ | |||
private Grid<T> grid; | |||
/** | |||
* Width of column in pixels | |||
* Should the column be visible in the grid | |||
*/ | |||
private int width = 100; | |||
private boolean visible = true; | |||
/** Width of column in pixels as {@link #setWidth(int)} has been called */ | |||
private int widthUser = GridColumnState.DEFAULT_COLUMN_WIDTH_PX; | |||
/** | |||
* Renderer for rendering a value into the cell | |||
@@ -1794,6 +1849,8 @@ public class Grid<T> extends ResizeComposite implements | |||
private String headerText = ""; | |||
private final AsyncWidthAutodetectRunner asyncAutodetectWidth = new AsyncWidthAutodetectRunner(); | |||
/** | |||
* Constructs a new column with a simple TextRenderer. | |||
*/ | |||
@@ -1863,6 +1920,8 @@ public class Grid<T> extends ResizeComposite implements | |||
this.grid = grid; | |||
if (grid != null) { | |||
updateHeader(); | |||
} else { | |||
asyncAutodetectWidth.stop(); | |||
} | |||
} | |||
@@ -1958,29 +2017,70 @@ public class Grid<T> extends ResizeComposite implements | |||
* @return the column itself | |||
*/ | |||
public GridColumn<C, T> setWidth(int pixels) { | |||
width = pixels; | |||
widthUser = pixels; | |||
if (pixels < 0) { | |||
setWidthAutodetect(); | |||
} else { | |||
setWidthAbsolute(pixels); | |||
} | |||
return (GridColumn<C, T>) this; | |||
} | |||
private void setWidthAutodetect() { | |||
if (grid != null) { | |||
int index = grid.indexOfColumn((GridColumn<?, T>) this); | |||
ColumnConfiguration conf = grid.escalator | |||
.getColumnConfiguration(); | |||
conf.setColumnWidth(index, pixels); | |||
asyncAutodetectWidth.reschedule(); | |||
} | |||
return (GridColumn<C, T>) this; | |||
/* | |||
* It's okay if the colum isn't attached to a grid immediately. The | |||
* width will be re-set once it gets attached. | |||
*/ | |||
} | |||
private void setWidthAbsolute(int pixels) { | |||
asyncAutodetectWidth.stop(); | |||
if (grid != null) { | |||
setWidthForce(pixels); | |||
} | |||
} | |||
private void setWidthForce(int pixels) { | |||
int index = grid.columns.indexOf(this); | |||
ColumnConfiguration conf = grid.escalator.getColumnConfiguration(); | |||
conf.setColumnWidth(index, pixels); | |||
} | |||
/** | |||
* Returns the pixel width of the column | |||
* Returns the pixel width of the column as given by the user. | |||
* <p> | |||
* <em>Note:</em> If a negative value was given to | |||
* {@link #setWidth(int)}, that same negative value is returned here. | |||
* | |||
* @return pixel width of the column | |||
* @return pixel width of the column, or a negative number if the column | |||
* width has been automatically calculated. | |||
* @see #setWidth(int) | |||
* @see #getWidthActual() | |||
*/ | |||
public int getWidth() { | |||
return width; | |||
return widthUser; | |||
} | |||
/** | |||
* Returns the effective pixel width of the column. | |||
* <p> | |||
* This differs from {@link #getWidth()} only when the column has been | |||
* automatically resized. | |||
* | |||
* @return pixel width of the column. | |||
*/ | |||
public int getWidthActual() { | |||
return grid.escalator.getColumnConfiguration() | |||
.getColumnWidthActual(grid.columns.indexOf(this)); | |||
} | |||
void reapplyWidth() { | |||
setWidth(width); | |||
setWidth(getWidth()); | |||
} | |||
/** | |||
@@ -2038,6 +2138,10 @@ public class Grid<T> extends ResizeComposite implements | |||
return getClass().getSimpleName() + "[" + details.trim() + "]"; | |||
} | |||
boolean widthCalculationPending() { | |||
return asyncAutodetectWidth.isRunning(); | |||
} | |||
} | |||
protected class BodyUpdater implements EscalatorUpdater { | |||
@@ -3166,6 +3270,7 @@ public class Grid<T> extends ResizeComposite implements | |||
body.removeRows(newSize, oldSize - newSize); | |||
} | |||
dataIsBeingFetched = true; | |||
Range visibleRowRange = escalator.getVisibleRowRange(); | |||
dataSource.ensureAvailability(visibleRowRange.getStart(), | |||
visibleRowRange.length()); | |||
@@ -3896,8 +4001,6 @@ public class Grid<T> extends ResizeComposite implements | |||
cellFocusHandler.offsetRangeBy(1); | |||
selectionColumn = new SelectionColumn(selectColumnRenderer); | |||
// FIXME: this needs to be done elsewhere, requires design... | |||
selectionColumn.setWidth(40); | |||
addColumnSkipSelectionColumnCheck(selectionColumn, 0); | |||
selectionColumn.initDone(); | |||
} else { | |||
@@ -4174,8 +4277,10 @@ public class Grid<T> extends ResizeComposite implements | |||
Scheduler.get().scheduleFinally(new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
handler.onDataAvailable(new DataAvailableEvent( | |||
currentDataAvailable)); | |||
if (!dataIsBeingFetched) { | |||
handler.onDataAvailable(new DataAvailableEvent( | |||
currentDataAvailable)); | |||
} | |||
} | |||
}); | |||
return addHandler(handler, DataAvailableEvent.TYPE); | |||
@@ -4386,7 +4491,17 @@ public class Grid<T> extends ResizeComposite implements | |||
@Override | |||
public boolean isWorkPending() { | |||
return escalator.isWorkPending() || dataIsBeingFetched; | |||
return escalator.isWorkPending() || dataIsBeingFetched | |||
|| anyColumnIsBeingResized(); | |||
} | |||
private boolean anyColumnIsBeingResized() { | |||
for (AbstractGridColumn<?, ?> column : columns) { | |||
if (column.widthCalculationPending()) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** |
@@ -15,7 +15,6 @@ | |||
*/ | |||
package com.vaadin.client.ui.grid; | |||
/** | |||
* Represents a column in the {@link Grid}. | |||
* |
@@ -28,6 +28,8 @@ import com.vaadin.shared.Connector; | |||
*/ | |||
public class GridColumnState implements Serializable { | |||
public static final int DEFAULT_COLUMN_WIDTH_PX = -1; | |||
/** | |||
* Id used by grid connector to map server side column with client side | |||
* column | |||
@@ -35,9 +37,10 @@ public class GridColumnState implements Serializable { | |||
public String id; | |||
/** | |||
* Column width in pixels. Default column width is 100px. | |||
* Column width in pixels. Default column width is | |||
* {@value #DEFAULT_COLUMN_WIDTH_PX}. | |||
*/ | |||
public int width = 100; | |||
public int width = DEFAULT_COLUMN_WIDTH_PX; | |||
/** | |||
* The connector for the renderer used to render the cells in this column. |
@@ -0,0 +1,94 @@ | |||
/* | |||
* 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; | |||
import static org.junit.Assert.assertEquals; | |||
import org.junit.Before; | |||
import org.junit.Test; | |||
import org.openqa.selenium.By; | |||
import org.openqa.selenium.WebElement; | |||
import com.vaadin.tests.tb3.MultiBrowserTest; | |||
@SuppressWarnings("boxing") | |||
public abstract class AbstractGridColumnAutoWidthTest extends MultiBrowserTest { | |||
public static final int TOTAL_MARGIN_PX = 13; | |||
@Before | |||
public void before() { | |||
openTestURL(); | |||
} | |||
@Test | |||
public void testNarrowHeaderWideBody() { | |||
WebElement[] col = getColumn(1); | |||
int headerWidth = col[0].getSize().getWidth(); | |||
int bodyWidth = col[1].getSize().getWidth(); | |||
int colWidth = col[2].getSize().getWidth() - TOTAL_MARGIN_PX; | |||
assertLessThan("header should've been narrower than body", headerWidth, | |||
bodyWidth); | |||
assertEquals("column should've been roughly as wide as the body", | |||
bodyWidth, colWidth, 5); | |||
} | |||
@Test | |||
public void testWideHeaderNarrowBody() { | |||
WebElement[] col = getColumn(2); | |||
int headerWidth = col[0].getSize().getWidth(); | |||
int bodyWidth = col[1].getSize().getWidth(); | |||
int colWidth = col[2].getSize().getWidth() - TOTAL_MARGIN_PX; | |||
assertGreater("header should've been wider than body", headerWidth, | |||
bodyWidth); | |||
assertEquals("column should've been roughly as wide as the header", | |||
headerWidth, colWidth, 5); | |||
} | |||
@Test | |||
public void testTooNarrowColumn() { | |||
WebElement[] col = getColumn(3); | |||
int headerWidth = col[0].getSize().getWidth(); | |||
int colWidth = col[2].getSize().getWidth() - TOTAL_MARGIN_PX; | |||
assertLessThan("column should've been narrower than content", colWidth, | |||
headerWidth); | |||
} | |||
@Test | |||
public void testTooWideColumn() { | |||
WebElement[] col = getColumn(4); | |||
int headerWidth = col[0].getSize().getWidth(); | |||
int colWidth = col[2].getSize().getWidth() - TOTAL_MARGIN_PX; | |||
assertGreater("column should've been wider than content", colWidth, | |||
headerWidth); | |||
} | |||
private WebElement[] getColumn(int i) { | |||
WebElement[] col = new WebElement[3]; | |||
col[0] = getDriver().findElement( | |||
By.xpath("//thead//th[" + (i + 1) + "]/span")); | |||
col[1] = getDriver().findElement( | |||
By.xpath("//tbody//td[" + (i + 1) + "]/span")); | |||
col[2] = getDriver().findElement( | |||
By.xpath("//tbody//td[" + (i + 1) + "]")); | |||
return col; | |||
} | |||
} |
@@ -0,0 +1,62 @@ | |||
/* | |||
* 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; | |||
import com.vaadin.data.Container; | |||
import com.vaadin.data.util.IndexedContainer; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.ui.Grid; | |||
import com.vaadin.ui.Grid.Column; | |||
import com.vaadin.ui.Grid.SelectionMode; | |||
import com.vaadin.ui.components.grid.renderers.HtmlRenderer; | |||
public class GridColumnAutoWidth extends AbstractTestUI { | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
Grid grid = new Grid(createContainer()); | |||
grid.getColumn("fixed width narrow").setWidth(50); | |||
grid.getColumn("fixed width wide").setWidth(200); | |||
for (Object propertyId : grid.getContainerDataSource() | |||
.getContainerPropertyIds()) { | |||
Column column = grid.getColumn(propertyId); | |||
column.setRenderer(new HtmlRenderer()); | |||
grid.getHeaderRow(0).getCell(propertyId) | |||
.setHtml("<span>" + column.getHeaderCaption() + "</span>"); | |||
} | |||
grid.setSelectionMode(SelectionMode.NONE); | |||
grid.setWidth("700px"); | |||
addComponent(grid); | |||
} | |||
private static Container.Indexed createContainer() { | |||
IndexedContainer c = new IndexedContainer(); | |||
c.addContainerProperty("equal width", String.class, | |||
"<span>equal width</span>"); | |||
c.addContainerProperty("short", String.class, | |||
"<span>a very long cell content</span>"); | |||
c.addContainerProperty("a very long header content", String.class, | |||
"<span>short</span>"); | |||
c.addContainerProperty("fixed width narrow", String.class, | |||
"<span>fixed width narrow</span>"); | |||
c.addContainerProperty("fixed width wide", String.class, | |||
"<span>fixed width wide</span>"); | |||
c.addItem(); | |||
return c; | |||
} | |||
} |
@@ -0,0 +1,35 @@ | |||
/* | |||
* 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; | |||
import com.vaadin.annotations.Widgetset; | |||
import com.vaadin.server.VaadinRequest; | |||
import com.vaadin.tests.components.AbstractTestUI; | |||
import com.vaadin.tests.widgetset.TestingWidgetSet; | |||
import com.vaadin.ui.AbstractComponent; | |||
@Widgetset(TestingWidgetSet.NAME) | |||
public class GridColumnAutoWidthClient extends AbstractTestUI { | |||
public static class GridColumnAutoWidthClientComponent extends | |||
AbstractComponent { | |||
} | |||
@Override | |||
protected void setup(VaadinRequest request) { | |||
addComponent(new GridColumnAutoWidthClientComponent()); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
/* | |||
* 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; | |||
import com.vaadin.tests.annotations.TestCategory; | |||
@TestCategory("grid") | |||
public class GridColumnAutoWidthClientTest extends | |||
AbstractGridColumnAutoWidthTest { | |||
@Override | |||
protected Class<?> getUIClass() { | |||
return GridColumnAutoWidthClient.class; | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
/* | |||
* 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; | |||
import com.vaadin.tests.annotations.TestCategory; | |||
@TestCategory("grid") | |||
public class GridColumnAutoWidthServerTest extends | |||
AbstractGridColumnAutoWidthTest { | |||
@Override | |||
protected Class<?> getUIClass() { | |||
return GridColumnAutoWidth.class; | |||
} | |||
} |
@@ -42,6 +42,7 @@ public abstract class EscalatorBasicClientFeaturesTest extends MultiBrowserTest | |||
protected static final String REMOVE_50_ROWS_FROM_ALMOST_BOTTOM = "Remove 50 rows from almost bottom"; | |||
protected static final String ADD_ONE_OF_EACH_ROW = "Add one of each row"; | |||
protected static final String RESIZE_FIRST_COLUMN_TO_MAX_WIDTH = "Resize first column to max width"; | |||
protected static final String RESIZE_FIRST_COLUMN_TO_100PX = "Resize first column to 100 px"; | |||
protected static final String HEADER_ROWS = "Header Rows"; | |||
protected static final String BODY_ROWS = "Body Rows"; |
@@ -102,11 +102,15 @@ public class GridClientDataSourcesTest extends MultiBrowserTest { | |||
} | |||
private void assertCellPresent(String content) { | |||
assertNotNull(findByXPath("//td[text()='" + content + "']")); | |||
assertNotNull("A cell with content \"" + content | |||
+ "\" should've been found", findByXPath("//td[text()='" | |||
+ content + "']")); | |||
} | |||
private void assertCellNotPresent(String content) { | |||
assertNull(findByXPath("//td[text()='" + content + "']")); | |||
assertNull("A cell with content \"" + content | |||
+ "\" should've not been found", findByXPath("//td[text()='" | |||
+ content + "']")); | |||
} | |||
private void scrollToTop() { | |||
@@ -130,7 +134,6 @@ public class GridClientDataSourcesTest extends MultiBrowserTest { | |||
} | |||
private Object executeScript(String script, Object args) { | |||
@SuppressWarnings("hiding") | |||
final WebDriver driver = getDriver(); | |||
if (driver instanceof JavascriptExecutor) { | |||
final JavascriptExecutor je = (JavascriptExecutor) driver; |
@@ -36,9 +36,9 @@ public class GridClientColumnPropertiesTest extends GridBasicClientFeaturesTest | |||
int width = getGridElement().getCell(0, col).getSize().getWidth(); | |||
if (col <= 6) { | |||
// Growing column widths | |||
assertEquals(50 + col * 25, width); | |||
} else { | |||
assertEquals(100, width); | |||
int expectedWidth = 50 + col * 25; | |||
assertEquals("column " + col + " has incorrect width", | |||
expectedWidth, width); | |||
} | |||
} | |||
} | |||
@@ -56,8 +56,9 @@ public class GridClientColumnPropertiesTest extends GridBasicClientFeaturesTest | |||
assertEquals(200, width); | |||
selectMenuPath("Component", "Columns", "Column 0", "Width", "auto"); | |||
width = getGridElement().getCell(0, 0).getSize().getWidth(); | |||
assertEquals(100, width); | |||
int autoWidth = getGridElement().getCell(0, 0).getSize().getWidth(); | |||
assertLessThan("Automatic sizing should've shrunk the column", | |||
autoWidth, width); | |||
} | |||
@Test |
@@ -40,8 +40,9 @@ public class EscalatorColspanTest extends EscalatorBasicClientFeaturesTest { | |||
openTestURL(); | |||
populate(); | |||
int singleCellWidth = getWidth(getBodyCell(0, 0)); | |||
int doubleCellWidth = singleCellWidth * 2; | |||
int firstCellWidth = getWidth(getBodyCell(0, 0)); | |||
int secondCellWidth = getWidth(getBodyCell(0, 1)); | |||
int doubleCellWidth = firstCellWidth + secondCellWidth; | |||
selectMenuPath(FEATURES, COLUMN_SPANNING, COLSPAN_NORMAL); | |||
@@ -219,7 +219,11 @@ public class EscalatorRowColumnTest extends EscalatorBasicClientFeaturesTest { | |||
openTestURL(); | |||
selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); | |||
selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, RESIZE_FIRST_COLUMN_TO_100PX); | |||
int originalWidth = getBodyCell(0, 0).getSize().getWidth(); | |||
assertEquals(100, originalWidth); | |||
selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, | |||
RESIZE_FIRST_COLUMN_TO_MAX_WIDTH); | |||
int newWidth = getBodyCell(0, 0).getSize().getWidth(); |
@@ -153,12 +153,13 @@ public class GridStructureTest extends GridBasicFeaturesTest { | |||
cell = getGridElement().getCell(0, 1); | |||
assertEquals(150, cell.getSize().getWidth()); | |||
// Set first column to be auto sized (defaults to 100px currently) | |||
selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", | |||
"Auto"); | |||
// since the column 0 was previously 200, it should've shrunk when | |||
// autoresizing. | |||
cell = getGridElement().getCell(0, 0); | |||
assertEquals(100, cell.getSize().getWidth()); | |||
assertLessThan("", cell.getSize().getWidth(), 200); | |||
} | |||
@Test |
@@ -469,9 +469,16 @@ public class EscalatorBasicClientFeaturesWidget extends | |||
@Override | |||
public void execute() { | |||
escalator.getColumnConfiguration() | |||
.setColumnWidthToContent(0); | |||
.setColumnWidth(0, -1); | |||
} | |||
}, menupath); | |||
addMenuCommand("Resize first column to 100 px", new ScheduledCommand() { | |||
@Override | |||
public void execute() { | |||
escalator.getColumnConfiguration().setColumnWidth(0, 100); | |||
} | |||
}, menupath); | |||
} | |||
private void createHeaderRowsMenu() { |
@@ -81,17 +81,6 @@ public class EscalatorProxy extends Escalator { | |||
return columnConfiguration.getColumnWidthActual(index); | |||
} | |||
@Override | |||
public void setColumnWidthToContent(int index) | |||
throws IllegalArgumentException { | |||
int oldWidth = columnConfiguration.getColumnWidthActual(index); | |||
columnConfiguration.setColumnWidthToContent(index); | |||
int newWidth = columnConfiguration.getColumnWidthActual(index); | |||
logWidget.log("Changed column " + index + " width from " + oldWidth | |||
+ "px to " + newWidth + "px"); | |||
logWidget.updateDebugLabel(); | |||
} | |||
@Override | |||
public void refreshColumns(int index, int numberOfColumns) | |||
throws IndexOutOfBoundsException, IllegalArgumentException { |
@@ -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.widgetset.client.grid; | |||
import com.google.gwt.core.client.GWT; | |||
import com.google.gwt.user.client.ui.Widget; | |||
import com.vaadin.client.ui.AbstractComponentConnector; | |||
import com.vaadin.shared.ui.Connect; | |||
import com.vaadin.tests.components.grid.GridColumnAutoWidthClient.GridColumnAutoWidthClientComponent; | |||
@Connect(GridColumnAutoWidthClientComponent.class) | |||
public class GridColumnAutoWidthClientConnector extends | |||
AbstractComponentConnector { | |||
@Override | |||
public Widget getWidget() { | |||
return GWT.create(GridColumnAutoWidthClientWidget.class); | |||
} | |||
} |
@@ -0,0 +1,71 @@ | |||
/* | |||
* 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.grid; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import com.vaadin.client.ui.grid.Grid; | |||
import com.vaadin.client.ui.grid.Grid.SelectionMode; | |||
import com.vaadin.client.ui.grid.GridColumn; | |||
import com.vaadin.client.ui.grid.datasources.ListDataSource; | |||
import com.vaadin.client.ui.grid.renderers.HtmlRenderer; | |||
public class GridColumnAutoWidthClientWidget extends | |||
PureGWTTestApplication<Grid<List<String>>> { | |||
private Grid<List<String>> grid; | |||
private class Col extends GridColumn<String, List<String>> { | |||
public Col(String header) { | |||
super(header, new HtmlRenderer()); | |||
} | |||
@Override | |||
public String getValue(List<String> row) { | |||
int index = grid.getColumns().indexOf(this); | |||
return "<span>" + String.valueOf(row.get(index)) + "</span>"; | |||
} | |||
} | |||
protected GridColumnAutoWidthClientWidget() { | |||
super(new Grid<List<String>>()); | |||
grid = getTestedWidget(); | |||
grid.setSelectionMode(SelectionMode.NONE); | |||
grid.setWidth("700px"); | |||
List<List<String>> list = new ArrayList<List<String>>(); | |||
list.add(Arrays.asList("equal length", "a very long cell content", | |||
"short", "fixed width narrow", "fixed width wide")); | |||
grid.setDataSource(new ListDataSource<List<String>>(list)); | |||
addColumn("equal length"); | |||
addColumn("short"); | |||
addColumn("a very long header content"); | |||
addColumn("fixed width narrow").setWidth(50); | |||
addColumn("fixed width wide").setWidth(200); | |||
addNorth(grid, 400); | |||
} | |||
private Col addColumn(String header) { | |||
Col column = (Col) grid.addColumn(new Col(header)); | |||
grid.getHeaderRow(0).getCell(column) | |||
.setHtml("<span>" + header + "</span>"); | |||
return column; | |||
} | |||
} |