summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--WebContent/VAADIN/themes/base/grid/grid.scss22
-rw-r--r--client/src/com/vaadin/client/ui/dd/DragAndDropHandler.java100
-rw-r--r--client/src/com/vaadin/client/ui/dd/DragHandle.java220
-rw-r--r--client/src/com/vaadin/client/widgets/Escalator.java4
-rw-r--r--client/src/com/vaadin/client/widgets/Grid.java124
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/AbstractGridColumnAutoWidthTest.java4
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNamesTest.java28
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java24
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java16
9 files changed, 463 insertions, 79 deletions
diff --git a/WebContent/VAADIN/themes/base/grid/grid.scss b/WebContent/VAADIN/themes/base/grid/grid.scss
index a176114fb6..5ae62940f4 100644
--- a/WebContent/VAADIN/themes/base/grid/grid.scss
+++ b/WebContent/VAADIN/themes/base/grid/grid.scss
@@ -260,6 +260,16 @@ $v-grid-details-border-bottom-stripe: 1px solid darken($v-grid-row-background-co
}
}
+ .#{$primaryStyleName}-column-resize-handle {
+ position: absolute;
+ width: 20px;
+ top: 0px;
+ bottom: 0px;
+ right: -10px;
+ cursor: col-resize;
+ z-index: 10;
+ }
+
// Footer
.#{$primaryStyleName}-footer {
@@ -278,6 +288,18 @@ $v-grid-details-border-bottom-stripe: 1px solid darken($v-grid-row-background-co
}
}
+ // Header and footer content
+
+ .#{$primaryStyleName}-column-header-content,
+ .#{$primaryStyleName}-column-footer-content {
+ width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ // Hackish, needed to override the "v-grid-cell > *" rule above
+ line-height: $v-grid-row-height;
+ vertical-align: baseline;
+ }
+
// Decorative elements
.#{$primaryStyleName}-header-deco {
diff --git a/client/src/com/vaadin/client/ui/dd/DragAndDropHandler.java b/client/src/com/vaadin/client/ui/dd/DragAndDropHandler.java
index e2b51fb72d..63c44f1fd5 100644
--- a/client/src/com/vaadin/client/ui/dd/DragAndDropHandler.java
+++ b/client/src/com/vaadin/client/ui/dd/DragAndDropHandler.java
@@ -21,6 +21,7 @@ import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
+import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.RootPanel;
import com.vaadin.client.WidgetUtil;
import com.vaadin.client.widgets.Grid;
@@ -46,20 +47,20 @@ public class DragAndDropHandler {
* Called when the drag has started. The drag can be canceled by
* returning {@code false}.
*
- * @param startEvent
+ * @param e
* the original event that started the drag
* @return {@code true} if the drag is OK to start, {@code false} to
* cancel
*/
- boolean onDragStart(NativeEvent startEvent);
+ boolean onDragStart(Event e);
/**
* Called on drag.
*
- * @param event
+ * @param e
* the event related to the drag
*/
- void onDragUpdate(NativePreviewEvent event);
+ void onDragUpdate(Event e);
/**
* Called after the has ended on a drop or cancel.
@@ -77,45 +78,58 @@ public class DragAndDropHandler {
void onDragCancel();
}
- private HandlerRegistration dragStartNativePreviewHandlerRegistration;
+ private HandlerRegistration startPreviewHandler;
private HandlerRegistration dragHandlerRegistration;
-
+ private DragAndDropCallback callback;
private boolean dragging;
- private DragAndDropCallback callback;
+ // XXX: This is a hack to stop a click event from propagating through to the
+ // client once dragging has completed. In the Grid case, this caused
+ // erroneous selections and/or sorting events.
+ private Timer stopTimer = new Timer() {
+ @Override
+ public void run() {
+ Event.releaseCapture(RootPanel.getBodyElement());
+ if (callback != null) {
+ callback.onDragEnd();
+ callback = null;
+ }
+ if (dragHandlerRegistration != null) {
+ dragHandlerRegistration.removeHandler();
+ dragHandlerRegistration = null;
+ }
+ dragging = false;
+ }
+ };
- private final NativePreviewHandler dragHandler = new NativePreviewHandler() {
+ private final NativePreviewHandler dragPreviewHandler = new NativePreviewHandler() {
@Override
public void onPreviewNativeEvent(NativePreviewEvent event) {
if (dragging) {
final int typeInt = event.getTypeInt();
switch (typeInt) {
+ case Event.ONMOUSEMOVE:
+ case Event.ONTOUCHMOVE:
+ callback.onDragUpdate(Event.as(event.getNativeEvent()));
+ break;
case Event.ONKEYDOWN:
+ // End drag if ESC is pressed
int keyCode = event.getNativeEvent().getKeyCode();
if (keyCode == KeyCodes.KEY_ESCAPE) {
- // end drag if ESC is hit
cancelDrag(event);
}
break;
- case Event.ONMOUSEMOVE:
- case Event.ONTOUCHMOVE:
- callback.onDragUpdate(event);
- // prevent text selection on IE
- event.getNativeEvent().preventDefault();
- break;
case Event.ONTOUCHCANCEL:
cancelDrag(event);
break;
case Event.ONTOUCHEND:
- /* Avoid simulated event on drag end */
- event.getNativeEvent().preventDefault();
- //$FALL-THROUGH$
case Event.ONMOUSEUP:
- callback.onDragUpdate(event);
+ callback.onDragUpdate(Event.as(event.getNativeEvent()));
callback.onDrop();
stopDrag();
- event.cancel();
+ break;
+ case Event.ONCLICK:
break;
default:
break;
@@ -123,6 +137,12 @@ public class DragAndDropHandler {
} else {
stopDrag();
}
+
+ // Kill events - as long as this thing is active, we don't want to
+ // let any event through.
+ event.getNativeEvent().stopPropagation();
+ event.getNativeEvent().preventDefault();
+ event.cancel();
}
};
@@ -142,7 +162,7 @@ public class DragAndDropHandler {
public void onDragStartOnDraggableElement(
final NativeEvent dragStartingEvent,
final DragAndDropCallback callback) {
- dragStartNativePreviewHandlerRegistration = Event
+ startPreviewHandler = Event
.addNativePreviewHandler(new NativePreviewHandler() {
private int startX = WidgetUtil
@@ -184,14 +204,17 @@ public class DragAndDropHandler {
.getNativeEvent());
if (Math.abs(startX - currentX) > 3
|| Math.abs(startY - currentY) > 3) {
- removeNativePreviewHandlerRegistration();
+ removeStartPreviewHandler();
startDrag(dragStartingEvent, event, callback);
}
+ event.getNativeEvent().stopPropagation();
+ event.getNativeEvent().preventDefault();
+ event.cancel();
break;
default:
// on any other events, clean up this preview
// listener
- removeNativePreviewHandlerRegistration();
+ removeStartPreviewHandler();
break;
}
}
@@ -200,27 +223,22 @@ public class DragAndDropHandler {
private void startDrag(NativeEvent startEvent,
NativePreviewEvent triggerEvent, DragAndDropCallback callback) {
- if (callback.onDragStart(startEvent)) {
+ if (callback.onDragStart(Event.as(startEvent))) {
+ this.callback = callback;
dragging = true;
+
// just capture something to prevent text selection in IE
Event.setCapture(RootPanel.getBodyElement());
- this.callback = callback;
+
dragHandlerRegistration = Event
- .addNativePreviewHandler(dragHandler);
- callback.onDragUpdate(triggerEvent);
+ .addNativePreviewHandler(dragPreviewHandler);
+ callback.onDragUpdate(Event.as(triggerEvent.getNativeEvent()));
}
}
private void stopDrag() {
- dragging = false;
- if (dragHandlerRegistration != null) {
- dragHandlerRegistration.removeHandler();
- dragHandlerRegistration = null;
- }
- Event.releaseCapture(RootPanel.getBodyElement());
- if (callback != null) {
- callback.onDragEnd();
- callback = null;
+ if (!stopTimer.isRunning()) {
+ stopTimer.schedule(100);
}
}
@@ -228,14 +246,12 @@ public class DragAndDropHandler {
callback.onDragCancel();
callback.onDragEnd();
stopDrag();
- event.cancel();
- event.getNativeEvent().preventDefault();
}
- private void removeNativePreviewHandlerRegistration() {
- if (dragStartNativePreviewHandlerRegistration != null) {
- dragStartNativePreviewHandlerRegistration.removeHandler();
- dragStartNativePreviewHandlerRegistration = null;
+ private void removeStartPreviewHandler() {
+ if (startPreviewHandler != null) {
+ startPreviewHandler.removeHandler();
+ startPreviewHandler = null;
}
}
}
diff --git a/client/src/com/vaadin/client/ui/dd/DragHandle.java b/client/src/com/vaadin/client/ui/dd/DragHandle.java
new file mode 100644
index 0000000000..c3a0768a72
--- /dev/null
+++ b/client/src/com/vaadin/client/ui/dd/DragHandle.java
@@ -0,0 +1,220 @@
+/*
+ * 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.client.ui.dd;
+
+import com.google.gwt.dom.client.DivElement;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.EventListener;
+import com.vaadin.client.WidgetUtil;
+import com.vaadin.client.ui.dd.DragAndDropHandler.DragAndDropCallback;
+
+/**
+ * Drag handle implementation. Drag handles are used for moving or resizing
+ * widgets. This is a minimal-case component, meant to be used specifically as a
+ * drag handle attached to another widget or element. As such, it does
+ * <b>not</b> provide access to the events it's listening to (from the point of
+ * view of this component, there really is no use for that). For the more
+ * general, event-providing interface that this component is based on, see
+ * {@link DragAndDropHandler}.
+ *
+ * @since
+ */
+public class DragHandle {
+
+ /**
+ * Callback interface for the DragHandle event life cycle
+ */
+ public interface DragHandleCallback {
+
+ /**
+ * Called when dragging starts
+ */
+ public void onStart();
+
+ /**
+ * Called when the drag handle has moved.
+ *
+ * @param deltaX
+ * change in X direction since start
+ * @param deltaY
+ * change in Y direction since start
+ */
+ public void onUpdate(double deltaX, double deltaY);
+
+ /**
+ * Called when the drag operation has been cancelled (usually by
+ * pressing ESC)
+ */
+ public void onCancel();
+
+ /**
+ * Called when the drag operation completes successfully
+ */
+ public void onComplete();
+
+ }
+
+ private Element parent;
+ private DivElement element;
+ private String baseClassName;
+
+ private DragAndDropHandler dndHandler;
+ private DragAndDropCallback dndCallback;
+
+ private DragHandleCallback userCallback;
+
+ /**
+ * Creates a new DragHandle.
+ *
+ * @param baseName
+ * CSS style name to use for this DragHandle element. This
+ * parameter is supplied to the constructor (rather than added
+ * later) both to provide the "-dragged" style and to make sure
+ * that the drag handle can be properly styled (it's otherwise
+ * invisible)
+ * @param callback
+ * Callback object allows hooking up the drag handle to the rest
+ * of the program logic
+ */
+ public DragHandle(String baseName, DragHandleCallback callback) {
+ parent = null;
+ element = DivElement.as(DOM.createElement("div"));
+ baseClassName = baseName;
+ userCallback = callback;
+ addStyleName(baseClassName);
+
+ dndCallback = new DragAndDropCallback() {
+
+ private double startX;
+ private double startY;
+
+ @Override
+ public void onDrop() {
+ removeDraggingStyle();
+ userCallback.onComplete();
+ }
+
+ @Override
+ public void onDragUpdate(Event e) {
+ double dx = WidgetUtil.getTouchOrMouseClientX(e) - startX;
+ double dy = WidgetUtil.getTouchOrMouseClientY(e) - startY;
+ userCallback.onUpdate(dx, dy);
+ }
+
+ @Override
+ public boolean onDragStart(Event e) {
+ addDraggingStyle();
+ startX = WidgetUtil.getTouchOrMouseClientX(e);
+ startY = WidgetUtil.getTouchOrMouseClientY(e);
+ userCallback.onStart();
+ return true;
+ }
+
+ @Override
+ public void onDragEnd() {
+ removeDraggingStyle();
+ userCallback.onComplete();
+ }
+
+ @Override
+ public void onDragCancel() {
+ removeDraggingStyle();
+ userCallback.onCancel();
+ }
+
+ private void addDraggingStyle() {
+ addStyleName(baseClassName + "-dragged");
+ }
+
+ private void removeDraggingStyle() {
+ removeStyleName(baseClassName + "-dragged");
+ }
+ };
+ dndHandler = new DragAndDropHandler();
+
+ DOM.sinkEvents(element, Event.ONMOUSEDOWN | Event.ONTOUCHSTART);
+ DOM.setEventListener(element, new EventListener() {
+ @Override
+ public void onBrowserEvent(Event event) {
+ dndHandler.onDragStartOnDraggableElement(event, dndCallback);
+ event.stopPropagation();
+ }
+ });
+ }
+
+ /**
+ * Returns the current parent element for this drag handle. May be null.
+ *
+ * @return an Element or null
+ */
+ public Element getParent() {
+ return parent;
+ }
+
+ /**
+ * Gets the element used as actual drag handle.
+ *
+ * @return an Element
+ */
+ public Element getElement() {
+ return element;
+ }
+
+ /**
+ * Adds this drag handle to an HTML element.
+ *
+ * @param elem
+ * an element
+ */
+ public void addTo(Element elem) {
+ removeFromParent();
+ parent = elem;
+ parent.appendChild(element);
+ }
+
+ /**
+ * Removes this drag handle from whatever it was attached to.
+ */
+ public void removeFromParent() {
+ if (parent != null) {
+ parent.removeChild(element);
+ parent = null;
+ }
+ }
+
+ /**
+ * Adds CSS style name to the drag handle element.
+ *
+ * @param styleName
+ * a CSS style name
+ */
+ public void addStyleName(String styleName) {
+ element.addClassName(styleName);
+ }
+
+ /**
+ * Removes existing style name from drag handle element.
+ *
+ * @param styleName
+ * a CSS style name
+ */
+ public void removeStyleName(String styleName) {
+ element.removeClassName(styleName);
+ }
+
+}
diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java
index 9b9616f474..1400d63b6b 100644
--- a/client/src/com/vaadin/client/widgets/Escalator.java
+++ b/client/src/com/vaadin/client/widgets/Escalator.java
@@ -5323,8 +5323,8 @@ public class Escalator extends Widget implements RequiresResize,
int[] indices = new int[splitArgs.length - 1];
for (int i = 0; i < indices.length; ++i) {
String tmp = splitArgs[i + 1];
- indices[i] = Integer
- .parseInt(tmp.substring(0, tmp.length() - 1));
+ indices[i] = Integer.parseInt(tmp.substring(0,
+ tmp.indexOf("]", 1)));
}
return new SubPartArguments(type, indices);
}
diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java
index 2eefc87f44..506b3fc876 100644
--- a/client/src/com/vaadin/client/widgets/Grid.java
+++ b/client/src/com/vaadin/client/widgets/Grid.java
@@ -86,6 +86,9 @@ import com.vaadin.client.renderers.WidgetRenderer;
import com.vaadin.client.ui.FocusUtil;
import com.vaadin.client.ui.SubPartAware;
import com.vaadin.client.ui.dd.DragAndDropHandler;
+import com.vaadin.client.ui.dd.DragAndDropHandler.DragAndDropCallback;
+import com.vaadin.client.ui.dd.DragHandle;
+import com.vaadin.client.ui.dd.DragHandle.DragHandleCallback;
import com.vaadin.client.widget.escalator.Cell;
import com.vaadin.client.widget.escalator.ColumnConfiguration;
import com.vaadin.client.widget.escalator.EscalatorUpdater;
@@ -951,8 +954,8 @@ public class Grid<T> extends ResizeComposite implements
}
/**
- * A single cell in a grid header row. Has a textual caption.
- *
+ * A single cell in a grid header row. Has a caption and, if it's in a
+ * default row, a drag handle.
*/
public static class HeaderCell extends StaticSection.StaticCell {
}
@@ -3037,7 +3040,9 @@ public class Grid<T> extends ResizeComposite implements
}
- /** @see Grid#autoColumnWidthsRecalculator */
+ /**
+ * @see Grid#autoColumnWidthsRecalculator
+ */
private class AutoColumnWidthsRecalculator {
private double lastCalculatedInnerWidth = -1;
@@ -3986,7 +3991,7 @@ public class Grid<T> extends ResizeComposite implements
private AutoScroller autoScroller = new AutoScroller(this);
- private DragAndDropHandler.DragAndDropCallback headerCellDndCallback = new DragAndDropHandler.DragAndDropCallback() {
+ private DragAndDropHandler.DragAndDropCallback headerCellDndCallback = new DragAndDropCallback() {
private final AutoScrollerCallback autoScrollerCallback = new AutoScrollerCallback() {
@@ -4071,10 +4076,9 @@ public class Grid<T> extends ResizeComposite implements
}
@Override
- public void onDragUpdate(NativePreviewEvent event) {
- if (event != null) {
- clientX = WidgetUtil.getTouchOrMouseClientX(event
- .getNativeEvent());
+ public void onDragUpdate(Event e) {
+ if (e != null) {
+ clientX = WidgetUtil.getTouchOrMouseClientX(e);
autoScrollX = 0;
}
resolveDragElementHorizontalPosition(clientX);
@@ -4179,7 +4183,7 @@ public class Grid<T> extends ResizeComposite implements
}
@Override
- public boolean onDragStart(NativeEvent startingEvent) {
+ public boolean onDragStart(Event e) {
calculatePossibleDropPositions();
if (possibleDropPositions.isEmpty()) {
@@ -4200,8 +4204,7 @@ public class Grid<T> extends ResizeComposite implements
// start the auto scroll handler
autoScroller.setScrollArea(60);
- autoScroller.start(startingEvent, ScrollAxis.HORIZONTAL,
- autoScrollerCallback);
+ autoScroller.start(e, ScrollAxis.HORIZONTAL, autoScrollerCallback);
return true;
}
@@ -5458,22 +5461,91 @@ public class Grid<T> extends ResizeComposite implements
// Assign colspan to cell before rendering
cell.setColSpan(metadata.getColspan());
- TableCellElement element = cell.getElement();
+ Element td = cell.getElement();
+ td.removeAllChildren();
+
+ Element content;
+ // Wrap text or html content in default header to isolate
+ // the content from the possible column resize drag handle
+ // next to it
+ if (metadata.getType() != GridStaticCellType.WIDGET) {
+ content = DOM.createDiv();
+
+ if (staticRow instanceof HeaderRow) {
+ content.setClassName(getStylePrimaryName()
+ + "-column-header-content");
+ if (((HeaderRow) staticRow).isDefault()) {
+ content.setClassName(content.getClassName() + " "
+ + getStylePrimaryName()
+ + "-column-default-header-content");
+ }
+ } else if (staticRow instanceof FooterRow) {
+ content.setClassName(getStylePrimaryName()
+ + "-column-footer-content");
+ } else {
+ getLogger().severe(
+ "Unhandled static row type "
+ + staticRow.getClass()
+ .getCanonicalName());
+ }
+
+ td.appendChild(content);
+ } else {
+ content = td;
+ }
+ setCustomStyleName(content, metadata.getStyleName());
+
switch (metadata.getType()) {
case TEXT:
- element.setInnerText(metadata.getText());
+ content.setInnerText(metadata.getText());
break;
case HTML:
- element.setInnerHTML(metadata.getHtml());
+ content.setInnerHTML(metadata.getHtml());
break;
case WIDGET:
preDetach(row, Arrays.asList(cell));
- element.setInnerHTML("");
+ content.setInnerHTML("");
postAttach(row, Arrays.asList(cell));
break;
}
- setCustomStyleName(element, metadata.getStyleName());
+ // XXX: Should add only once in preAttach/postAttach or when
+ // resizable status changes
+ // Only add resize handles to default header row for now
+ if (staticRow instanceof HeaderRow
+ && ((HeaderRow) staticRow).isDefault()) {
+
+ final int column = cell.getColumn();
+ DragHandle dragger = new DragHandle(getStylePrimaryName()
+ + "-column-resize-handle",
+ new DragHandleCallback() {
+
+ private Column<?, T> col = getVisibleColumn(column);
+ private double initialWidth = 0;
+
+ @Override
+ public void onUpdate(double deltaX,
+ double deltaY) {
+ col.setWidth(initialWidth + deltaX);
+ }
+
+ @Override
+ public void onStart() {
+ initialWidth = col.getWidthActual();
+ }
+
+ @Override
+ public void onComplete() {
+ // NOP
+ }
+
+ @Override
+ public void onCancel() {
+ col.setWidth(initialWidth);
+ }
+ });
+ dragger.addTo(td);
+ }
cellFocusHandler.updateFocusedCellStyle(cell, container);
}
@@ -7140,15 +7212,33 @@ public class Grid<T> extends ResizeComposite implements
* handles details[] (translated to spacer[] for Escalator), cell[],
* header[] and footer[]
*/
+
+ // "#header[0][0]/DRAGhANDLE"
Element escalatorElement = escalator.getSubPartElement(subPart
.replaceFirst("^details\\[", "spacer["));
if (escalatorElement != null) {
+
+ int detailIdx = subPart.indexOf("/");
+ if (detailIdx > 0) {
+ String detail = subPart.substring(detailIdx + 1);
+ getLogger().severe(
+ "Looking up detail from index " + detailIdx
+ + " onward: \"" + detail + "\"");
+ if (detail.equalsIgnoreCase("content")) {
+ // XXX: Fix this to look up by class name!
+ return DOM.asOld(Element.as(escalatorElement.getChild(0)));
+ }
+ if (detail.equalsIgnoreCase("draghandle")) {
+ // XXX: Fix this to look up by class name!
+ return DOM.asOld(Element.as(escalatorElement.getChild(1)));
+ }
+ }
+
return DOM.asOld(escalatorElement);
}
SubPartArguments args = SubPartArguments.create(subPart);
-
Element editor = getSubPartElementEditor(args);
if (editor != null) {
return DOM.asOld(editor);
diff --git a/uitest/src/com/vaadin/tests/components/grid/AbstractGridColumnAutoWidthTest.java b/uitest/src/com/vaadin/tests/components/grid/AbstractGridColumnAutoWidthTest.java
index a9e0b03932..422c57d842 100644
--- a/uitest/src/com/vaadin/tests/components/grid/AbstractGridColumnAutoWidthTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/AbstractGridColumnAutoWidthTest.java
@@ -99,9 +99,9 @@ public abstract class AbstractGridColumnAutoWidthTest extends MultiBrowserTest {
private WebElement[] getColumn(int i) {
WebElement[] col = new WebElement[3];
col[0] = getDriver().findElement(
- By.xpath("//thead//th[" + (i + 1) + "]/span"));
+ By.xpath("//thead//th[" + (i + 1) + "]/div[1]/span"));
col[1] = getDriver().findElement(
- By.xpath("//tbody//td[" + (i + 1) + "]/span"));
+ By.xpath("//tbody//td[" + (i + 1) + "]//span"));
col[2] = getDriver().findElement(
By.xpath("//tbody//td[" + (i + 1) + "]"));
return col;
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNamesTest.java b/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNamesTest.java
index 8b3a81e660..f5216b4287 100644
--- a/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNamesTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/GridHeaderStyleNamesTest.java
@@ -18,6 +18,7 @@ package com.vaadin.tests.components.grid;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
+import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import com.vaadin.testbench.elements.ButtonElement;
@@ -41,10 +42,20 @@ public class GridHeaderStyleNamesTest extends SingleBrowserTest {
return grid.getHeaderCell(0, 3);
}
+ private WebElement getMergedHeaderCellContent() {
+ return getMergedHeaderCell().findElement(
+ By.cssSelector("div.v-grid-column-header-content"));
+ }
+
private GridCellElement getAgeFooterCell() {
return grid.getFooterCell(0, 2);
}
+ private WebElement getAgeFooterCellContent() {
+ return getAgeFooterCell().findElement(
+ By.cssSelector("div.v-grid-column-footer-content"));
+ }
+
@Test
public void cellStyleNamesCanBeAddedAndRemoved() {
ButtonElement toggleStyles = $(ButtonElement.class).caption(
@@ -74,23 +85,23 @@ public class GridHeaderStyleNamesTest extends SingleBrowserTest {
if (set) {
assertHasStyleName(
"Footer cell should have the assigned 'age-footer' class name",
- getAgeFooterCell(), "age-footer");
+ getAgeFooterCellContent(), "age-footer");
assertHasStyleName(
"Header cell should have the assigned 'age' class name",
- getAgeHeaderCell(), "age");
+ getAgeHeaderCellContent(), "age");
assertHasStyleName(
"The merged header cell should have the assigned 'city-country' class name",
- getMergedHeaderCell(), "city-country");
+ getMergedHeaderCellContent(), "city-country");
} else {
assertHasNotStyleName(
"Footer cell should not have the removed 'age-footer' class name",
- getAgeFooterCell(), "age-footer");
+ getAgeFooterCellContent(), "age-footer");
assertHasNotStyleName(
"Header cell should not have the removed 'age' class name",
- getAgeHeaderCell(), "age");
+ getAgeHeaderCellContent(), "age");
assertHasNotStyleName(
"Ther merged header cell should not have the removed 'city-country' class name",
- getMergedHeaderCell(), "city-country");
+ getMergedHeaderCellContent(), "city-country");
}
assertHasStyleName(
"The default v-grid-cell style name should not be removed from the header cell",
@@ -133,6 +144,11 @@ public class GridHeaderStyleNamesTest extends SingleBrowserTest {
return grid.getHeaderCell(1, 2);
}
+ private WebElement getAgeHeaderCellContent() {
+ return getAgeHeaderCell().findElement(
+ By.cssSelector("div.v-grid-column-header-content"));
+ }
+
private WebElement getFooterRow() {
return grid.getFooterRow(0);
}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java
index cc801bf870..ef7d15ff3d 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java
@@ -17,6 +17,9 @@ package com.vaadin.tests.components.grid.basicfeatures.client;
import static org.junit.Assert.assertEquals;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
import com.vaadin.testbench.TestBenchElement;
import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures;
@@ -32,16 +35,18 @@ public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest
protected void assertHeaderTexts(int headerId, int rowIndex) {
int i = 0;
for (TestBenchElement cell : getGridElement().getHeaderCells(rowIndex)) {
+ WebElement content = cell.findElement(By.tagName("div"));
if (i % 3 == 0) {
- assertText(String.format("Header (%d,%d)", headerId, i), cell);
+ assertText(String.format("Header (%d,%d)", headerId, i),
+ content);
} else if (i % 2 == 0) {
assertHTML(String.format("<b>Header (%d,%d)</b>", headerId, i),
- cell);
+ content);
} else {
assertHTML(String.format(
"<div class=\"gwt-HTML\">Header (%d,%d)</div>",
- headerId, i), cell);
+ headerId, i), content);
}
i++;
@@ -52,27 +57,30 @@ public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest
protected void assertFooterTexts(int footerId, int rowIndex) {
int i = 0;
for (TestBenchElement cell : getGridElement().getFooterCells(rowIndex)) {
+ WebElement content = cell.findElement(By.tagName("div"));
+
if (i % 3 == 0) {
- assertText(String.format("Footer (%d,%d)", footerId, i), cell);
+ assertText(String.format("Footer (%d,%d)", footerId, i),
+ content);
} else if (i % 2 == 0) {
assertHTML(String.format("<b>Footer (%d,%d)</b>", footerId, i),
- cell);
+ content);
} else {
assertHTML(String.format(
"<div class=\"gwt-HTML\">Footer (%d,%d)</div>",
- footerId, i), cell);
+ footerId, i), content);
}
i++;
}
assertEquals("number of footer columns", GridBasicFeatures.COLUMNS, i);
}
- protected static void assertText(String text, TestBenchElement e) {
+ protected static void assertText(String text, WebElement e) {
// TBE.getText returns "" if the element is scrolled out of view
assertEquals(text, e.getAttribute("innerHTML"));
}
- protected static void assertHTML(String text, TestBenchElement e) {
+ protected static void assertHTML(String text, WebElement e) {
String html = e.getAttribute("innerHTML");
// IE 8 returns tags as upper case while other browsers do not, make the
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java
index f44f39689c..024e54260a 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java
@@ -40,6 +40,17 @@ import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
public class GridStructureTest extends GridBasicFeaturesTest {
@Test
+ public void testResizeHandlesPresent() {
+ openTestURL();
+
+ // Test that all column headers contain resize handles
+ for (int i = 0; i < GridBasicFeatures.COLUMNS; ++i) {
+ assertFalse(getGridElement().getHeaderCell(0, i).findElement(
+ By.cssSelector("div.v-grid-column-resize-handle")) == null);
+ }
+ }
+
+ @Test
public void testRemovingAllColumns() {
setDebug(true);
openTestURL();
@@ -318,13 +329,14 @@ public class GridStructureTest extends GridBasicFeaturesTest {
setDebug(true);
openTestURL();
+ int col = GridBasicFeatures.COLUMNS;
String columnName = "Column " + (GridBasicFeatures.COLUMNS - 1);
assertTrue(columnName + " was not present in DOM",
- isElementPresent(By.xpath("//th[text()='" + columnName + "']")));
+ isElementPresent(By.xpath("//th[" + col + "]/div[1]")));
selectMenuPath("Component", "Columns", columnName, "Add / Remove");
assertFalse(isElementPresent(NotificationElement.class));
assertFalse(columnName + " was still present in DOM",
- isElementPresent(By.xpath("//th[text()='" + columnName + "']")));
+ isElementPresent(By.xpath("//th[" + col + "]/div[1]")));
}
@Test