summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client-compiler/pom.xml2
-rw-r--r--client/pom.xml2
-rw-r--r--client/src/main/java/com/vaadin/client/ui/menubar/MenuBarConnector.java13
-rw-r--r--client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java18
-rw-r--r--client/src/main/java/com/vaadin/client/widgets/Escalator.java32
-rwxr-xr-x[-rw-r--r--]client/src/main/java/com/vaadin/client/widgets/Grid.java25
-rw-r--r--compatibility-client/pom.xml2
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/selection/MultiSelectionRenderer.java15
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Escalator.java31
-rw-r--r--compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java21
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/BeanItem.java45
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/MethodProperty.java31
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/data/util/NestedMethodProperty.java34
-rw-r--r--compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java3
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/data/util/BeanItemTest.java37
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/data/util/MethodPropertyTest.java75
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/data/util/NestedMethodPropertyTest.java23
-rw-r--r--compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/GridChildrenTest.java61
-rw-r--r--compatibility-shared/pom.xml2
-rw-r--r--server/pom.xml2
-rw-r--r--server/src/main/java/com/vaadin/server/DownloadStream.java15
-rw-r--r--server/src/main/java/com/vaadin/server/communication/AtmospherePushConnection.java14
-rw-r--r--server/src/main/java/com/vaadin/server/communication/UIInitHandler.java13
-rw-r--r--server/src/main/java/com/vaadin/util/EncodeUtil.java71
-rw-r--r--server/src/test/java/com/vaadin/server/DownloadStreamTest.java8
-rw-r--r--server/src/test/java/com/vaadin/server/communication/ServletUIInitHandlerTest.java188
-rw-r--r--server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java2
-rw-r--r--server/src/test/java/com/vaadin/util/EncodeUtilTest.java32
-rw-r--r--shared/pom.xml2
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/FileDownloaderUI.java4
-rwxr-xr-xuitest/src/main/java/com/vaadin/tests/components/grid/GridDetailsReattach.java37
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/menubar/MenuBarIcons.java64
-rw-r--r--uitest/src/main/java/com/vaadin/tests/components/ui/UIInitException.java10
-rw-r--r--uitest/src/main/java/com/vaadin/v7/tests/components/grid/RemoveHiddenColumn.java60
-rw-r--r--uitest/src/main/resources/com/vaadin/tests/components/embedded/File åäö-日本語.pdf (renamed from uitest/src/main/resources/com/vaadin/tests/components/embedded/åäö-日本語.pdf)bin22522 -> 22522 bytes
-rw-r--r--uitest/src/main/themes/VAADIN/themes/tests-valo/img/email-reply.pngbin0 -> 762 bytes
-rwxr-xr-xuitest/src/test/java/com/vaadin/tests/components/grid/GridDetailsReattachTest.java34
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/grid/GridSelectionTest.java52
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/menubar/MenuBarIconsTest.java82
-rw-r--r--uitest/src/test/java/com/vaadin/tests/components/ui/UIInitExceptionTest.java4
-rw-r--r--uitest/src/test/java/com/vaadin/v7/tests/components/grid/RemoveHiddenColumnTest.java45
41 files changed, 1116 insertions, 95 deletions
diff --git a/client-compiler/pom.xml b/client-compiler/pom.xml
index 1ccfccc666..b9aa8188ef 100644
--- a/client-compiler/pom.xml
+++ b/client-compiler/pom.xml
@@ -58,7 +58,7 @@
<execution>
<id>copy-sources</id>
<!-- here the phase you need -->
- <phase>prepare-package</phase>
+ <phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
diff --git a/client/pom.xml b/client/pom.xml
index 53a497b183..e687aee36e 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -57,7 +57,7 @@
<execution>
<id>copy-sources</id>
<!-- here the phase you need -->
- <phase>prepare-package</phase>
+ <phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
diff --git a/client/src/main/java/com/vaadin/client/ui/menubar/MenuBarConnector.java b/client/src/main/java/com/vaadin/client/ui/menubar/MenuBarConnector.java
index cc8e3872ad..79df33e9a7 100644
--- a/client/src/main/java/com/vaadin/client/ui/menubar/MenuBarConnector.java
+++ b/client/src/main/java/com/vaadin/client/ui/menubar/MenuBarConnector.java
@@ -25,9 +25,8 @@ import com.vaadin.client.ApplicationConnection;
import com.vaadin.client.Paintable;
import com.vaadin.client.TooltipInfo;
import com.vaadin.client.UIDL;
-import com.vaadin.client.WidgetUtil;
import com.vaadin.client.ui.AbstractComponentConnector;
-import com.vaadin.client.ui.ImageIcon;
+import com.vaadin.client.ui.Icon;
import com.vaadin.client.ui.SimpleManagedLayout;
import com.vaadin.client.ui.VMenuBar;
import com.vaadin.shared.ui.ComponentStateUtil;
@@ -77,11 +76,11 @@ public class MenuBarConnector extends AbstractComponentConnector
StringBuffer itemHTML = new StringBuffer();
if (moreItemUIDL.hasAttribute("icon")) {
- itemHTML.append("<img src=\""
- + WidgetUtil.escapeAttribute(client.translateVaadinUri(
- moreItemUIDL.getStringAttribute("icon")))
- + "\" class=\"" + ImageIcon.CLASSNAME
- + "\" alt=\"\" />");
+ Icon icon = client
+ .getIcon(moreItemUIDL.getStringAttribute("icon"));
+ if (icon != null) {
+ itemHTML.append(icon.getElement().getString());
+ }
}
String moreItemText = moreItemUIDL.getStringAttribute("text");
diff --git a/client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java b/client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
index 14c2210696..8ccd4373c2 100644
--- a/client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
+++ b/client/src/main/java/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java
@@ -26,6 +26,7 @@ import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.TableElement;
+import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.dom.client.TableSectionElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
@@ -45,6 +46,7 @@ import com.vaadin.client.widget.grid.RendererCellReference;
import com.vaadin.client.widget.grid.events.GridEnabledHandler;
import com.vaadin.client.widget.grid.events.GridSelectionAllowedEvent;
import com.vaadin.client.widget.grid.events.GridSelectionAllowedHandler;
+import com.vaadin.client.widgets.Escalator.AbstractRowContainer;
import com.vaadin.client.widgets.Grid;
/**
@@ -330,7 +332,7 @@ public class MultiSelectionRenderer<T>
int constrainedPageY = Math.max(bodyAbsoluteTop,
Math.min(bodyAbsoluteBottom, pageY));
- int logicalRow = getLogicalRowIndex(WidgetUtil
+ int logicalRow = getLogicalRowIndex(grid, WidgetUtil
.getElementFromPoint(initialPageX, constrainedPageY));
int incrementOrDecrement = (logicalRow > lastModifiedLogicalRow) ? 1
@@ -584,8 +586,6 @@ public class MultiSelectionRenderer<T>
}
}
- private static final String LOGICAL_ROW_PROPERTY_INT = "vEscalatorLogicalRow";
-
private final Grid<T> grid;
private HandlerRegistration nativePreviewHandlerRegistration;
@@ -629,10 +629,7 @@ public class MultiSelectionRenderer<T>
public void render(final RendererCellReference cell, final Boolean data,
CheckBox checkBox) {
checkBox.setValue(data, false);
- checkBox.setEnabled(grid.isEnabled() && !grid.isEditorActive()
- && grid.getSelectionModel().isSelectionAllowed());
- checkBox.getElement().setPropertyInt(LOGICAL_ROW_PROPERTY_INT,
- cell.getRowIndex());
+ checkBox.setEnabled(grid.isEnabled() && !grid.isEditorActive());
}
@Override
@@ -666,7 +663,7 @@ public class MultiSelectionRenderer<T>
private void startDragSelect(NativeEvent event, final Element target) {
injectNativeHandler();
- int logicalRowIndex = getLogicalRowIndex(target);
+ int logicalRowIndex = getLogicalRowIndex(grid, target);
autoScrollHandler.start(logicalRowIndex);
event.preventDefault();
event.stopPropagation();
@@ -685,7 +682,7 @@ public class MultiSelectionRenderer<T>
}
}
- private int getLogicalRowIndex(final Element target) {
+ private int getLogicalRowIndex(Grid<T> grid, final Element target) {
if (target == null) {
return -1;
}
@@ -705,7 +702,8 @@ public class MultiSelectionRenderer<T>
final Element checkbox = td.getFirstChildElement();
assert checkbox != null : "Checkbox has disappeared";
- return checkbox.getPropertyInt(LOGICAL_ROW_PROPERTY_INT);
+ return ((AbstractRowContainer) grid.getEscalator().getBody())
+ .getLogicalRowIndex((TableRowElement) tr);
}
tr = tr.getNextSiblingElement();
}
diff --git a/client/src/main/java/com/vaadin/client/widgets/Escalator.java b/client/src/main/java/com/vaadin/client/widgets/Escalator.java
index 3c7b7c0159..239ed9b90b 100644
--- a/client/src/main/java/com/vaadin/client/widgets/Escalator.java
+++ b/client/src/main/java/com/vaadin/client/widgets/Escalator.java
@@ -53,7 +53,6 @@ import com.google.gwt.dom.client.TableSectionElement;
import com.google.gwt.dom.client.Touch;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.logging.client.LogConfiguration;
-import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RequiresResize;
@@ -702,13 +701,13 @@ public class Escalator extends Widget
/*-{
var vScroll = esc.@com.vaadin.client.widgets.Escalator::verticalScrollbar;
var vScrollElem = vScroll.@com.vaadin.client.widget.escalator.ScrollbarBundle::getElement()();
-
+
var hScroll = esc.@com.vaadin.client.widgets.Escalator::horizontalScrollbar;
var hScrollElem = hScroll.@com.vaadin.client.widget.escalator.ScrollbarBundle::getElement()();
-
+
return $entry(function(e) {
var target = e.target;
-
+
// in case the scroll event was native (i.e. scrollbars were dragged, or
// the scrollTop/Left was manually modified), the bundles have old cache
// values. We need to make sure that the caches are kept up to date.
@@ -729,29 +728,29 @@ public class Escalator extends Widget
return $entry(function(e) {
var deltaX = e.deltaX ? e.deltaX : -0.5*e.wheelDeltaX;
var deltaY = e.deltaY ? e.deltaY : -0.5*e.wheelDeltaY;
-
+
// Delta mode 0 is in pixels; we don't need to do anything...
-
+
// A delta mode of 1 means we're scrolling by lines instead of pixels
// We need to scale the number of lines by the default line height
if(e.deltaMode === 1) {
var brc = esc.@com.vaadin.client.widgets.Escalator::body;
deltaY *= brc.@com.vaadin.client.widgets.Escalator.AbstractRowContainer::getDefaultRowHeight()();
}
-
+
// Other delta modes aren't supported
if((e.deltaMode !== undefined) && (e.deltaMode >= 2 || e.deltaMode < 0)) {
var msg = "Unsupported wheel delta mode \"" + e.deltaMode + "\"";
-
+
// Print warning message
esc.@com.vaadin.client.widgets.Escalator::logWarning(*)(msg);
}
-
+
// IE8 has only delta y
if (isNaN(deltaY)) {
deltaY = -0.5*e.wheelDelta;
}
-
+
@com.vaadin.client.widgets.Escalator.JsniUtil::moveScrollFromEvent(*)(esc, deltaX, deltaY, e);
});
}-*/;
@@ -1098,7 +1097,7 @@ public class Escalator extends Widget
}
}
- protected abstract class AbstractRowContainer implements RowContainer {
+ public abstract class AbstractRowContainer implements RowContainer {
private EscalatorUpdater updater = EscalatorUpdater.NULL;
private int rows;
@@ -2124,7 +2123,14 @@ public class Escalator extends Widget
*/
protected abstract double getHeightOfSection();
- protected int getLogicalRowIndex(final TableRowElement tr) {
+ /**
+ * Gets the logical row index for the given table row element.
+ *
+ * @param tr
+ * the table row element inside this container.
+ * @return the logical index of the given element
+ */
+ public int getLogicalRowIndex(final TableRowElement tr) {
return tr.getSectionRowIndex();
};
@@ -3433,7 +3439,7 @@ public class Escalator extends Widget
}
@Override
- protected int getLogicalRowIndex(final TableRowElement tr) {
+ public int getLogicalRowIndex(final TableRowElement tr) {
assert tr
.getParentNode() == root : "The given element isn't a row element in the body";
int internalIndex = visualRowOrder.indexOf(tr);
diff --git a/client/src/main/java/com/vaadin/client/widgets/Grid.java b/client/src/main/java/com/vaadin/client/widgets/Grid.java
index 9974505bd4..a135827a5a 100644..100755
--- a/client/src/main/java/com/vaadin/client/widgets/Grid.java
+++ b/client/src/main/java/com/vaadin/client/widgets/Grid.java
@@ -4159,6 +4159,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
private GridSpacerUpdater gridSpacerUpdater = new GridSpacerUpdater();
/** A set keeping track of the indices of all currently open details */
private Set<Integer> visibleDetails = new HashSet<>();
+ /** A set of indices of details to reopen after detach and on attach */
+ private final Set<Integer> reattachVisibleDetails = new HashSet<>();
private boolean columnReorderingAllowed;
@@ -6450,8 +6452,14 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
int columnIndex = columns.indexOf(column);
// Remove from column configuration
- escalator.getColumnConfiguration()
- .removeColumns(getVisibleColumns().indexOf(column), 1);
+ int visibleColumnIndex = getVisibleColumns().indexOf(column);
+ if (visibleColumnIndex < 0) {
+ assert column.isHidden();
+ // Hidden columns are not included in Escalator
+ } else {
+ getEscalator().getColumnConfiguration()
+ .removeColumns(visibleColumnIndex, 1);
+ }
updateFrozenColumns();
@@ -6830,7 +6838,12 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
return editor;
}
- protected Escalator getEscalator() {
+ /**
+ * Gets the {@link Escalator} used by this Grid instnace.
+ *
+ * @return the escalator instance, never <code>null</code>
+ */
+ public Escalator getEscalator() {
return escalator;
}
@@ -8712,11 +8725,17 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
// Grid was just attached to DOM. Column widths should be calculated.
recalculateColumnWidths();
+ for (int row : reattachVisibleDetails) {
+ setDetailsVisible(row, true);
+ }
+ reattachVisibleDetails.clear();
}
@Override
protected void onDetach() {
Set<Integer> details = new HashSet<>(visibleDetails);
+ reattachVisibleDetails.clear();
+ reattachVisibleDetails.addAll(details);
for (int row : details) {
setDetailsVisible(row, false);
}
diff --git a/compatibility-client/pom.xml b/compatibility-client/pom.xml
index 898326526c..76c06a3755 100644
--- a/compatibility-client/pom.xml
+++ b/compatibility-client/pom.xml
@@ -75,7 +75,7 @@
<execution>
<id>copy-sources</id>
<!-- here the phase you need -->
- <phase>prepare-package</phase>
+ <phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/selection/MultiSelectionRenderer.java b/compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/selection/MultiSelectionRenderer.java
index 678d37369f..a7c974aead 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/selection/MultiSelectionRenderer.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/widget/grid/selection/MultiSelectionRenderer.java
@@ -26,6 +26,7 @@ import com.google.gwt.dom.client.BrowserEvents;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.TableElement;
+import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.dom.client.TableSectionElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
@@ -45,6 +46,7 @@ import com.vaadin.v7.client.widget.grid.RendererCellReference;
import com.vaadin.v7.client.widget.grid.events.GridEnabledEvent;
import com.vaadin.v7.client.widget.grid.events.GridEnabledHandler;
import com.vaadin.v7.client.widget.grid.selection.SelectionModel.Multi.Batched;
+import com.vaadin.v7.client.widgets.Escalator.AbstractRowContainer;
import com.vaadin.v7.client.widgets.Grid;
/**
@@ -319,7 +321,7 @@ public class MultiSelectionRenderer<T>
int constrainedPageY = Math.max(bodyAbsoluteTop,
Math.min(bodyAbsoluteBottom, pageY));
- int logicalRow = getLogicalRowIndex(WidgetUtil
+ int logicalRow = getLogicalRowIndex(grid, WidgetUtil
.getElementFromPoint(initialPageX, constrainedPageY));
int incrementOrDecrement = (logicalRow > lastModifiedLogicalRow) ? 1
@@ -586,8 +588,6 @@ public class MultiSelectionRenderer<T>
}
}
- private static final String LOGICAL_ROW_PROPERTY_INT = "vEscalatorLogicalRow";
-
private final Grid<T> grid;
private HandlerRegistration nativePreviewHandlerRegistration;
@@ -633,8 +633,6 @@ public class MultiSelectionRenderer<T>
CheckBox checkBox) {
checkBox.setValue(data, false);
checkBox.setEnabled(grid.isEnabled() && !grid.isEditorActive());
- checkBox.getElement().setPropertyInt(LOGICAL_ROW_PROPERTY_INT,
- cell.getRowIndex());
}
@Override
@@ -668,7 +666,7 @@ public class MultiSelectionRenderer<T>
private void startDragSelect(NativeEvent event, final Element target) {
injectNativeHandler();
- int logicalRowIndex = getLogicalRowIndex(target);
+ int logicalRowIndex = getLogicalRowIndex(grid, target);
autoScrollHandler.start(logicalRowIndex);
event.preventDefault();
event.stopPropagation();
@@ -687,7 +685,7 @@ public class MultiSelectionRenderer<T>
}
}
- private int getLogicalRowIndex(final Element target) {
+ private int getLogicalRowIndex(Grid<T> grid, final Element target) {
if (target == null) {
return -1;
}
@@ -707,7 +705,8 @@ public class MultiSelectionRenderer<T>
final Element checkbox = td.getFirstChildElement();
assert checkbox != null : "Checkbox has disappeared";
- return checkbox.getPropertyInt(LOGICAL_ROW_PROPERTY_INT);
+ return ((AbstractRowContainer) grid.getEscalator().getBody())
+ .getLogicalRowIndex((TableRowElement) tr);
}
tr = tr.getNextSiblingElement();
}
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Escalator.java b/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Escalator.java
index f343d45f6f..cb2786a4cf 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Escalator.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Escalator.java
@@ -673,13 +673,13 @@ public class Escalator extends Widget
/*-{
var vScroll = esc.@com.vaadin.v7.client.widgets.Escalator::verticalScrollbar;
var vScrollElem = vScroll.@com.vaadin.v7.client.widget.escalator.ScrollbarBundle::getElement()();
-
+
var hScroll = esc.@com.vaadin.v7.client.widgets.Escalator::horizontalScrollbar;
var hScrollElem = hScroll.@com.vaadin.v7.client.widget.escalator.ScrollbarBundle::getElement()();
-
+
return $entry(function(e) {
var target = e.target;
-
+
// in case the scroll event was native (i.e. scrollbars were dragged, or
// the scrollTop/Left was manually modified), the bundles have old cache
// values. We need to make sure that the caches are kept up to date.
@@ -700,29 +700,29 @@ public class Escalator extends Widget
return $entry(function(e) {
var deltaX = e.deltaX ? e.deltaX : -0.5*e.wheelDeltaX;
var deltaY = e.deltaY ? e.deltaY : -0.5*e.wheelDeltaY;
-
+
// Delta mode 0 is in pixels; we don't need to do anything...
-
+
// A delta mode of 1 means we're scrolling by lines instead of pixels
// We need to scale the number of lines by the default line height
if(e.deltaMode === 1) {
var brc = esc.@com.vaadin.v7.client.widgets.Escalator::body;
deltaY *= brc.@com.vaadin.v7.client.widgets.Escalator.AbstractRowContainer::getDefaultRowHeight()();
}
-
+
// Other delta modes aren't supported
if((e.deltaMode !== undefined) && (e.deltaMode >= 2 || e.deltaMode < 0)) {
var msg = "Unsupported wheel delta mode \"" + e.deltaMode + "\"";
-
+
// Print warning message
esc.@com.vaadin.v7.client.widgets.Escalator::logWarning(*)(msg);
}
-
+
// IE8 has only delta y
if (isNaN(deltaY)) {
deltaY = -0.5*e.wheelDelta;
}
-
+
@com.vaadin.v7.client.widgets.Escalator.JsniUtil::moveScrollFromEvent(*)(esc, deltaX, deltaY, e);
});
}-*/;
@@ -1044,7 +1044,7 @@ public class Escalator extends Widget
}
}
- protected abstract class AbstractRowContainer implements RowContainer {
+ public abstract class AbstractRowContainer implements RowContainer {
private EscalatorUpdater updater = EscalatorUpdater.NULL;
private int rows;
@@ -2070,7 +2070,14 @@ public class Escalator extends Widget
*/
protected abstract double getHeightOfSection();
- protected int getLogicalRowIndex(final TableRowElement tr) {
+ /**
+ * Gets the logical row index for the given table row element.
+ *
+ * @param tr
+ * the table row element inside this container
+ * @return the logical index of the given element
+ */
+ public int getLogicalRowIndex(final TableRowElement tr) {
return tr.getSectionRowIndex();
};
@@ -3379,7 +3386,7 @@ public class Escalator extends Widget
}
@Override
- protected int getLogicalRowIndex(final TableRowElement tr) {
+ public int getLogicalRowIndex(final TableRowElement tr) {
assert tr
.getParentNode() == root : "The given element isn't a row element in the body";
int internalIndex = visualRowOrder.indexOf(tr);
diff --git a/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java b/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java
index e59fc2213f..5e48188128 100644
--- a/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java
+++ b/compatibility-client/src/main/java/com/vaadin/v7/client/widgets/Grid.java
@@ -4128,6 +4128,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
private GridSpacerUpdater gridSpacerUpdater = new GridSpacerUpdater();
/** A set keeping track of the indices of all currently open details */
private Set<Integer> visibleDetails = new HashSet<>();
+ /** A set of indices of details to reopen after detach and on attach */
+ private final Set<Integer> reattachVisibleDetails = new HashSet<>();
private boolean columnReorderingAllowed;
@@ -6451,8 +6453,14 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
int columnIndex = columns.indexOf(column);
// Remove from column configuration
- escalator.getColumnConfiguration()
- .removeColumns(getVisibleColumns().indexOf(column), 1);
+ int visibleColumnIndex = getVisibleColumns().indexOf(column);
+ if (visibleColumnIndex < 0) {
+ assert column.isHidden();
+ // Hidden columns are not included in Escalator
+ } else {
+ getEscalator().getColumnConfiguration()
+ .removeColumns(visibleColumnIndex, 1);
+ }
updateFrozenColumns();
@@ -6831,7 +6839,12 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
return editor;
}
- protected Escalator getEscalator() {
+ /**
+ * Gets the {@link Escalator} used by this Grid instnace.
+ *
+ * @return the escalator instance, never <code>null</code>
+ */
+ public Escalator getEscalator() {
return escalator;
}
@@ -8766,6 +8779,8 @@ public class Grid<T> extends ResizeComposite implements HasSelectionHandlers<T>,
@Override
protected void onDetach() {
Set<Integer> details = new HashSet<>(visibleDetails);
+ reattachVisibleDetails.clear();
+ reattachVisibleDetails.addAll(details);
for (int row : details) {
setDetailsVisible(row, false);
}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/BeanItem.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/BeanItem.java
index 8bba865ffc..a286cdc3b2 100644
--- a/compatibility-server/src/main/java/com/vaadin/v7/data/util/BeanItem.java
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/BeanItem.java
@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.Set;
import com.vaadin.data.util.BeanUtil;
+import com.vaadin.v7.data.Property;
/**
* A wrapper class for adding the Item interface to any Java Bean.
@@ -41,7 +42,7 @@ public class BeanItem<BT> extends PropertysetItem {
/**
* The bean which this Item is based on.
*/
- private final BT bean;
+ private BT bean;
/**
* <p>
@@ -264,4 +265,46 @@ public class BeanItem<BT> extends PropertysetItem {
return bean;
}
+ /**
+ * Changes the Java Bean this item is based on.
+ * <p>
+ * This will cause any existing properties to be re-mapped to the new bean.
+ * Any added custom properties which are not of type {@link MethodProperty}
+ * or {@link NestedMethodProperty} will not be updated to reflect the change
+ * of bean.
+ * <p>
+ * Changing the bean will fire value change events for all properties of
+ * type {@link MethodProperty} or {@link NestedMethodProperty}.
+ *
+ * @param bean
+ * The new bean to use for this item, not <code>null</code>
+ */
+ public void setBean(BT bean) {
+ if (bean == null) {
+ throw new IllegalArgumentException("Bean cannot be null");
+ }
+
+ if (getBean().getClass() != bean.getClass()) {
+ throw new IllegalArgumentException(
+ "The new bean class " + bean.getClass().getName()
+ + " does not match the old bean class "
+ + getBean().getClass());
+ }
+
+ // Remap properties
+ for (Object propertyId : getItemPropertyIds()) {
+ Property p = getItemProperty(propertyId);
+ if (p instanceof MethodProperty) {
+ MethodProperty mp = (MethodProperty) p;
+ assert (mp.getInstance() == getBean());
+ mp.setInstance(bean);
+ } else if (p instanceof NestedMethodProperty) {
+ NestedMethodProperty nmp = (NestedMethodProperty) p;
+ assert (nmp.getInstance() == getBean());
+ nmp.setInstance(bean);
+ }
+ }
+
+ this.bean = bean;
+ }
}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/MethodProperty.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/MethodProperty.java
index ba5edbb146..e3651d0272 100644
--- a/compatibility-server/src/main/java/com/vaadin/v7/data/util/MethodProperty.java
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/MethodProperty.java
@@ -769,6 +769,37 @@ public class MethodProperty<T> extends AbstractProperty<T> {
super.fireValueChange();
}
+ /**
+ * The instance used by this property
+ *
+ * @return the instance used for fetching the property value
+ */
+ public Object getInstance() {
+ return instance;
+ }
+
+ /**
+ * Sets the instance used by this property.
+ * <p>
+ * The new instance must be of the same type as the old instance
+ * <p>
+ * To be consistent with {@link #setValue(Object)}, this method will fire a
+ * value change event even if the value stays the same
+ *
+ * @param instance
+ * the instance to use
+ */
+ public void setInstance(Object instance) {
+ if (this.instance.getClass() != instance.getClass()) {
+ throw new IllegalArgumentException("The new instance is of type "
+ + instance.getClass().getName()
+ + " which does not match the old instance type "
+ + this.instance.getClass().getName());
+ }
+ this.instance = instance;
+ fireValueChange();
+ }
+
private static final Logger getLogger() {
return Logger.getLogger(MethodProperty.class.getName());
}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/data/util/NestedMethodProperty.java b/compatibility-server/src/main/java/com/vaadin/v7/data/util/NestedMethodProperty.java
index 3f9236c4ac..ab23d07551 100644
--- a/compatibility-server/src/main/java/com/vaadin/v7/data/util/NestedMethodProperty.java
+++ b/compatibility-server/src/main/java/com/vaadin/v7/data/util/NestedMethodProperty.java
@@ -193,9 +193,10 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> {
/**
* Gets the value stored in the Property. The value is resolved by calling
- * the specified getter method with the argument specified at instantiation.
+ * the specified getter methods on the current instance:
*
* @return the value of the Property
+ * @see #getInstance()
*/
@Override
public T getValue() {
@@ -267,4 +268,35 @@ public class NestedMethodProperty<T> extends AbstractProperty<T> {
return Collections.unmodifiableList(getMethods);
}
+ /**
+ * The instance used by this property
+ *
+ * @return the instance used for fetching the property value
+ */
+ public Object getInstance() {
+ return instance;
+ }
+
+ /**
+ * Sets the instance used by this property.
+ * <p>
+ * The new instance must be of the same type as the old instance
+ * <p>
+ * To be consistent with {@link #setValue(Object)}, this method will fire a
+ * value change event even if the value stays the same
+ *
+ * @param instance
+ * the instance to use
+ */
+ public void setInstance(Object instance) {
+ if (this.instance.getClass() != instance.getClass()) {
+ throw new IllegalArgumentException("The new instance is of type "
+ + instance.getClass().getName()
+ + " which does not match the old instance type "
+ + this.instance.getClass().getName());
+ }
+ this.instance = instance;
+ fireValueChange();
+ }
+
}
diff --git a/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java b/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java
index cabba91d31..ee9b968c00 100644
--- a/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java
+++ b/compatibility-server/src/main/java/com/vaadin/v7/ui/Grid.java
@@ -2556,6 +2556,9 @@ public class Grid extends AbstractComponent
for (CELLTYPE cell : cells.values()) {
cell.detach();
}
+ for (CELLTYPE cell : cellGroups.values()) {
+ cell.detach();
+ }
}
}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/data/util/BeanItemTest.java b/compatibility-server/src/test/java/com/vaadin/v7/data/util/BeanItemTest.java
index cc5d72f3df..a9eb3d740b 100644
--- a/compatibility-server/src/test/java/com/vaadin/v7/data/util/BeanItemTest.java
+++ b/compatibility-server/src/test/java/com/vaadin/v7/data/util/BeanItemTest.java
@@ -386,4 +386,41 @@ public class BeanItemTest {
// Should not be exception
property.setValue(null);
}
+
+ @Test
+ public void testChangeBean() {
+ BeanItem<MyClass> beanItem = new BeanItem<BeanItemTest.MyClass>(
+ new MyClass("Foo"));
+ beanItem.setBean(new MyClass("Bar"));
+ Assert.assertEquals("Bar", beanItem.getItemProperty("name").getValue());
+ }
+
+ @Test
+ public void testChangeBeanNestedProperty() {
+ BeanItem<MyClass> beanItem = new BeanItem<BeanItemTest.MyClass>(
+ new MyClass("Foo"));
+ beanItem.setBean(new MyClass("Bar"));
+ Assert.assertEquals("Bar", beanItem.getItemProperty("name").getValue());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testChangeBeanToIncompatibleOne() {
+ BeanItem<Object> beanItem = new BeanItem<Object>(new MyClass("Foo"));
+ beanItem.setBean(new Generic<String>());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testChangeBeanToSubclass() {
+ BeanItem<MyClass> beanItem = new BeanItem<BeanItemTest.MyClass>(
+ new MyClass("Foo"));
+ beanItem.setBean(new MyClass("Bar"));
+ beanItem.setBean(new MyClass2("foo"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testChangeBeanToNull() {
+ BeanItem<Object> beanItem = new BeanItem<Object>(new MyClass("Foo"));
+ beanItem.setBean(null);
+ }
+
}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/data/util/MethodPropertyTest.java b/compatibility-server/src/test/java/com/vaadin/v7/data/util/MethodPropertyTest.java
new file mode 100644
index 0000000000..61c66b9167
--- /dev/null
+++ b/compatibility-server/src/test/java/com/vaadin/v7/data/util/MethodPropertyTest.java
@@ -0,0 +1,75 @@
+/*
+ * 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.v7.data.util;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.v7.data.util.NestedMethodPropertyTest.Address;
+
+public class MethodPropertyTest {
+
+ private Address testObject;
+
+ @Before
+ public void setup() {
+ testObject = new Address("some street", 123);
+ }
+
+ @Test
+ public void getValue() {
+ MethodProperty<String> mp = new MethodProperty<String>(testObject,
+ "street");
+ Assert.assertEquals("some street", mp.getValue());
+ }
+
+ @Test
+ public void getValueAfterBeanUpdate() {
+ MethodProperty<String> mp = new MethodProperty<String>(testObject,
+ "street");
+ testObject.setStreet("Foo street");
+ Assert.assertEquals("Foo street", mp.getValue());
+ }
+
+ @Test
+ public void setValue() {
+ MethodProperty<String> mp = new MethodProperty<String>(testObject,
+ "street");
+ mp.setValue("Foo street");
+ Assert.assertEquals("Foo street", testObject.getStreet());
+ }
+
+ @Test
+ public void changeInstance() {
+ MethodProperty<String> mp = new MethodProperty<String>(testObject,
+ "street");
+ Address newStreet = new Address("new street", 999);
+ mp.setInstance(newStreet);
+ Assert.assertEquals("new street", mp.getValue());
+ Assert.assertEquals("some street", testObject.getStreet());
+
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void changeInstanceToIncompatible() {
+ MethodProperty<String> mp = new MethodProperty<String>(testObject,
+ "street");
+ mp.setInstance("foobar");
+
+ }
+
+}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/data/util/NestedMethodPropertyTest.java b/compatibility-server/src/test/java/com/vaadin/v7/data/util/NestedMethodPropertyTest.java
index a5103e0e0a..9a47e395e2 100644
--- a/compatibility-server/src/test/java/com/vaadin/v7/data/util/NestedMethodPropertyTest.java
+++ b/compatibility-server/src/test/java/com/vaadin/v7/data/util/NestedMethodPropertyTest.java
@@ -348,4 +348,27 @@ public class NestedMethodPropertyTest {
Assert.assertTrue(booleanProperty.isReadOnly());
}
+ @Test
+ public void testChangeInstance() {
+ NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.address.street");
+
+ Address somewhere = new Address("The street", 1234);
+ Person someone = new Person("Someone", somewhere);
+ Team someteam = new Team("The team", someone);
+ streetProperty.setInstance(someteam);
+
+ Assert.assertEquals("The street", streetProperty.getValue());
+ Assert.assertEquals("Ruukinkatu 2-4", vaadin.getManager().getAddress()
+ .getStreet());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testChangeInstanceToIncompatible() {
+ NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>(
+ vaadin, "manager.address.street");
+
+ streetProperty.setInstance("bar");
+ }
+
}
diff --git a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/GridChildrenTest.java b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/GridChildrenTest.java
index 7a599f2745..2d8edddac1 100644
--- a/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/GridChildrenTest.java
+++ b/compatibility-server/src/test/java/com/vaadin/v7/tests/server/component/grid/GridChildrenTest.java
@@ -18,6 +18,7 @@ package com.vaadin.v7.tests.server.component.grid;
import java.util.Iterator;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import com.vaadin.ui.Component;
@@ -28,12 +29,19 @@ import com.vaadin.v7.ui.Grid.HeaderCell;
public class GridChildrenTest {
- @Test
- public void componentsInMergedHeader() {
- Grid grid = new Grid();
+ private Grid grid;
+
+ @Before
+ public void createGrid() {
+ grid = new Grid();
grid.addColumn("foo");
grid.addColumn("bar");
grid.addColumn("baz");
+
+ }
+
+ @Test
+ public void iteratorFindsComponentsInMergedHeader() {
HeaderCell merged = grid.getDefaultHeaderRow().join("foo", "bar",
"baz");
Label label = new Label();
@@ -44,16 +52,55 @@ public class GridChildrenTest {
}
@Test
+ public void removeComponentInMergedHeaderCell() {
+ HeaderCell merged = grid.getDefaultHeaderRow().join("foo", "bar",
+ "baz");
+ Label label = new Label();
+ merged.setComponent(label);
+ Assert.assertEquals(grid, label.getParent());
+ merged.setText("foo");
+ Assert.assertNull(label.getParent());
+ }
+
+ @Test
+ public void removeHeaderWithComponentInMergedHeaderCell() {
+ HeaderCell merged = grid.getDefaultHeaderRow().join("foo", "bar",
+ "baz");
+ Label label = new Label();
+ merged.setComponent(label);
+ Assert.assertEquals(grid, label.getParent());
+ grid.removeHeaderRow(0);
+ Assert.assertNull(label.getParent());
+ }
+
+ @Test
+ public void removeComponentInMergedFooterCell() {
+ FooterCell merged = grid.addFooterRowAt(0).join("foo", "bar", "baz");
+ Label label = new Label();
+ merged.setComponent(label);
+ Assert.assertEquals(grid, label.getParent());
+ merged.setText("foo");
+ Assert.assertNull(label.getParent());
+ }
+
+ @Test
+ public void removeFooterWithComponentInMergedFooterCell() {
+ FooterCell merged = grid.addFooterRowAt(0).join("foo", "bar", "baz");
+ Label label = new Label();
+ merged.setComponent(label);
+ Assert.assertEquals(grid, label.getParent());
+ grid.removeFooterRow(0);
+ Assert.assertNull(label.getParent());
+ }
+
+ @Test
public void componentsInMergedFooter() {
- Grid grid = new Grid();
- grid.addColumn("foo");
- grid.addColumn("bar");
- grid.addColumn("baz");
FooterCell merged = grid.addFooterRowAt(0).join("foo", "bar", "baz");
Label label = new Label();
merged.setComponent(label);
Iterator<Component> i = grid.iterator();
Assert.assertEquals(label, i.next());
Assert.assertFalse(i.hasNext());
+ Assert.assertEquals(grid, label.getParent());
}
}
diff --git a/compatibility-shared/pom.xml b/compatibility-shared/pom.xml
index d702702748..abdc1ca849 100644
--- a/compatibility-shared/pom.xml
+++ b/compatibility-shared/pom.xml
@@ -75,7 +75,7 @@
<execution>
<id>copy-sources</id>
<!-- here the phase you need -->
- <phase>prepare-package</phase>
+ <phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
diff --git a/server/pom.xml b/server/pom.xml
index 479935666c..4a31cd47eb 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -165,7 +165,7 @@
<execution>
<id>copy-sources</id>
<!-- here the phase you need -->
- <phase>prepare-package</phase>
+ <phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
diff --git a/server/src/main/java/com/vaadin/server/DownloadStream.java b/server/src/main/java/com/vaadin/server/DownloadStream.java
index a0a1334135..b52b2e83a4 100644
--- a/server/src/main/java/com/vaadin/server/DownloadStream.java
+++ b/server/src/main/java/com/vaadin/server/DownloadStream.java
@@ -20,14 +20,14 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
+import com.vaadin.util.EncodeUtil;
+
/**
* Downloadable stream.
* <p>
@@ -329,13 +329,10 @@ public class DownloadStream implements Serializable {
* @return A value for inclusion in a Content-Disposition header
*/
public static String getContentDispositionFilename(String filename) {
- try {
- String encodedFilename = URLEncoder.encode(filename, "UTF-8");
- return String.format("filename=\"%s\"; filename*=utf-8''%s",
- encodedFilename, encodedFilename);
- } catch (UnsupportedEncodingException e) {
- return null;
- }
+ String encodedFilename = EncodeUtil.rfc5987Encode(filename);
+
+ return String.format("filename=\"%s\"; filename*=utf-8''%s",
+ encodedFilename, encodedFilename);
}
/**
diff --git a/server/src/main/java/com/vaadin/server/communication/AtmospherePushConnection.java b/server/src/main/java/com/vaadin/server/communication/AtmospherePushConnection.java
index 92d675001b..b5a6f55e4c 100644
--- a/server/src/main/java/com/vaadin/server/communication/AtmospherePushConnection.java
+++ b/server/src/main/java/com/vaadin/server/communication/AtmospherePushConnection.java
@@ -258,17 +258,21 @@ public class AtmospherePushConnection implements PushConnection {
}
/**
- * @return the UI associated with this connection.
+ * Gets the UI this push connection is associated with.
+ *
+ * @return the UI associated with this connection
*/
- protected UI getUI() {
+ public UI getUI() {
return ui;
}
/**
- * @return The AtmosphereResource associated with this connection or null if
- * connection not open.
+ * Gets the atmosphere resource associated with this connection.
+ *
+ * @return The AtmosphereResource associated with this connection or
+ * <code>null</code> if the connection is not open.
*/
- protected AtmosphereResource getResource() {
+ public AtmosphereResource getResource() {
return resource;
}
diff --git a/server/src/main/java/com/vaadin/server/communication/UIInitHandler.java b/server/src/main/java/com/vaadin/server/communication/UIInitHandler.java
index 09d2b0aa79..c0c6850d32 100644
--- a/server/src/main/java/com/vaadin/server/communication/UIInitHandler.java
+++ b/server/src/main/java/com/vaadin/server/communication/UIInitHandler.java
@@ -211,10 +211,17 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler {
// Set thread local here so it is available in init
UI.setCurrent(ui);
- ui.doInit(request, uiId.intValue(), embedId);
-
+ Exception initException = null;
+ try {
+ ui.doInit(request, uiId.intValue(), embedId);
+ } catch (Exception e) {
+ initException = e;
+ }
session.addUI(ui);
-
+ if (initException != null) {
+ ui.getSession().getCommunicationManager()
+ .handleConnectorRelatedException(ui, initException);
+ }
// Warn if the window can't be preserved
if (embedId == null
&& vaadinService.preserveUIOnRefresh(provider, event)) {
diff --git a/server/src/main/java/com/vaadin/util/EncodeUtil.java b/server/src/main/java/com/vaadin/util/EncodeUtil.java
new file mode 100644
index 0000000000..eae0890542
--- /dev/null
+++ b/server/src/main/java/com/vaadin/util/EncodeUtil.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2000-2016 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.util;
+
+import java.nio.charset.Charset;
+
+/**
+ * Utilities related to various encoding schemes.
+ *
+ * @author Vaadin Ltd
+ * @since
+ */
+public final class EncodeUtil {
+ private static final Charset UTF8 = Charset.forName("UTF-8");
+
+ private EncodeUtil() {
+ // Static utils only
+ }
+
+ /**
+ * Encodes the given string to UTF-8 <code>value-chars</code> as defined in
+ * RFC5987 for use in e.g. the <code>Content-Disposition</code> HTTP header.
+ *
+ * @param value
+ * the string to encode, not <code>null</code>
+ * @return the encoded string
+ */
+ public static String rfc5987Encode(String value) {
+ StringBuilder builder = new StringBuilder();
+
+ for (int i = 0; i < value.length();) {
+ int cp = value.codePointAt(i);
+ if (cp < 127 && (Character.isLetterOrDigit(cp) || cp == '.')) {
+ builder.append((char) cp);
+ } else {
+ // Create string from a single code point
+ String cpAsString = new String(new int[] { cp }, 0, 1);
+
+ appendHexBytes(builder, cpAsString.getBytes(UTF8));
+ }
+
+ // Advance to the next code point
+ i += Character.charCount(cp);
+ }
+
+ return builder.toString();
+ }
+
+ private static void appendHexBytes(StringBuilder builder, byte[] bytes) {
+ for (byte byteValue : bytes) {
+ // mask with 0xFF to compensate for "negative" values
+ int intValue = byteValue & 0xFF;
+ String hexCode = Integer.toString(intValue, 16);
+ builder.append('%').append(hexCode);
+ }
+ }
+
+}
diff --git a/server/src/test/java/com/vaadin/server/DownloadStreamTest.java b/server/src/test/java/com/vaadin/server/DownloadStreamTest.java
index 81f45f6173..4bb97de79f 100644
--- a/server/src/test/java/com/vaadin/server/DownloadStreamTest.java
+++ b/server/src/test/java/com/vaadin/server/DownloadStreamTest.java
@@ -7,13 +7,16 @@ import static org.mockito.Mockito.verify;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URLEncoder;
import org.junit.Before;
import org.junit.Test;
public class DownloadStreamTest {
- private final String filename = "日本語.png";
+ private String filename = "A å日.png";
+ private String encodedFileName = "A" + "%20" // space
+ + "%c3%a5" // å
+ + "%e6%97%a5" // 日
+ + ".png";
private DownloadStream stream;
@Before
@@ -27,7 +30,6 @@ public class DownloadStreamTest {
stream.writeResponse(mock(VaadinRequest.class), response);
- String encodedFileName = URLEncoder.encode(filename, "utf-8");
verify(response).setHeader(eq(DownloadStream.CONTENT_DISPOSITION),
contains(String.format("filename=\"%s\";", encodedFileName)));
verify(response).setHeader(eq(DownloadStream.CONTENT_DISPOSITION),
diff --git a/server/src/test/java/com/vaadin/server/communication/ServletUIInitHandlerTest.java b/server/src/test/java/com/vaadin/server/communication/ServletUIInitHandlerTest.java
new file mode 100644
index 0000000000..6c61922307
--- /dev/null
+++ b/server/src/test/java/com/vaadin/server/communication/ServletUIInitHandlerTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2000-2016 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.server.communication;
+
+import java.io.IOException;
+import java.util.Properties;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.vaadin.server.DefaultDeploymentConfiguration;
+import com.vaadin.server.ErrorEvent;
+import com.vaadin.server.ErrorHandler;
+import com.vaadin.server.LegacyCommunicationManager;
+import com.vaadin.server.MockServletConfig;
+import com.vaadin.server.UIClassSelectionEvent;
+import com.vaadin.server.UICreateEvent;
+import com.vaadin.server.UIProvider;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinServlet;
+import com.vaadin.server.VaadinServletRequest;
+import com.vaadin.server.VaadinServletResponse;
+import com.vaadin.server.VaadinServletService;
+import com.vaadin.tests.util.AlwaysLockedVaadinSession;
+import com.vaadin.ui.UI;
+
+public class ServletUIInitHandlerTest {
+
+ public static class CommunicationMock {
+
+ public final UI ui;
+ public final ServletConfig servletConfig;
+ public final VaadinServlet servlet;
+ public final DefaultDeploymentConfiguration deploymentConfiguration;
+ public final VaadinServletService service;
+ public final AlwaysLockedVaadinSession session;
+
+ public CommunicationMock(final UI ui) throws Exception {
+ servletConfig = new MockServletConfig();
+ servlet = new VaadinServlet();
+ servlet.init(servletConfig);
+
+ deploymentConfiguration = new DefaultDeploymentConfiguration(
+ UI.class, new Properties());
+
+ service = new VaadinServletService(servlet,
+ deploymentConfiguration);
+ session = new AlwaysLockedVaadinSession(service);
+ LegacyCommunicationManager communicationManager = new LegacyCommunicationManager(
+ session);
+ session.setCommunicationManager(communicationManager);
+ session.setConfiguration(deploymentConfiguration);
+ session.addUIProvider(new UIProvider() {
+
+ @Override
+ public Class<? extends UI> getUIClass(
+ UIClassSelectionEvent event) {
+ return ui.getClass();
+ }
+
+ @Override
+ public UI createInstance(UICreateEvent event) {
+ return ui;
+ }
+ });
+ this.ui = ui;
+ }
+
+ public VaadinRequest createInitRequest() {
+ return new VaadinServletRequest(
+ Mockito.mock(HttpServletRequest.class), service) {
+ @Override
+ public String getMethod() {
+ return "POST";
+ }
+
+ @Override
+ public String getParameter(String name) {
+ if (UIInitHandler.BROWSER_DETAILS_PARAMETER.equals(name)) {
+ return "1";
+ }
+ return super.getParameter(name);
+ }
+
+ };
+ }
+
+ }
+
+ @Test
+ public void errorHandlerForInitException() throws Exception {
+ final AtomicInteger pre = new AtomicInteger(0);
+ final AtomicInteger errorHandlerCalls = new AtomicInteger(0);
+
+ UI ui = new UI() {
+ @Override
+ protected void init(VaadinRequest request) {
+ pre.incrementAndGet();
+ throw new RuntimeException("Exception produced in init()");
+ }
+ };
+
+ ui.setErrorHandler(new ErrorHandler() {
+ @Override
+ public void error(ErrorEvent event) {
+ errorHandlerCalls.incrementAndGet();
+ }
+ });
+
+ CommunicationMock mock = new CommunicationMock(ui);
+ VaadinRequest initRequest = mock.createInitRequest();
+
+ ServletUIInitHandler servletUIInitHandler = new ServletUIInitHandler();
+ servletUIInitHandler.handleRequest(mock.session, initRequest,
+ new VaadinServletResponse(
+ Mockito.mock(HttpServletResponse.class), mock.service) {
+ @Override
+ public ServletOutputStream getOutputStream()
+ throws IOException {
+ return new ServletOutputStream() {
+ @Override
+ public void write(int b) throws IOException {
+ }
+ };
+ }
+ });
+
+ Assert.assertEquals(1, pre.getAndIncrement());
+ Assert.assertEquals(1, errorHandlerCalls.getAndIncrement());
+ Assert.assertEquals(mock.session, ui.getSession());
+ }
+
+ @Test
+ public void initExceptionNoErrorHandler() throws Exception {
+ final AtomicInteger pre = new AtomicInteger(0);
+
+ UI ui = new UI() {
+ @Override
+ protected void init(VaadinRequest request) {
+ pre.incrementAndGet();
+ throw new RuntimeException("Exception produced in init()");
+ }
+ };
+
+ CommunicationMock mock = new CommunicationMock(ui);
+ VaadinRequest initRequest = mock.createInitRequest();
+
+ ServletUIInitHandler servletUIInitHandler = new ServletUIInitHandler();
+ servletUIInitHandler.handleRequest(mock.session, initRequest,
+ new VaadinServletResponse(
+ Mockito.mock(HttpServletResponse.class), mock.service) {
+ @Override
+ public ServletOutputStream getOutputStream()
+ throws IOException {
+ return new ServletOutputStream() {
+ @Override
+ public void write(int b) throws IOException {
+ }
+ };
+ }
+ });
+
+ Assert.assertEquals(1, pre.getAndIncrement());
+ // Default error handler only logs the exception
+ Assert.assertEquals(mock.session, ui.getSession());
+ }
+
+}
diff --git a/server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java b/server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java
index fca87ccbdf..a3375585c7 100644
--- a/server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java
@@ -74,6 +74,7 @@ public class ClassesSerializableTest {
// interfaces
"com\\.vaadin\\.server\\.LegacyCommunicationManager.*", //
"com\\.vaadin\\.buildhelpers.*", //
+ "com\\.vaadin\\.util\\.EncodeUtil.*", //
"com\\.vaadin\\.util\\.ReflectTools.*", //
"com\\.vaadin\\.data\\.util\\.ReflectTools.*", //
"com\\.vaadin\\.data\\.util\\.JsonUtil.*", //
@@ -235,6 +236,7 @@ public class ClassesSerializableTest {
Assert.fail(
"Serializable not implemented by the following classes and interfaces: "
+ nonSerializableString);
+
}
private static boolean isFunctionalType(Type type) {
diff --git a/server/src/test/java/com/vaadin/util/EncodeUtilTest.java b/server/src/test/java/com/vaadin/util/EncodeUtilTest.java
new file mode 100644
index 0000000000..7bac539968
--- /dev/null
+++ b/server/src/test/java/com/vaadin/util/EncodeUtilTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2016 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.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EncodeUtilTest {
+ @Test
+ public void rfc5987Encode() {
+ Assert.assertEquals("A", EncodeUtil.rfc5987Encode("A"));
+ Assert.assertEquals("%20", EncodeUtil.rfc5987Encode(" "));
+ Assert.assertEquals("%c3%a5", EncodeUtil.rfc5987Encode("å"));
+ Assert.assertEquals("%e6%97%a5", EncodeUtil.rfc5987Encode("日"));
+
+ Assert.assertEquals("A" + "%20" + "%c3%a5" + "%e6%97%a5",
+ EncodeUtil.rfc5987Encode("A å日"));
+ }
+}
diff --git a/shared/pom.xml b/shared/pom.xml
index c896f6f744..6956e6c490 100644
--- a/shared/pom.xml
+++ b/shared/pom.xml
@@ -79,7 +79,7 @@
<execution>
<id>copy-sources</id>
<!-- here the phase you need -->
- <phase>prepare-package</phase>
+ <phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
diff --git a/uitest/src/main/java/com/vaadin/tests/components/FileDownloaderUI.java b/uitest/src/main/java/com/vaadin/tests/components/FileDownloaderUI.java
index 141ef664b4..e74a7128d5 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/FileDownloaderUI.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/FileDownloaderUI.java
@@ -99,8 +99,8 @@ public class FileDownloaderUI extends AbstractTestUIWithLog {
addComponents("Class resource pdf", resource, components);
Button downloadUtf8File = new Button("Download UTF-8 named file");
- FileDownloader fd = new FileDownloader(
- new ClassResource(new EmbeddedPdf().getClass(), "åäö-日本語.pdf"));
+ FileDownloader fd = new FileDownloader(new ClassResource(
+ new EmbeddedPdf().getClass(), "File åäö-日本語.pdf"));
fd.setOverrideContentType(false);
fd.extend(downloadUtf8File);
addComponent(downloadUtf8File);
diff --git a/uitest/src/main/java/com/vaadin/tests/components/grid/GridDetailsReattach.java b/uitest/src/main/java/com/vaadin/tests/components/grid/GridDetailsReattach.java
new file mode 100755
index 0000000000..0328d87d07
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/components/grid/GridDetailsReattach.java
@@ -0,0 +1,37 @@
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.VerticalLayout;
+
+public class GridDetailsReattach extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ final VerticalLayout verticalMain = new VerticalLayout();
+
+ final VerticalLayout layoutWithGrid = new VerticalLayout();
+
+ Grid<String> grid = new Grid<>("Grid");
+ grid.addColumn(String::toString).setCaption("Foo");
+ grid.setHeight("150px");
+ grid.setItems("Foo");
+ grid.setDetailsGenerator(str -> new Label("AnyDetails"));
+ grid.setDetailsVisible("Foo", true);
+ layoutWithGrid.addComponent(grid);
+
+ Button addCaptionToLayoutWithGridButton = new Button(
+ "Add caption to 'layoutWithGrid' layout");
+ addCaptionToLayoutWithGridButton.addClickListener(e -> layoutWithGrid
+ .setCaption("Caption added to 'layoutWithGrid' layout"));
+ layoutWithGrid.addComponent(addCaptionToLayoutWithGridButton);
+
+ verticalMain.addComponent(layoutWithGrid);
+
+ addComponent(verticalMain);
+
+ }
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/menubar/MenuBarIcons.java b/uitest/src/main/java/com/vaadin/tests/components/menubar/MenuBarIcons.java
new file mode 100644
index 0000000000..9352daed83
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/tests/components/menubar/MenuBarIcons.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2016 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.menubar;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.server.FontAwesome;
+import com.vaadin.server.Resource;
+import com.vaadin.server.ThemeResource;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.MenuBar;
+import com.vaadin.ui.MenuBar.MenuItem;
+
+@Theme("tests-valo")
+public class MenuBarIcons extends AbstractTestUI {
+
+ @Override
+ protected void setup(VaadinRequest request) {
+ MenuBar fontIconMenu = new MenuBar();
+ fontIconMenu.setId("fontIcon");
+ fontIconMenu.setWidth("400px");
+ fontIconMenu.addItem("Main", FontAwesome.MAIL_REPLY_ALL, null);
+ MenuItem hasSub = fontIconMenu.addItem("Has sub", FontAwesome.SUBWAY,
+ null);
+ hasSub.addItem("Sub item", FontAwesome.AMBULANCE, null);
+ for (int i = 0; i < 10; i++) {
+ fontIconMenu.addItem("Filler " + i, FontAwesome.ANGELLIST, null);
+ }
+ MenuItem more = fontIconMenu.getMoreMenuItem();
+ more.setText("More");
+ more.setIcon(FontAwesome.MOTORCYCLE);
+ addComponent(fontIconMenu);
+
+ MenuBar menu = new MenuBar();
+ menu.setId("image");
+ menu.setWidth("400px");
+ Resource imageIcon = new ThemeResource("img/email-reply.png");
+ menu.addItem("Main", imageIcon, null);
+ hasSub = menu.addItem("Has sub", imageIcon, null);
+ hasSub.addItem("Sub item", imageIcon, null);
+ for (int i = 0; i < 10; i++) {
+ menu.addItem("Filler " + i, imageIcon, null);
+ }
+ more = menu.getMoreMenuItem();
+ more.setText("More");
+ more.setIcon(imageIcon);
+ addComponent(menu);
+
+ }
+
+}
diff --git a/uitest/src/main/java/com/vaadin/tests/components/ui/UIInitException.java b/uitest/src/main/java/com/vaadin/tests/components/ui/UIInitException.java
index 22b6a8d031..76573d1f81 100644
--- a/uitest/src/main/java/com/vaadin/tests/components/ui/UIInitException.java
+++ b/uitest/src/main/java/com/vaadin/tests/components/ui/UIInitException.java
@@ -1,12 +1,22 @@
package com.vaadin.tests.components.ui;
+import com.vaadin.server.ErrorHandler;
import com.vaadin.server.VaadinRequest;
import com.vaadin.tests.components.AbstractReindeerTestUI;
+import com.vaadin.ui.Label;
public class UIInitException extends AbstractReindeerTestUI {
@Override
protected void setup(VaadinRequest request) {
+ setErrorHandler(new ErrorHandler() {
+ @Override
+ public void error(com.vaadin.server.ErrorEvent event) {
+ addComponent(new Label("An exception occurred: "
+ + event.getThrowable().getMessage()));
+
+ }
+ });
throw new RuntimeException("Catch me if you can");
}
diff --git a/uitest/src/main/java/com/vaadin/v7/tests/components/grid/RemoveHiddenColumn.java b/uitest/src/main/java/com/vaadin/v7/tests/components/grid/RemoveHiddenColumn.java
new file mode 100644
index 0000000000..1c053ca8d7
--- /dev/null
+++ b/uitest/src/main/java/com/vaadin/v7/tests/components/grid/RemoveHiddenColumn.java
@@ -0,0 +1,60 @@
+package com.vaadin.v7.tests.components.grid;
+
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUIWithLog;
+import com.vaadin.tests.data.bean.Person;
+import com.vaadin.tests.data.bean.Sex;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.v7.data.util.BeanItemContainer;
+import com.vaadin.v7.ui.Grid;
+import com.vaadin.v7.ui.Grid.Column;
+
+public class RemoveHiddenColumn extends AbstractTestUIWithLog {
+
+ private final Grid testGrid = new Grid();
+ private final Button testBtn = new Button("updateGrid");
+ private final Button testBtn2 = new Button("show/hide Grid");
+ private final HorizontalLayout buttonBar = new HorizontalLayout(testBtn,
+ testBtn2);
+ private final VerticalLayout mainLayout = new VerticalLayout(testGrid,
+ buttonBar);
+
+ @Override
+ protected void setup(final VaadinRequest request) {
+ final Grid grid = new Grid();
+ final BeanItemContainer<Person> bic = new BeanItemContainer<Person>(
+ Person.class);
+ grid.setContainerDataSource(bic);
+ grid.setColumns("firstName", "lastName", "email", "age");
+
+ grid.getColumn("firstName").setHidden(true);
+ grid.getColumn("email").setHidden(true);
+
+ Button addRow = new Button("Add data row", new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent e) {
+ bic.addBean(new Person("first", "last", "email", 42, Sex.FEMALE,
+ null));
+
+ }
+ });
+ addRow.setId("add");
+ Button removeColumn = new Button("Remove first column",
+ new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent e) {
+ Column column = grid.getColumns().get(0);
+ log("Removed column '" + column.getHeaderCaption() + "'"
+ + (column.isHidden() ? " (hidden)" : ""));
+ grid.removeColumn(column.getPropertyId());
+ }
+ });
+ removeColumn.setId("remove");
+
+ addComponents(grid, addRow, removeColumn);
+ }
+}
diff --git a/uitest/src/main/resources/com/vaadin/tests/components/embedded/åäö-日本語.pdf b/uitest/src/main/resources/com/vaadin/tests/components/embedded/File åäö-日本語.pdf
index e44a87e9ad..e44a87e9ad 100644
--- a/uitest/src/main/resources/com/vaadin/tests/components/embedded/åäö-日本語.pdf
+++ b/uitest/src/main/resources/com/vaadin/tests/components/embedded/File åäö-日本語.pdf
Binary files differ
diff --git a/uitest/src/main/themes/VAADIN/themes/tests-valo/img/email-reply.png b/uitest/src/main/themes/VAADIN/themes/tests-valo/img/email-reply.png
new file mode 100644
index 0000000000..be7fd2244d
--- /dev/null
+++ b/uitest/src/main/themes/VAADIN/themes/tests-valo/img/email-reply.png
Binary files differ
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/GridDetailsReattachTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridDetailsReattachTest.java
new file mode 100755
index 0000000000..a6fa1dae94
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/tests/components/grid/GridDetailsReattachTest.java
@@ -0,0 +1,34 @@
+package com.vaadin.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.parallel.TestCategory;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridDetailsReattachTest extends MultiBrowserTest {
+
+ @Before
+ public void setUp() {
+ setDebug(true);
+ }
+
+ @Test
+ public void clickToAddCaption() {
+ openTestURL();
+ Assert.assertTrue("Grid details don't exist", hasDetailsElement());
+ $(ButtonElement.class).first().click();
+ Assert.assertTrue("Grid details don't exist after deattach and reattach",hasDetailsElement() );
+ }
+
+ private final By locator = By.className("v-grid-spacer");
+
+ private boolean hasDetailsElement() {
+ return !findElements(locator).isEmpty();
+ }
+
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/grid/GridSelectionTest.java b/uitest/src/test/java/com/vaadin/tests/components/grid/GridSelectionTest.java
index 912a1eb996..25a81984ea 100644
--- a/uitest/src/test/java/com/vaadin/tests/components/grid/GridSelectionTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/components/grid/GridSelectionTest.java
@@ -3,6 +3,11 @@ package com.vaadin.tests.components.grid;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
@@ -403,6 +408,53 @@ public class GridSelectionTest extends GridBasicsTest {
assertTrue(getGridElement().getRow(0).isSelected());
}
+ @Test
+ @Ignore("Removing rows is not implemented in the UI")
+ public void testRemoveSelectedRowMulti() {
+ openTestURL();
+
+ setSelectionModelMulti();
+ GridElement grid = getGridElement();
+ grid.getCell(5, 0).click();
+
+ selectMenuPath("Component", "Body rows", "Remove selected rows");
+ assertSelected();
+ grid.getCell(5, 0).click();
+ assertSelected(5);
+ grid.getCell(6, 0).click();
+ assertSelected(5, 6);
+ grid.getCell(5, 0).click();
+ assertSelected(6);
+ grid.getCell(5, 0).click();
+ grid.getCell(4, 0).click();
+ selectMenuPath("Component", "Body rows", "Remove selected rows");
+ assertSelected();
+ grid.getCell(0, 0).click();
+ assertSelected(0);
+ grid.getCell(5, 0).click();
+ assertSelected(0, 5);
+ grid.getCell(6, 0).click();
+ assertSelected(0, 5, 6);
+
+ }
+
+ private void assertSelected(Integer... selected) {
+ GridElement grid = getGridElement();
+ HashSet<Integer> expected = new HashSet<Integer>(
+ Arrays.asList(selected));
+ for (int i = 0; i < 10; i++) {
+ boolean rowSelected = grid.getRow(i).isSelected();
+ if (expected.contains(i)) {
+ Assert.assertTrue("Expected row " + i + " to be selected",
+ rowSelected);
+ } else {
+ Assert.assertFalse("Expected row " + i + " not to be selected",
+ rowSelected);
+ }
+ }
+
+ }
+
private void toggleUserSelectionAllowed() {
selectMenuPath("Component", "State", "Disallow user selection");
}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/menubar/MenuBarIconsTest.java b/uitest/src/test/java/com/vaadin/tests/components/menubar/MenuBarIconsTest.java
new file mode 100644
index 0000000000..7213d2d466
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/tests/components/menubar/MenuBarIconsTest.java
@@ -0,0 +1,82 @@
+package com.vaadin.tests.components.menubar;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.server.FontAwesome;
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.elements.MenuBarElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class MenuBarIconsTest extends SingleBrowserTest {
+
+ @Test
+ public void fontIconsRendered() {
+ openTestURL();
+ MenuBarElement menu = $(MenuBarElement.class).id("fontIcon");
+ WebElement moreItem = menu
+ .findElements(By.className("v-menubar-menuitem")).get(3);
+
+ assertFontIcon(FontAwesome.MAIL_REPLY_ALL,
+ menu.findElement(By.vaadin("#Main")));
+ WebElement hasSubElement = menu.findElement(By.vaadin("#Has sub"));
+ assertFontIcon(FontAwesome.SUBWAY, hasSubElement);
+ assertFontIcon(FontAwesome.ANGELLIST,
+ menu.findElement(By.vaadin("#Filler 0")));
+
+ hasSubElement.click();
+
+ assertFontIcon(FontAwesome.AMBULANCE,
+ hasSubElement.findElement(By.vaadin("#Sub item")));
+ // Close sub menu
+ hasSubElement.click();
+
+ assertFontIcon(FontAwesome.MOTORCYCLE, moreItem);
+
+ moreItem.click();
+ WebElement filler5 = moreItem.findElement(By.vaadin("#Filler 5"));
+ assertFontIcon(FontAwesome.ANGELLIST, filler5);
+
+ }
+
+ @Test
+ public void imageIconsRendered() {
+ openTestURL();
+ MenuBarElement menu = $(MenuBarElement.class).id("image");
+ WebElement moreItem = menu
+ .findElements(By.className("v-menubar-menuitem")).get(3);
+
+ String image = "/tests-valo/img/email-reply.png";
+ assertImage(image, menu.findElement(By.vaadin("#Main")));
+ WebElement hasSubElement = menu.findElement(By.vaadin("#Has sub"));
+ assertImage(image, hasSubElement);
+ assertImage(image, menu.findElement(By.vaadin("#Filler 0")));
+
+ hasSubElement.click();
+
+ assertImage(image, hasSubElement.findElement(By.vaadin("#Sub item")));
+ // Close sub menu
+ hasSubElement.click();
+
+ assertImage(image, moreItem);
+
+ moreItem.click();
+ WebElement filler5 = moreItem.findElement(By.vaadin("#Filler 5"));
+ assertImage(image, filler5);
+
+ }
+
+ private void assertImage(String image, WebElement menuItem) {
+ WebElement imageElement = menuItem.findElement(By.className("v-icon"));
+ Assert.assertTrue(imageElement.getAttribute("src").endsWith(image));
+ }
+
+ private void assertFontIcon(FontAwesome expected, WebElement menuItem) {
+ WebElement mainIcon = menuItem.findElement(By.className("v-icon"));
+
+ Assert.assertEquals(expected.getCodepoint(),
+ mainIcon.getText().codePointAt(0));
+
+ }
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/ui/UIInitExceptionTest.java b/uitest/src/test/java/com/vaadin/tests/components/ui/UIInitExceptionTest.java
index c1d6aaa55b..064132d4c7 100644
--- a/uitest/src/test/java/com/vaadin/tests/components/ui/UIInitExceptionTest.java
+++ b/uitest/src/test/java/com/vaadin/tests/components/ui/UIInitExceptionTest.java
@@ -3,9 +3,9 @@ package com.vaadin.tests.components.ui;
import org.junit.Assert;
import org.junit.Test;
-import com.vaadin.tests.tb3.MultiBrowserTest;
+import com.vaadin.tests.tb3.SingleBrowserTest;
-public class UIInitExceptionTest extends MultiBrowserTest {
+public class UIInitExceptionTest extends SingleBrowserTest {
@Test
public void testExceptionOnUIInit() throws Exception {
openTestURL();
diff --git a/uitest/src/test/java/com/vaadin/v7/tests/components/grid/RemoveHiddenColumnTest.java b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/RemoveHiddenColumnTest.java
new file mode 100644
index 0000000000..ecb5285401
--- /dev/null
+++ b/uitest/src/test/java/com/vaadin/v7/tests/components/grid/RemoveHiddenColumnTest.java
@@ -0,0 +1,45 @@
+package com.vaadin.v7.tests.components.grid;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.tests.tb3.SingleBrowserTest;
+
+public class RemoveHiddenColumnTest extends SingleBrowserTest {
+
+ @Test
+ public void removeHiddenColumnInEmptyGrid() {
+ openTestURL("debug");
+ removeColumns();
+ }
+
+ @Test
+ public void removeHiddenColumnInPopulatedGrid() {
+ openTestURL("debug");
+ ButtonElement add = $(ButtonElement.class).id("add");
+ add.click();
+ removeColumns();
+
+ }
+
+ private void removeColumns() {
+ ButtonElement remove = $(ButtonElement.class).id("remove");
+ remove.click();
+ Assert.assertEquals("1. Removed column 'First Name' (hidden)",
+ getLogRow(0));
+ assertNoErrorNotifications();
+
+ remove.click();
+ Assert.assertEquals("2. Removed column 'Last Name'", getLogRow(0));
+ assertNoErrorNotifications();
+ remove.click();
+ Assert.assertEquals("3. Removed column 'Email' (hidden)", getLogRow(0));
+ assertNoErrorNotifications();
+ remove.click();
+ Assert.assertEquals("4. Removed column 'Age'", getLogRow(0));
+ assertNoErrorNotifications();
+
+ }
+
+}