diff options
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 |