From 7fa43952ca1b1e26afe79f5c0a75f9e735431be0 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Fri, 20 Mar 2015 16:51:45 +0200 Subject: Use special logic for allocating selection col widths (#17091) Change-Id: I2d0a80a26e8211d6f5e9110e1476f857803b4d3f --- client/src/com/vaadin/client/widgets/Grid.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index cb9e9c55d1..f4a5b0961c 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -2528,7 +2528,7 @@ public class Grid extends ResizeComposite implements final double widthFixed = Math.max(widthAsIs, column.getMinimumWidth()); defaultExpandRatios = defaultExpandRatios - && column.getExpandRatio() == -1; + && (column.getExpandRatio() == -1 || column == selectionColumn); if (isFixedWidth) { columnSizes.put(indexOfColumn(column), widthFixed); @@ -2546,7 +2546,8 @@ public class Grid extends ResizeComposite implements .getExpandRatio()); final double newWidth = column.getWidthActual(); final double maxWidth = getMaxWidth(column); - boolean shouldExpand = newWidth < maxWidth && expandRatio > 0; + boolean shouldExpand = newWidth < maxWidth && expandRatio > 0 + && column != selectionColumn; if (shouldExpand) { totalRatios += expandRatio; columnsToExpand.add(column); -- cgit v1.2.3 From 2a671f2810dfb409cc4d30a1606868282d0925d3 Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 23 Mar 2015 12:10:07 +0200 Subject: Fix declarative support for CustomLayout (#17210) CustomLayout now has a public default constructor. If a template is not set using one of the setters, a warning message is displayed like in the case where the template file is specified but not found. Change-Id: I5d56f24fafc5c82e6ab76dec393a0c25bd78aae5 --- .../ui/customlayout/CustomLayoutConnector.java | 22 ++--- server/src/com/vaadin/ui/CustomLayout.java | 36 +++++++- .../customlayout/CustomLayoutDeclarativeTest.java | 96 ++++++++++++++++++++++ .../customlayout/CustomLayoutWithNullTemplate.java | 44 ++++++++++ .../CustomLayoutWithNullTemplateTest.java | 43 ++++++++++ 5 files changed, 229 insertions(+), 12 deletions(-) create mode 100644 server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutDeclarativeTest.java create mode 100644 uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplate.java create mode 100644 uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplateTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java b/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java index 80979587b9..cde1f1af0f 100644 --- a/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/customlayout/CustomLayoutConnector.java @@ -77,22 +77,24 @@ public class CustomLayoutConnector extends AbstractLayoutConnector implements // (even though both can never be given at the same time) templateContents = getConnection().getResource( "layouts/" + templateName + ".html"); - if (templateContents == null) { - // Template missing -> show debug notice and render components - // in order. - getWidget() - .getElement() - .setInnerHTML( - "Layout file layouts/" - + templateName - + ".html is missing. Components will be drawn for debug purposes."); - } } if (templateContents != null) { // Template ok -> initialize. getWidget().initializeHTML(templateContents, getConnection().getThemeUri()); + } else { + // Template missing -> show debug notice and render components in + // order. + String warning = templateName != null ? "Layout file layouts/" + + templateName + ".html is missing." + : "Layout file not specified."; + getWidget() + .getElement() + .setInnerHTML( + "" + + warning + + " Components will be drawn for debug purposes."); } templateUpdated = true; } diff --git a/server/src/com/vaadin/ui/CustomLayout.java b/server/src/com/vaadin/ui/CustomLayout.java index a9c266b0b9..ceb47e1e7a 100644 --- a/server/src/com/vaadin/ui/CustomLayout.java +++ b/server/src/com/vaadin/ui/CustomLayout.java @@ -23,12 +23,16 @@ import java.io.InputStreamReader; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import org.jsoup.nodes.Element; + import com.vaadin.server.JsonPaintTarget; import com.vaadin.server.PaintException; import com.vaadin.server.PaintTarget; import com.vaadin.shared.ui.customlayout.CustomLayoutState; +import com.vaadin.ui.declarative.DesignContext; /** *

@@ -71,8 +75,8 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent { * {@link #setTemplateName(String)}, that makes layout fetch the template * from theme, or {@link #setTemplateContents(String)}. */ - protected CustomLayout() { - setWidth(100, UNITS_PERCENTAGE); + public CustomLayout() { + setWidth(100, Unit.PERCENTAGE); } /** @@ -305,4 +309,32 @@ public class CustomLayout extends AbstractLayout implements LegacyComponent { } } + @Override + public void readDesign(Element design, DesignContext designContext) { + super.readDesign(design, designContext); + + for (Element child : design.children()) { + + Component childComponent = designContext.readDesign(child); + + if (child.hasAttr(":location")) { + addComponent(childComponent, child.attr(":location")); + } else { + addComponent(childComponent); + } + } + } + + @Override + public void writeDesign(Element design, DesignContext designContext) { + super.writeDesign(design, designContext); + + for (Entry slot : slots.entrySet()) { + Element child = designContext.createElement(slot.getValue()); + if (slots.size() > 1 || !"".equals(slot.getKey())) { + child.attr(":location", slot.getKey()); + } + design.appendChild(child); + } + } } diff --git a/server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutDeclarativeTest.java b/server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutDeclarativeTest.java new file mode 100644 index 0000000000..44261a61dc --- /dev/null +++ b/server/tests/src/com/vaadin/tests/server/component/customlayout/CustomLayoutDeclarativeTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.server.component.customlayout; + +import org.junit.Test; + +import com.vaadin.tests.design.DeclarativeTestBase; +import com.vaadin.ui.Button; +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.Label; + +/** + * Tests declarative support for {@link CustomLayout}. + * + * @since + * @author Vaadin Ltd + */ +public class CustomLayoutDeclarativeTest extends + DeclarativeTestBase { + + @Test + public void testEmpty() { + String design = ""; + CustomLayout expected = new CustomLayout(); + test(design, expected); + } + + @Test + public void testWithChildren() { + String design = "" + // + "" + // + "" + // + ""; + + CustomLayout expected = new CustomLayout(); + expected.addComponent(new Button(), "b"); + expected.addComponent(new Label(), "l"); + + test(design, expected); + } + + @Test + public void testWithOneChild() { + String design = ""; + + CustomLayout expected = new CustomLayout(); + expected.addComponent(new Button()); + + test(design, expected); + } + + @Test + public void testWithTemplate() { + String design = ""; + CustomLayout expected = new CustomLayout("template.html"); + test(design, expected); + } + + @Test + public void testWithDuplicateLocations() { + String design = "" + // + "" + // + "" + // + ""; + + CustomLayout expected = new CustomLayout(); + expected.addComponent(new Button(), "foo"); + expected.addComponent(new Label(), "foo"); + + testRead(design, expected); + + String written = "" + // + "" + // + ""; + + testWrite(written, expected); + } + + protected void test(String design, CustomLayout expected) { + testRead(design, expected); + testWrite(design, expected); + } +} diff --git a/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplate.java b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplate.java new file mode 100644 index 0000000000..de1caf86df --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplate.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.customlayout; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.CustomLayout; +import com.vaadin.ui.Label; + +public class CustomLayoutWithNullTemplate extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + CustomLayout cl = new CustomLayout(); + cl.addComponent(new Label("This Label should be visible."), "foo"); + cl.addComponent(new Button("This Button too."), "bar"); + + addComponent(cl); + } + + @Override + protected String getTestDescription() { + return "Verify that a default-constructed CustomLayout renders child components"; + } + + @Override + protected Integer getTicketNumber() { + return 17210; + } +} diff --git a/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplateTest.java b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplateTest.java new file mode 100644 index 0000000000..668d43f18f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/customlayout/CustomLayoutWithNullTemplateTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.customlayout; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.testbench.ElementQuery; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.CustomLayoutElement; +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class CustomLayoutWithNullTemplateTest extends SingleBrowserTest { + + @Test + public void testChildComponents() { + openTestURL(); + + ElementQuery customLayout = $(CustomLayoutElement.class); + + // Verify the Button and Label are rendered inside the CustomLayout. + assertTrue("Button was not rendered.", + customLayout.$(ButtonElement.class).exists()); + assertTrue("Label was not rendered.", customLayout + .$(LabelElement.class).exists()); + } + +} -- cgit v1.2.3 From f18a9642b7ad5831719b2c15c1b4adb788b386e8 Mon Sep 17 00:00:00 2001 From: Anna Miroshnik Date: Fri, 6 Mar 2015 16:05:09 +0300 Subject: Fix Table column header sorting on Chrome (#14796) This fix is similar to the fix that has been made for other similar cases (i.e. #13381). Couldn't find a reliable way to reproduce the problem. Hopefully this will fix the issue. Was reproduced (before fix) on Google Chrome 40.0.2214.115 m on TableSortingStopsWorkingOnChrome test one time (but then suddenly it started to work again). Was reproduced (before fix) on Project TableSorting once, as described in the ticket. That project has been attached to the ticket. Change-Id: Id901c9ce4a0a7c369572bf4374223851658aa703 --- client/src/com/vaadin/client/ui/VScrollTable.java | 88 +++++++----- .../vaadin/client/ui/dd/VDragAndDropManager.java | 12 +- .../table/TableSortingStopsWorkingOnChrome.java | 150 +++++++++++++++++++++ 3 files changed, 210 insertions(+), 40 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/table/TableSortingStopsWorkingOnChrome.java (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 12de2724fc..13561dcd0f 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -2774,7 +2774,9 @@ public class VScrollTable extends FlowPanel implements HasWidgets, private boolean sortable = false; private final String cid; + private boolean dragging; + private Integer currentDragX = null; // is used to resolve #14796 private int dragStartX; private int colIndex; @@ -3146,6 +3148,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, event.stopPropagation(); } dragging = true; + currentDragX = WidgetUtil.getTouchOrMouseClientX(event); moved = false; colIndex = getColIndexByKey(cid); DOM.setCapture(getElement()); @@ -3160,6 +3163,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (columnReordering && WidgetUtil.isTouchEventOrLeftMouseButton(event)) { dragging = false; + currentDragX = null; DOM.releaseCapture(getElement()); if (WidgetUtil.isTouchEvent(event)) { @@ -3227,47 +3231,57 @@ public class VScrollTable extends FlowPanel implements HasWidgets, break; case Event.ONTOUCHMOVE: case Event.ONMOUSEMOVE: - if (dragging && WidgetUtil.isTouchEventOrLeftMouseButton(event)) { - if (event.getTypeInt() == Event.ONTOUCHMOVE) { - /* - * prevent using this event in e.g. scrolling - */ - event.stopPropagation(); - } - if (!moved) { - createFloatingCopy(); - moved = true; - } + // only start the drag if the mouse / touch has moved a minimum + // distance in x-axis (the same idea as in #13381) + int currentX = WidgetUtil.getTouchOrMouseClientX(event); - final int clientX = WidgetUtil - .getTouchOrMouseClientX(event); - final int x = clientX + tHead.hTableWrapper.getScrollLeft(); - int slotX = headerX; - closestSlot = colIndex; - int closestDistance = -1; - int start = 0; - if (showRowHeaders) { - start++; - } - final int visibleCellCount = tHead.getVisibleCellCount(); - for (int i = start; i <= visibleCellCount; i++) { - if (i > 0) { - final String colKey = getColKeyByIndex(i - 1); - // getColWidth only returns the internal width - // without padding, not the offset width of the - // whole td (#10890) - slotX += getColWidth(colKey) - + scrollBody.getCellExtraWidth(); + if (currentDragX == null + || Math.abs(currentDragX - currentX) > VDragAndDropManager.MINIMUM_DISTANCE_TO_START_DRAG) { + if (dragging + && WidgetUtil.isTouchEventOrLeftMouseButton(event)) { + if (event.getTypeInt() == Event.ONTOUCHMOVE) { + /* + * prevent using this event in e.g. scrolling + */ + event.stopPropagation(); } - final int dist = Math.abs(x - slotX); - if (closestDistance == -1 || dist < closestDistance) { - closestDistance = dist; - closestSlot = i; + if (!moved) { + createFloatingCopy(); + moved = true; } - } - tHead.focusSlot(closestSlot); - updateFloatingCopysPosition(clientX, -1); + final int clientX = WidgetUtil + .getTouchOrMouseClientX(event); + final int x = clientX + + tHead.hTableWrapper.getScrollLeft(); + int slotX = headerX; + closestSlot = colIndex; + int closestDistance = -1; + int start = 0; + if (showRowHeaders) { + start++; + } + final int visibleCellCount = tHead + .getVisibleCellCount(); + for (int i = start; i <= visibleCellCount; i++) { + if (i > 0) { + final String colKey = getColKeyByIndex(i - 1); + // getColWidth only returns the internal width + // without padding, not the offset width of the + // whole td (#10890) + slotX += getColWidth(colKey) + + scrollBody.getCellExtraWidth(); + } + final int dist = Math.abs(x - slotX); + if (closestDistance == -1 || dist < closestDistance) { + closestDistance = dist; + closestSlot = i; + } + } + tHead.focusSlot(closestSlot); + + updateFloatingCopysPosition(clientX, -1); + } } break; default: diff --git a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java index 844f4c1b9c..3a0b52b6af 100644 --- a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java +++ b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java @@ -38,9 +38,9 @@ import com.vaadin.client.ComponentConnector; import com.vaadin.client.MouseEventDetailsBuilder; import com.vaadin.client.Profiler; import com.vaadin.client.UIDL; -import com.vaadin.client.WidgetUtil; import com.vaadin.client.VConsole; import com.vaadin.client.ValueMap; +import com.vaadin.client.WidgetUtil; import com.vaadin.client.ui.VOverlay; import com.vaadin.shared.ApplicationConstants; import com.vaadin.shared.MouseEventDetails; @@ -240,6 +240,12 @@ public class VDragAndDropManager { } + /* + * #13381, #14796. The drag only actually starts when the mouse move or + * touch move event is more than 3 pixel away. + */ + public static final int MINIMUM_DISTANCE_TO_START_DRAG = 3; + private static VDragAndDropManager instance; private HandlerRegistration handlerRegistration; private VDragEvent currentDrag; @@ -425,8 +431,8 @@ public class VDragAndDropManager { int currentY = WidgetUtil .getTouchOrMouseClientY(event .getNativeEvent()); - if (Math.abs(startX - currentX) > 3 - || Math.abs(startY - currentY) > 3) { + if (Math.abs(startX - currentX) > MINIMUM_DISTANCE_TO_START_DRAG + || Math.abs(startY - currentY) > MINIMUM_DISTANCE_TO_START_DRAG) { if (deferredStartRegistration != null) { deferredStartRegistration .removeHandler(); diff --git a/uitest/src/com/vaadin/tests/components/table/TableSortingStopsWorkingOnChrome.java b/uitest/src/com/vaadin/tests/components/table/TableSortingStopsWorkingOnChrome.java new file mode 100644 index 0000000000..23d0581e5a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableSortingStopsWorkingOnChrome.java @@ -0,0 +1,150 @@ +package com.vaadin.tests.components.table; + +import java.io.Serializable; + +import com.vaadin.annotations.Theme; +import com.vaadin.data.util.BeanItemContainer; +import com.vaadin.event.dd.DragAndDropEvent; +import com.vaadin.event.dd.DropHandler; +import com.vaadin.event.dd.acceptcriteria.AcceptAll; +import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.ColumnReorderEvent; +import com.vaadin.ui.Table.ColumnReorderListener; +import com.vaadin.ui.Table.HeaderClickEvent; +import com.vaadin.ui.Table.HeaderClickListener; +import com.vaadin.ui.VerticalLayout; + +@Theme("valo") +@SuppressWarnings("serial") +public class TableSortingStopsWorkingOnChrome extends AbstractTestUI { + + protected static final int ROW_COUNT = 100; + + @Override + protected void setup(VaadinRequest request) { + VerticalLayout layout = new VerticalLayout(); + layout.setSizeFull(); + + final Table table = new Table(); + table.setColumnReorderingAllowed(true); + table.setSizeFull(); + + BeanItemContainer cont = new BeanItemContainer( + TestItem.class); + + for (int i = 0; i < ROW_COUNT; i++) { + TestItem ti = new TestItem(); + ti.setValue1("Value1_" + i); + ti.setValue2("Value2_" + (ROW_COUNT - i)); + ti.setValue3("Value3_" + i); + ti.setValue4("Value4_" + (ROW_COUNT - i)); + ti.setValue5("Value5_" + i); + cont.addBean(ti); + } + + table.setContainerDataSource(cont); + table.setImmediate(true); + table.setSelectable(true); + table.setMultiSelect(false); + + table.setPageLength(10); + table.setDragMode(Table.TableDragMode.ROW); + + table.setDropHandler(new DropHandler() { + @Override + public void drop(DragAndDropEvent dragAndDropEvent) { + + } + + @Override + public AcceptCriterion getAcceptCriterion() { + return AcceptAll.get(); + } + }); + + table.addColumnReorderListener(new ColumnReorderListener() { + + @Override + public void columnReorder(ColumnReorderEvent event) { + System.out.println("columnReorder"); + } + }); + + table.addHeaderClickListener(new HeaderClickListener() { + + @Override + public void headerClick(HeaderClickEvent event) { + System.out.println("Header was clicked"); + } + }); + + layout.addComponent(table); + + addComponent(layout); + } + + public class TestItem implements Serializable { + private static final long serialVersionUID = -745849615488792221L; + + private String value1; + private String value2; + private String value3; + private String value4; + private String value5; + + public String getValue1() { + return value1; + } + + public void setValue1(String value1) { + this.value1 = value1; + } + + public String getValue2() { + return value2; + } + + public void setValue2(String value2) { + this.value2 = value2; + } + + public String getValue3() { + return value3; + } + + public void setValue3(String value3) { + this.value3 = value3; + } + + public String getValue4() { + return value4; + } + + public void setValue4(String value4) { + this.value4 = value4; + } + + public String getValue5() { + return value5; + } + + public void setValue5(String value5) { + this.value5 = value5; + } + + } + + @Override + protected String getTestDescription() { + return "After an indeterminate period of time sorting tables via clicking on the column header should not stop working on Chrome"; + } + + @Override + protected Integer getTicketNumber() { + return 14796; + } + +} -- cgit v1.2.3 From 1c569304b3f10960854c2045030d907408978d05 Mon Sep 17 00:00:00 2001 From: Johannes Tuikkala Date: Thu, 5 Mar 2015 13:32:33 +0200 Subject: Fixed scroll jump by using native focusing in IE (#15294) Change-Id: I412ba219f31567ebba019b7d6ce4db4af9be9363 --- .../TableInIframeRowClickScrollJumpTest.html | 12 ++ .../com/vaadin/client/ui/FocusableScrollPanel.java | 8 ++ .../tests/components/table/TableBlurFocus.java | 153 +++++++++++++++++++++ .../tests/components/table/TableBlurFocusTest.java | 64 +++++++++ .../table/TableInIframeRowClickScrollJumpTest.java | 127 +++++++++++++++++ 5 files changed, 364 insertions(+) create mode 100644 WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html create mode 100644 uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java create mode 100644 uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java create mode 100644 uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java (limited to 'client') diff --git a/WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html b/WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html new file mode 100644 index 0000000000..dfddbdb7e5 --- /dev/null +++ b/WebContent/statictestfiles/TableInIframeRowClickScrollJumpTest.html @@ -0,0 +1,12 @@ + + +IEJumpTest + + + +

test div
+ + + + \ No newline at end of file diff --git a/client/src/com/vaadin/client/ui/FocusableScrollPanel.java b/client/src/com/vaadin/client/ui/FocusableScrollPanel.java index 475c8f8074..9dd9c17675 100644 --- a/client/src/com/vaadin/client/ui/FocusableScrollPanel.java +++ b/client/src/com/vaadin/client/ui/FocusableScrollPanel.java @@ -48,9 +48,11 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements Style style = getElement().getStyle(); style.setProperty("zoom", "1"); style.setPosition(Position.RELATIVE); + browserInfo = BrowserInfo.get(); } private DivElement focusElement; + private BrowserInfo browserInfo; public FocusableScrollPanel(boolean useFakeFocusElement) { this(); @@ -72,6 +74,12 @@ public class FocusableScrollPanel extends SimpleFocusablePanel implements style.setPosition(Position.FIXED); style.setTop(0, Unit.PX); style.setLeft(0, Unit.PX); + if (browserInfo.isIE()) { + // for #15294: artificially hide little bit more the + // focusElement, otherwise IE will make the window to scroll + // into it when focused + style.setLeft(-999, Unit.PX); + } getElement().appendChild(focusElement); /* Sink from focusElemet too as focusa and blur don't bubble */ DOM.sinkEvents(focusElement, Event.FOCUSEVENTS); diff --git a/uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java b/uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java new file mode 100644 index 0000000000..d95b406c1a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableBlurFocus.java @@ -0,0 +1,153 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.table; + +import java.util.Map; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Label; +import com.vaadin.ui.Notification; +import com.vaadin.ui.Table; + +/** + * Tests that previously focused component's blur event happens before any + * variable changes in the focused Table. + * + * @author Vaadin Ltd + */ +public class TableBlurFocus extends AbstractTestUIWithLog { + + enum Columns { + COLUMN1, COLUMN2, COLUMN3, COLUMN4, COLUMN5 + } + + private int count = 0; + private Button focusButton; + + @Override + protected void setup(VaadinRequest request) { + System.out + .println("TableBlurFocus/TableInIframeRowClickScrollJumpTest"); + Button button = new Button("click to focus"); + button.addFocusListener(new FocusListener() { + + @Override + public void focus(FocusEvent event) { + log("focus"); + } + }); + button.addBlurListener(new BlurListener() { + + @Override + public void blur(BlurEvent event) { + log("blur"); + } + }); + final Button scrollButton = new Button( + "focus lowest button to scroll down"); + scrollButton.setId("scroll-button"); + scrollButton.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + focusButton.focus(); + } + }); + + Label spacerLabel = new Label("spacer"); + spacerLabel.setHeight("300px"); + + addComponent(button); + addComponent(scrollButton); + addComponent(createTable()); + addComponent(spacerLabel); + addComponent(focusButton = new Button("for focus")); + focusButton.setId("focus-button"); + focusButton.addFocusListener(new FocusListener() { + @Override + public void focus(FocusEvent event) { + focusButton.setCaption("focused"); + } + }); + } + + private Table createTable() { + Table table = new Table() { + @Override + public void changeVariables(Object source, + Map variables) { + log("variable change"); + super.changeVariables(source, variables); + } + }; + table.setSelectable(true); + table.setImmediate(true); + + table.addContainerProperty(Columns.COLUMN1, String.class, " "); + table.addContainerProperty(Columns.COLUMN2, Label.class, null); + table.addContainerProperty(Columns.COLUMN3, Button.class, null); + table.addContainerProperty(Columns.COLUMN4, String.class, " "); + table.setColumnCollapsingAllowed(true); + table.setColumnCollapsible(Columns.COLUMN4, true); + table.setColumnCollapsed(Columns.COLUMN4, true); + table.setSortEnabled(true); + table.setFooterVisible(true); + table.setPageLength(14); + table.addGeneratedColumn(Columns.COLUMN5, new Table.ColumnGenerator() { + + @Override + public Object generateCell(Table source, Object itemId, + Object columnId) { + return "Generated"; + } + }); + + table.setColumnHeader(Columns.COLUMN1, "Column"); + for (int x = 0; x < 120; x++) { + final Label buttonLabel = new Label("Not clicked"); + Button button = new Button("Click me?", new Button.ClickListener() { + + @Override + public void buttonClick(Button.ClickEvent event) { + ++count; + buttonLabel.setValue("Clicked " + count + " times"); + Notification.show("Clicked!"); + } + }); + table.addItem(new Object[] { "entryString" + x, buttonLabel, + button, " " }, "entryID" + x); + } + return table; + } + + @Override + protected String getTestDescription() { + return "Click button to focus, then click Table header. Blur event should arrive before the next variable change."; + } + + @Override + protected Integer getTicketNumber() { + return 15294; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java b/uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java new file mode 100644 index 0000000000..e5d07abc22 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableBlurFocusTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.table; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TableBlurFocusTest extends MultiBrowserTest { + + @Test + public void testBlurAndFocus() throws InterruptedException { + openTestURL(); + waitForElementPresent(By.className("v-button")); + + assertAnyLogText("1. variable change"); + assertEquals("Unexpected column header,", "COLUMN2", + $(TableElement.class).first().getHeaderCell(1).getCaption()); + assertEquals("Unexpected button caption,", "click to focus", + $(ButtonElement.class).first().getCaption()); + + $(ButtonElement.class).first().click(); + assertAnyLogText("2. focus", "3. focus"); + + $(TableElement.class).first().getHeaderCell(1).click(); + assertAnyLogText("3. blur", "4. blur"); + } + + private void assertAnyLogText(String... texts) { + assertThat(String.format( + "Correct log text was not found, expected any of %s", + Arrays.asList(texts)), logContainsAnyText(texts)); + } + + private boolean logContainsAnyText(String... texts) { + for (String text : texts) { + if (logContainsText(text)) { + return true; + } + } + return false; + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java b/uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java new file mode 100644 index 0000000000..074958d671 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableInIframeRowClickScrollJumpTest.java @@ -0,0 +1,127 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.table; + +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * For testing that UI scroll does not jump back to up when: 1. UI is in iframe + * 2. the window scrolled down 3. and table is clicked + * + * @since + * @author Vaadin Ltd + */ +public class TableInIframeRowClickScrollJumpTest extends MultiBrowserTest { + + private static final String TEST_URL = "statictestfiles/TableInIframeRowClickScrollJumpTest.html"; + + @Test + public void testRowClicking_WhenScrolledDown_shouldMaintainScrollPosition() + throws InterruptedException { + System.out.println(">>>" + getBaseURL() + TEST_URL); + + driver.get(getUrl()); + + // using non-standard way because of iframe + sleep(4000); + + // make sure we are in the "main content" + driver.switchTo().defaultContent(); + sleep(2000); + switchIntoIframe(); + + // using non-standard way because of iframe + waitForElementVisible(By.id("scroll-button")); + + ButtonElement scrollbutton = $(ButtonElement.class).id("scroll-button"); + scrollbutton.click(); + + // using non-standard way because of iframe + sleep(1000); + + Long scrollPosition = getWindowsScrollPosition(); + + assertThat("Scroll position should be greater than 100 (it was " + + scrollPosition + ")", scrollPosition > 100); + + TableElement table = $(TableElement.class).first(); + table.getRow(13).getCell(0).click(); + + // using non-standard way because of iframe + sleep(1000); + + Long scrollPosition2 = getWindowsScrollPosition(); + + assertThat("Scroll position should stay about the same. Old was " + + scrollPosition + " and new one " + scrollPosition2, + Math.abs(scrollPosition - scrollPosition2) < 10); + } + + private String getUrl() { + String url; + // using non-standard way because of iframe + if (getBaseURL().charAt(getBaseURL().length() - 1) == '/') { + url = getBaseURL() + TEST_URL; + } else { + // this one is for gerrit's teamcity :( + url = getBaseURL() + '/' + TEST_URL; + } + return url; + } + + public void switchIntoIframe() { + List frames = driver.findElements(By.tagName("iframe")); + assertThat("No frames was found", frames.size() > 0); + driver.switchTo().frame(frames.get(0)); + } + + private Long getWindowsScrollPosition() { + // measure scroll pos in the main window + driver.switchTo().defaultContent(); + + JavascriptExecutor executor = (JavascriptExecutor) driver; + Long value = (Long) executor + .executeScript("if (window.pageYOffset) return window.pageYOffset;else if (window.document.documentElement.scrollTop) return window.document.documentElement.scrollTop;else return window.document.body.scrollTop;"); + + // back to the iframe + switchIntoIframe(); + + return value; + } + + @Override + // using non-standard way because of iframe + protected void closeApplication() { + if (driver != null) { + try { + driver.get(getUrl() + "?closeApplication"); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} -- cgit v1.2.3 From 140844eaff3de1b926460081405eb7d53ec811f8 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Thu, 19 Mar 2015 09:49:32 +0000 Subject: Revert "Make push path configurable (#14432)." Breaks long polling fallback when implemented this way This reverts commit 735f0748344d7ee594c4e52a715d867dfdb23cb1. Conflicts: push/build.xml push/ivy.xml server/src/com/vaadin/server/Constants.java uitest/src/com/vaadin/tests/push/PushPathTest.java Change-Id: I07f6fedafc648b0ee403865ccb322017d2a8d571 --- WebContent/WEB-INF/web.xml | 22 +------ .../communication/AtmospherePushConnection.java | 15 ++--- server/src/com/vaadin/server/Constants.java | 3 +- .../server/DefaultDeploymentConfiguration.java | 19 ------ .../com/vaadin/server/DeploymentConfiguration.java | 10 +-- .../com/vaadin/server/ServletPortletHelper.java | 3 +- .../vaadin/server/communication/UIInitHandler.java | 5 +- server/src/com/vaadin/ui/PushConfiguration.java | 47 +------------ .../AbstractDeploymentConfigurationTest.java | 4 -- .../tests/util/MockDeploymentConfiguration.java | 6 -- .../com/vaadin/shared/ApplicationConstants.java | 12 ++-- shared/src/com/vaadin/shared/ui/ui/UIState.java | 1 - .../vaadin/launcher/ApplicationRunnerServlet.java | 9 +-- uitest/src/com/vaadin/tests/push/PushPath.java | 77 ---------------------- uitest/src/com/vaadin/tests/push/PushPathTest.java | 39 ----------- 15 files changed, 24 insertions(+), 248 deletions(-) delete mode 100644 uitest/src/com/vaadin/tests/push/PushPath.java delete mode 100644 uitest/src/com/vaadin/tests/push/PushPathTest.java (limited to 'client') diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index c1102f4682..ef60364202 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -87,9 +87,9 @@ - + VaadinApplicationRunnerWithTimeoutRedirect com.vaadin.launcher.ApplicationRunnerServlet @@ -115,17 +115,6 @@ true - - - VaadinApplicationRunnerWithPushPathTest - com.vaadin.launcher.ApplicationRunnerServlet - - pushPath - ws - - true - - Embed App 1 /embed1/* @@ -159,11 +148,6 @@ /run-push/* - - VaadinApplicationRunnerWithPushPathTest - /run-pushpath/* - - IntegrationTest /integration/* diff --git a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java index 787da9bc6f..e544c91d0f 100644 --- a/client/src/com/vaadin/client/communication/AtmospherePushConnection.java +++ b/client/src/com/vaadin/client/communication/AtmospherePushConnection.java @@ -43,7 +43,7 @@ import elemental.json.JsonObject; /** * The default {@link PushConnection} implementation that uses Atmosphere for * handling the communication channel. - * + * * @author Vaadin Ltd * @since 7.1 */ @@ -135,8 +135,6 @@ public class AtmospherePushConnection implements PushConnection { */ private Command pendingDisconnectCommand; - private String pushPath; - public AtmospherePushConnection() { } @@ -183,9 +181,6 @@ public class AtmospherePushConnection implements PushConnection { pushConfiguration.parameters.get(param)); } - pushPath = pushConfiguration.pushPath; - assert pushPath != null; - runWhenAtmosphereLoaded(new Command() { @Override public void execute() { @@ -202,7 +197,7 @@ public class AtmospherePushConnection implements PushConnection { private void connect() { String baseUrl = connection .translateVaadinUri(ApplicationConstants.APP_PROTOCOL_PREFIX - + pushPath + '/'); + + ApplicationConstants.PUSH_PATH + '/'); String extraParams = UIConstants.UI_ID_PARAMETER + "=" + connection.getConfiguration().getUIId(); @@ -277,9 +272,9 @@ public class AtmospherePushConnection implements PushConnection { /** * Called whenever a server push connection is established (or * re-established). - * + * * @param response - * + * * @since 7.2 */ protected void onConnect(AtmosphereResponse response) { @@ -360,7 +355,7 @@ public class AtmospherePushConnection implements PushConnection { /** * Called if the push connection fails. Atmosphere will automatically retry * the connection until successful. - * + * */ protected void onError(AtmosphereResponse response) { state = State.DISCONNECTED; diff --git a/server/src/com/vaadin/server/Constants.java b/server/src/com/vaadin/server/Constants.java index b7c2a1ff3e..f3cdd48d58 100644 --- a/server/src/com/vaadin/server/Constants.java +++ b/server/src/com/vaadin/server/Constants.java @@ -132,12 +132,11 @@ public interface Constants { static final String SERVLET_PARAMETER_RESOURCE_CACHE_TIME = "resourceCacheTime"; static final String SERVLET_PARAMETER_HEARTBEAT_INTERVAL = "heartbeatInterval"; static final String SERVLET_PARAMETER_CLOSE_IDLE_SESSIONS = "closeIdleSessions"; + static final String SERVLET_PARAMETER_PUSH_MODE = "pushMode"; static final String SERVLET_PARAMETER_UI_PROVIDER = "UIProvider"; static final String SERVLET_PARAMETER_LEGACY_PROPERTY_TOSTRING = "legacyPropertyToString"; static final String SERVLET_PARAMETER_SYNC_ID_CHECK = "syncIdCheck"; static final String SERVLET_PARAMETER_SENDURLSASPARAMETERS = "sendUrlsAsParameters"; - static final String SERVLET_PARAMETER_PUSH_MODE = "pushMode"; - static final String SERVLET_PARAMETER_PUSH_PATH = "pushPath"; // Configurable parameter names static final String PARAMETER_VAADIN_RESOURCES = "Resources"; diff --git a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java index 5402979be8..b26e048431 100644 --- a/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DefaultDeploymentConfiguration.java @@ -61,13 +61,6 @@ public class DefaultDeploymentConfiguration extends public static final boolean DEFAULT_SEND_URLS_AS_PARAMETERS = true; - /** - * Default value for {@link #getPushPath()} = {@value} . - * - * @since 7.4.1 - */ - public static final String DEFAULT_PUSH_PATH = "PUSH"; - private final Properties initParameters; private boolean productionMode; private boolean xsrfProtectionEnabled; @@ -291,18 +284,6 @@ public class DefaultDeploymentConfiguration extends return initParameters; } - /** - * {@inheritDoc} - *

- * The default path {@link DEFAULT_PUSH_PATH} can be changed by using init - * parameter {@link Constants.SERVLET_PARAMETER_PUSH_PATH}. - */ - @Override - public String getPushPath() { - return getApplicationOrSystemProperty( - Constants.SERVLET_PARAMETER_PUSH_PATH, DEFAULT_PUSH_PATH); - } - /** * Log a warning if Vaadin is not running in production mode. */ diff --git a/server/src/com/vaadin/server/DeploymentConfiguration.java b/server/src/com/vaadin/server/DeploymentConfiguration.java index 06556e28a7..968ec7c0c3 100644 --- a/server/src/com/vaadin/server/DeploymentConfiguration.java +++ b/server/src/com/vaadin/server/DeploymentConfiguration.java @@ -195,7 +195,7 @@ public interface DeploymentConfiguration extends Serializable { * * @since 7.4 * - * @return the name of the widgetset + * @return UI class name */ public String getWidgetset(String defaultValue); @@ -213,14 +213,6 @@ public interface DeploymentConfiguration extends Serializable { */ public String getClassLoaderName(); - /** - * Returns the push path configuration option value. Should never be null. - * - * @since 7.4.1 - * @return the path used with server push - */ - public String getPushPath(); - /** * Returns to legacy Property.toString() mode used. See * {@link AbstractProperty#isLegacyToStringEnabled()} for more information. diff --git a/server/src/com/vaadin/server/ServletPortletHelper.java b/server/src/com/vaadin/server/ServletPortletHelper.java index 1f0c7f02b9..197d9fe416 100644 --- a/server/src/com/vaadin/server/ServletPortletHelper.java +++ b/server/src/com/vaadin/server/ServletPortletHelper.java @@ -124,8 +124,7 @@ public class ServletPortletHelper implements Serializable { } public static boolean isPushRequest(VaadinRequest request) { - return hasPathPrefix(request, request.getService() - .getDeploymentConfiguration().getPushPath() + '/'); + return hasPathPrefix(request, ApplicationConstants.PUSH_PATH + '/'); } public static void initDefaultUIProvider(VaadinSession session, diff --git a/server/src/com/vaadin/server/communication/UIInitHandler.java b/server/src/com/vaadin/server/communication/UIInitHandler.java index 02b4e64159..3a6dc1e55f 100644 --- a/server/src/com/vaadin/server/communication/UIInitHandler.java +++ b/server/src/com/vaadin/server/communication/UIInitHandler.java @@ -198,11 +198,10 @@ public abstract class UIInitHandler extends SynchronizedRequestHandler { PushMode pushMode = provider.getPushMode(event); if (pushMode == null) { - pushMode = session.getConfiguration().getPushMode(); + pushMode = session.getService().getDeploymentConfiguration() + .getPushMode(); } ui.getPushConfiguration().setPushMode(pushMode); - ui.getPushConfiguration().setPushPath( - session.getConfiguration().getPushPath()); Transport transport = provider.getPushTransport(event); if (transport != null) { diff --git a/server/src/com/vaadin/ui/PushConfiguration.java b/server/src/com/vaadin/ui/PushConfiguration.java index d5e89b4b14..90ad28542c 100644 --- a/server/src/com/vaadin/ui/PushConfiguration.java +++ b/server/src/com/vaadin/ui/PushConfiguration.java @@ -104,26 +104,6 @@ public interface PushConfiguration extends Serializable { */ public void setFallbackTransport(Transport fallbackTransport); - /** - * Sets the path that is used with push. - * - * @since 7.4.1 - * @param pushPath - * The path to be used with push - * - * @throws IllegalArgumentException - * if the argument is null or empty. - */ - public void setPushPath(String pushPath); - - /** - * Returns the path used with push. - * - * @since 7.4.1 - * @return The path that is used with push - */ - public String getPushPath(); - /** * Returns the given parameter, if set. *

@@ -275,32 +255,6 @@ class PushConfigurationImpl implements PushConfiguration { fallbackTransport.getIdentifier()); } - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.PushConfiguration#setPushPath(java.lang.String) - */ - @Override - public void setPushPath(String pushPath) { - if (pushPath != null && !pushPath.isEmpty()) { - getState().pushPath = pushPath; - } else { - throw new IllegalArgumentException( - "Push path can't be empty or null"); - } - - } - - /* - * (non-Javadoc) - * - * @see com.vaadin.ui.PushConfiguration#getPushPath() - */ - @Override - public String getPushPath() { - return getState(false).pushPath; - } - /* * (non-Javadoc) * @@ -336,4 +290,5 @@ class PushConfigurationImpl implements PushConfiguration { return Collections.unmodifiableCollection(getState(false).parameters .keySet()); } + } diff --git a/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java b/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java index ccdbfea150..0518bea650 100644 --- a/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java +++ b/server/tests/src/com/vaadin/server/AbstractDeploymentConfigurationTest.java @@ -158,9 +158,5 @@ public class AbstractDeploymentConfigurationTest { return DefaultDeploymentConfiguration.DEFAULT_SEND_URLS_AS_PARAMETERS; } - @Override - public String getPushPath() { - return null; - } } } diff --git a/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java b/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java index 175dcb2b94..ddee23a9ec 100644 --- a/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java +++ b/server/tests/src/com/vaadin/tests/util/MockDeploymentConfiguration.java @@ -22,7 +22,6 @@ public class MockDeploymentConfiguration extends private LegacyProperyToStringMode legacyPropertyToStringMode = LegacyProperyToStringMode.DISABLED; private boolean syncIdCheckEnabled = true; private boolean sendUrlsAsParameters = true; - private String pushPath = "PUSH"; @Override public boolean isProductionMode() { @@ -126,9 +125,4 @@ public class MockDeploymentConfiguration extends return sendUrlsAsParameters; } - @Override - public String getPushPath() { - return pushPath; - } - } diff --git a/shared/src/com/vaadin/shared/ApplicationConstants.java b/shared/src/com/vaadin/shared/ApplicationConstants.java index 990564a6b8..d7aaee6267 100644 --- a/shared/src/com/vaadin/shared/ApplicationConstants.java +++ b/shared/src/com/vaadin/shared/ApplicationConstants.java @@ -28,6 +28,8 @@ public class ApplicationConstants implements Serializable { public static final String HEARTBEAT_PATH = "HEARTBEAT"; + public static final String PUSH_PATH = "PUSH"; + public static final String PUBLISHED_FILE_PATH = APP_PATH + '/' + "PUBLISHED"; @@ -74,7 +76,7 @@ public class ApplicationConstants implements Serializable { /** * The name of the javascript containing the bootstrap code. The file is * located in the VAADIN directory. - * + * * @since 7.3 */ public static final String VAADIN_BOOTSTRAP_JS = "vaadinBootstrap.js"; @@ -88,7 +90,7 @@ public class ApplicationConstants implements Serializable { /** * The name of the debug version of the javascript containing push support. * The file is located in the VAADIN directory. - * + * * @since 7.1.6 */ public static final String VAADIN_PUSH_DEBUG_JS = "vaadinPush.debug.js"; @@ -100,14 +102,14 @@ public class ApplicationConstants implements Serializable { /** * The name of the parameter used to transmit RPC invocations - * + * * @since 7.2 */ public static final String RPC_INVOCATIONS = "rpc"; /** * The name of the parameter used to transmit the CSRF token - * + * * @since 7.2 */ public static final String CSRF_TOKEN = "csrfToken"; @@ -116,7 +118,7 @@ public class ApplicationConstants implements Serializable { * The name of the parameter used to transmit the sync id. The value can be * set to -1 e.g. when testing with pre-recorded requests to make the * framework ignore the sync id. - * + * * @see com.vaadin.ui.ConnectorTracker#getCurrentSyncId() * @since 7.2 */ diff --git a/shared/src/com/vaadin/shared/ui/ui/UIState.java b/shared/src/com/vaadin/shared/ui/ui/UIState.java index 04e182c5d4..2f51fef6ee 100644 --- a/shared/src/com/vaadin/shared/ui/ui/UIState.java +++ b/shared/src/com/vaadin/shared/ui/ui/UIState.java @@ -110,7 +110,6 @@ public class UIState extends TabIndexState { public static final String FALLBACK_TRANSPORT_PARAM = "fallbackTransport"; public PushMode mode = PushMode.DISABLED; - public String pushPath; public Map parameters = new HashMap(); { parameters diff --git a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java index 5c2e58d3a2..e2b93ab7d2 100644 --- a/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java +++ b/uitest/src/com/vaadin/launcher/ApplicationRunnerServlet.java @@ -402,12 +402,9 @@ public class ApplicationRunnerServlet extends LegacyVaadinServlet { try { VaadinServletService service = (VaadinServletService) VaadinService .getCurrent(); - if (service != null) { - session = service - .findVaadinSession(new VaadinServletRequest( - currentRequest, service)); - } - + session = service + .findVaadinSession(new VaadinServletRequest( + currentRequest, service)); } finally { /* * Clear some state set by findVaadinSession to diff --git a/uitest/src/com/vaadin/tests/push/PushPath.java b/uitest/src/com/vaadin/tests/push/PushPath.java deleted file mode 100644 index 20771bd84f..0000000000 --- a/uitest/src/com/vaadin/tests/push/PushPath.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2000-2014 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.tests.push; - -import com.vaadin.annotations.Push; -import com.vaadin.server.VaadinRequest; -import com.vaadin.shared.ui.ui.Transport; -import com.vaadin.tests.components.AbstractTestUI; -import com.vaadin.ui.Label; - -@Push(transport = Transport.WEBSOCKET) -public class PushPath extends AbstractTestUI { - - public static final String PUSH_PATH_LABEL_ID = "push-path-label-id"; - public static final String PUSH_PATH_LABEL_TEXT = "Label by push"; - - @Override - protected void setup(VaadinRequest request) { - // use only websockets - getPushConfiguration().setFallbackTransport(Transport.WEBSOCKET); - - String pushPath = request.getService().getDeploymentConfiguration() - .getPushPath(); - String transport = getPushConfiguration().getTransport().name(); - Label pushPathLabel = new Label(String.format( - "Waiting for push from path '%s' using %s in 3 seconds.", - pushPath, transport)); - addComponent(pushPathLabel); - - new PushThread().start(); - } - - public class PushThread extends Thread { - - @Override - public void run() { - try { - Thread.sleep(3000); - } catch (InterruptedException e) { - } - access(new Runnable() { - - @Override - public void run() { - Label pushLabel = new Label(PUSH_PATH_LABEL_TEXT); - pushLabel.setId(PUSH_PATH_LABEL_ID); - addComponent(pushLabel); - } - }); - - } - } - - @Override - public Integer getTicketNumber() { - return 14432; - } - - @Override - public String getDescription() { - return "Push path should be configurable since some servers can't serve both websockets and long polling from same URL."; - } - -} diff --git a/uitest/src/com/vaadin/tests/push/PushPathTest.java b/uitest/src/com/vaadin/tests/push/PushPathTest.java deleted file mode 100644 index 0af9c8d3a7..0000000000 --- a/uitest/src/com/vaadin/tests/push/PushPathTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2000-2014 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ -package com.vaadin.tests.push; - -import org.junit.Assert; -import org.junit.Test; - -import com.vaadin.tests.tb3.WebsocketTest; - -public class PushPathTest extends WebsocketTest { - - private static final int TEN_SECONDS_IN_MS = 10 * 1000; - - @Test - public void testCustomPushPath() throws InterruptedException { - openTestURL(); - sleep(TEN_SECONDS_IN_MS); - Assert.assertEquals(vaadinElementById(PushPath.PUSH_PATH_LABEL_ID) - .getText(), PushPath.PUSH_PATH_LABEL_TEXT); - } - - @Override - protected String getDeploymentPath(Class uiClass) { - return "/run-pushpath/" + uiClass.getCanonicalName(); - } -} -- cgit v1.2.3 From f665aed236f64da849862d4e463d80deecc33d9a Mon Sep 17 00:00:00 2001 From: Alexey Fansky Date: Mon, 23 Mar 2015 11:55:55 -0700 Subject: Disables selection when Grid's editor is open (#17132). Change-Id: Ibbbffbfe2e8bcb763031ac277c2c36ce4eb4e3fc --- .../grid/selection/MultiSelectionRenderer.java | 1 + client/src/com/vaadin/client/widgets/Grid.java | 13 +++++ .../components/grid/GridEditorMultiselect.java | 35 ++++++++++++++ .../components/grid/GridEditorMultiselectTest.java | 55 ++++++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselect.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselectTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java b/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java index 5024c8bffa..ddbf690970 100644 --- a/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java +++ b/client/src/com/vaadin/client/widget/grid/selection/MultiSelectionRenderer.java @@ -569,6 +569,7 @@ public class MultiSelectionRenderer extends ComplexRenderer { InputElement checkbox = InputElement.as(cell.getElement() .getFirstChildElement()); checkbox.setChecked(data.booleanValue()); + checkbox.setDisabled(grid.isEditorActive()); checkbox.setPropertyInt(LOGICAL_ROW_PROPERTY_INT, cell.getRowIndex()); } diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index f4a5b0961c..d9845bcdc8 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -1157,6 +1157,7 @@ public class Grid extends ResizeComposite implements + "Grid editor"); grid.getEscalator().setScrollLocked(Direction.VERTICAL, false); + updateSelectionCheckboxesAsNeeded(true); } } }; @@ -1256,6 +1257,16 @@ public class Grid extends ResizeComposite implements null); handler.cancel(request); state = State.INACTIVE; + updateSelectionCheckboxesAsNeeded(true); + } + + private void updateSelectionCheckboxesAsNeeded(boolean isEnabled) { + if (grid.getSelectionModel() instanceof Multi) { + grid.refreshBody(); + CheckBox checkBox = (CheckBox) grid.getDefaultHeaderRow() + .getCell(grid.selectionColumn).getWidget(); + checkBox.setEnabled(isEnabled); + } } /** @@ -1282,6 +1293,7 @@ public class Grid extends ResizeComposite implements EditorRequest request = new EditorRequestImpl(grid, rowIndex, saveRequestCallback); handler.save(request); + updateSelectionCheckboxesAsNeeded(true); } /** @@ -1346,6 +1358,7 @@ public class Grid extends ResizeComposite implements rowIndex, bindRequestCallback); handler.bind(request); grid.getEscalator().setScrollLocked(Direction.VERTICAL, true); + updateSelectionCheckboxesAsNeeded(false); } } diff --git a/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselect.java b/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselect.java new file mode 100644 index 0000000000..b80a9d1153 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselect.java @@ -0,0 +1,35 @@ +package com.vaadin.tests.components.grid; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Grid; + +public class GridEditorMultiselect extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + Grid grid = new Grid(); + + grid.addColumn("name"); + grid.addColumn("age", Integer.class); + + for (int i = 0; i < 30; i++) { + grid.addRow("name " + i, i); + } + + grid.setEditorEnabled(true); + grid.setSelectionMode(Grid.SelectionMode.MULTI); + + addComponent(grid); + } + + @Override + protected Integer getTicketNumber() { + return 17132; + } + + @Override + public String getDescription() { + return "Grid Multiselect: Edit mode allows invalid selection"; + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselectTest.java b/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselectTest.java new file mode 100644 index 0000000000..ba689fb5e1 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridEditorMultiselectTest.java @@ -0,0 +1,55 @@ +package com.vaadin.tests.components.grid; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.GridElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class GridEditorMultiselectTest extends MultiBrowserTest { + + @Test + public void testSelectCheckboxesDisabled() { + openTestURL(); + GridElement grid = openEditor(); + assertCheckboxesEnabled(grid, false); + } + + @Test + public void testSelectCheckboxesEnabledBackOnSave() { + openTestURL(); + GridElement grid = openEditor(); + grid.getEditor().save(); + assertCheckboxesEnabled(grid, true); + } + + @Test + public void testSelectCheckboxesEnabledBackOnCancel() { + openTestURL(); + GridElement grid = openEditor(); + grid.getEditor().cancel(); + assertCheckboxesEnabled(grid, true); + } + + private GridElement openEditor() { + GridElement grid = $(GridElement.class).first(); + grid.getRow(0).doubleClick(); + Assert.assertTrue("Grid editor should be displayed.", grid.getEditor() + .isDisplayed()); + return grid; + } + + private void assertCheckboxesEnabled(GridElement grid, boolean isEnabled) { + List checkboxes = grid.findElements(By + .xpath("//input[@type='checkbox']")); + for (WebElement checkbox : checkboxes) { + Assert.assertEquals("Select checkboxes should be " + + (isEnabled ? "enabled" : "disabled"), isEnabled, + checkbox.isEnabled()); + } + } +} -- cgit v1.2.3 From f7f581d57a8bfa42428c0751454aa8dccb00ec49 Mon Sep 17 00:00:00 2001 From: Juho Nurminen Date: Thu, 26 Mar 2015 10:23:14 +0200 Subject: Use native scrolling in IE on touch devices (#14864) Change-Id: I8c652944b917d6392e2d02052b00ddb119ec242c --- client/src/com/vaadin/client/BrowserInfo.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'client') diff --git a/client/src/com/vaadin/client/BrowserInfo.java b/client/src/com/vaadin/client/BrowserInfo.java index 5ca79cb121..3bc75a9a9b 100644 --- a/client/src/com/vaadin/client/BrowserInfo.java +++ b/client/src/com/vaadin/client/BrowserInfo.java @@ -411,6 +411,11 @@ public class BrowserInfo { if (isIOS() && isWebkit() && getOperatingSystemMajorVersion() >= 6) { return false; } + + if (isIE()) { + return false; + } + return true; } -- cgit v1.2.3 From aaae44fe637a5416a25655510379bb215c9de7b5 Mon Sep 17 00:00:00 2001 From: Patrik Lindström Date: Tue, 24 Mar 2015 12:58:25 +0200 Subject: Make Grid update column renderers (#16552) Change-Id: I3adf9d0cc32f800a535a82ffe5d6ba503a36e746 --- .../vaadin/client/connectors/GridConnector.java | 32 +++---- client/src/com/vaadin/client/widgets/Grid.java | 10 +- .../tests/components/grid/GridSwitchRenderers.java | 103 +++++++++++++++++++++ .../components/grid/GridSwitchRenderersTest.java | 84 +++++++++++++++++ 4 files changed, 209 insertions(+), 20 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderers.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderersTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java index 55f07ecf85..5e9dfc6101 100644 --- a/client/src/com/vaadin/client/connectors/GridConnector.java +++ b/client/src/com/vaadin/client/connectors/GridConnector.java @@ -165,6 +165,18 @@ public class GridConnector extends AbstractHasComponentsConnector implements this.id = id; } + /** + * Sets a new renderer for this column object + * + * @param rendererConnector + * a renderer connector object + */ + public void setRenderer( + AbstractRendererConnector rendererConnector) { + setRenderer(rendererConnector.getRenderer()); + this.rendererConnector = rendererConnector; + } + @Override public Object getValue(final JsonObject obj) { final JsonObject rowData = obj.getObject(GridState.JSONKEY_DATA); @@ -178,16 +190,6 @@ public class GridConnector extends AbstractHasComponentsConnector implements return null; } - /* - * Only used to check that the renderer connector will not change during - * the column lifetime. - * - * TODO remove once support for changing renderers is implemented - */ - private AbstractRendererConnector getRendererConnector() { - return rendererConnector; - } - private AbstractFieldConnector getEditorConnector() { return editorConnector; } @@ -730,13 +732,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements */ private void updateColumnFromStateChangeEvent(GridColumnState columnState) { CustomGridColumn column = columnIdToColumn.get(columnState.id); - updateColumnFromState(column, columnState); - - if (columnState.rendererConnector != column.getRendererConnector()) { - throw new UnsupportedOperationException( - "Changing column renderer after initialization is currently unsupported"); - } } /** @@ -780,6 +776,7 @@ public class GridConnector extends AbstractHasComponentsConnector implements * @param state * The state to get the data from */ + @SuppressWarnings("unchecked") private static void updateColumnFromState(CustomGridColumn column, GridColumnState state) { column.setWidth(state.width); @@ -787,6 +784,9 @@ public class GridConnector extends AbstractHasComponentsConnector implements column.setMaximumWidth(state.maxWidth); column.setExpandRatio(state.expandRatio); + assert state.rendererConnector instanceof AbstractRendererConnector : "GridColumnState.rendererConnector is invalid (not subclass of AbstractRendererConnector)"; + column.setRenderer((AbstractRendererConnector) state.rendererConnector); + column.setSortable(state.sortable); column.setEditable(state.editable); column.setEditorConnector((AbstractFieldConnector) state.editorConnector); diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index d9845bcdc8..31cf4ec866 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -3115,12 +3115,14 @@ public class Grid extends ResizeComposite implements if (renderer == null) { throw new IllegalArgumentException("Renderer cannot be null."); } - bodyRenderer = renderer; - if (grid != null) { - grid.refreshBody(); - } + if (renderer != bodyRenderer) { + bodyRenderer = renderer; + if (grid != null) { + grid.refreshBody(); + } + } return this; } diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderers.java b/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderers.java new file mode 100644 index 0000000000..e233edc5d0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderers.java @@ -0,0 +1,103 @@ +package com.vaadin.tests.components.grid; + +import java.util.List; +import java.util.Random; + +import com.vaadin.annotations.Theme; +import com.vaadin.data.Item; +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUIWithLog; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Grid.Column; +import com.vaadin.ui.Grid.SelectionMode; +import com.vaadin.ui.renderers.HtmlRenderer; +import com.vaadin.ui.renderers.TextRenderer; + +@SuppressWarnings("serial") +@Theme("valo") +public class GridSwitchRenderers extends AbstractTestUIWithLog { + private static final int MANUALLY_FORMATTED_COLUMNS = 1; + private static final int COLUMNS = 3; + private static final int ROWS = 1000; + private static final String EXPANSION_COLUMN_ID = "Column 0"; + + private IndexedContainer ds; + + @Override + protected void setup(VaadinRequest request) { + ds = new IndexedContainer() { + @Override + public List getItemIds(int startIndex, int numberOfIds) { + log("Requested items " + startIndex + " - " + + (startIndex + numberOfIds)); + return super.getItemIds(startIndex, numberOfIds); + } + }; + + { + ds.addContainerProperty(EXPANSION_COLUMN_ID, String.class, ""); + + int col = MANUALLY_FORMATTED_COLUMNS; + for (; col < COLUMNS; col++) { + ds.addContainerProperty(getColumnProperty(col), String.class, + ""); + } + } + + Random rand = new Random(); + rand.setSeed(13334); + for (int row = 0; row < ROWS; row++) { + Item item = ds.addItem(Integer.valueOf(row)); + fillRow("" + row, item); + item.getItemProperty(getColumnProperty(1)).setReadOnly(true); + } + + final Grid grid = new Grid(ds); + grid.setWidth("100%"); + + grid.getColumn(EXPANSION_COLUMN_ID).setWidth(50); + for (int col = MANUALLY_FORMATTED_COLUMNS; col < COLUMNS; col++) { + grid.getColumn(getColumnProperty(col)).setWidth(300); + grid.getColumn(getColumnProperty(col)).setRenderer( + new TextRenderer()); + } + + grid.setSelectionMode(SelectionMode.NONE); + addComponent(grid); + + final CheckBox changeRenderer = new CheckBox( + "SetHtmlRenderer for Column 2", false); + changeRenderer.addValueChangeListener(new ValueChangeListener() { + @Override + public void valueChange(ValueChangeEvent event) { + Column column = grid.getColumn(getColumnProperty(1)); + if (changeRenderer.getValue()) { + column.setRenderer(new HtmlRenderer()); + } else { + column.setRenderer(new TextRenderer()); + } + grid.markAsDirty(); + } + }); + addComponent(changeRenderer); + } + + @SuppressWarnings("unchecked") + private void fillRow(String content, Item item) { + int col = MANUALLY_FORMATTED_COLUMNS; + + for (; col < COLUMNS; col++) { + item.getItemProperty(getColumnProperty(col)).setValue( + "(" + content + ", " + col + ")"); + } + } + + private static String getColumnProperty(int c) { + return "Column " + c; + } + +} \ No newline at end of file diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderersTest.java b/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderersTest.java new file mode 100644 index 0000000000..e3bab865c0 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridSwitchRenderersTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.grid; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.testbench.elements.CheckBoxElement; +import com.vaadin.testbench.elements.GridElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class GridSwitchRenderersTest extends MultiBrowserTest { + + @Test + public void testRendererSwitch() { + + // The UI should start with TEXT rendering in the second column + // Clicking the checkbox will toggle rendering to HTML mode + // Clicking it again should return TEXT rendering mode. + + openTestURL(); + + GridElement grid = $(GridElement.class).first(); + + Assert.assertTrue( + "Initial rendering of column 1 is not unformatted text", + cellTextIsUnformatted(grid.getCell(0, 1).getText())); + + // NOTE: must click at 5,5 because of Valo and rendering in Chrome + // This is a TestBench bug that may be fixed sometime in the future + CheckBoxElement cb = $(CheckBoxElement.class).first(); + cb.click(5, 5); + + Assert.assertTrue( + "Column 1 data has not been rendered with HTMLRenderer after renderer swap", + cellTextIsHTMLFormatted(grid.getCell(0, 1).getText())); + cb.click(5, 5); + + Assert.assertTrue( + "Column 1 data has not been re-rendered as text after renderer swap", + cellTextIsUnformatted(grid.getCell(0, 1).getText())); + } + + /** + * Attempts to match a string to a string like {@code (4, 1)}. + * + * @param cellText + * input string + * @return true if input string is formatted like a raw HTML string + */ + private boolean cellTextIsUnformatted(String cellText) { + String regex = "\\(\\d+, \\d+\\)"; + return cellText.matches(regex); + } + + /** + * Attempts to match a string to a string like {@code (4, 1)}, i.e. the HTML + * formatted version of the above (the bold tags should be consumed by the + * renderer). + * + * @param cellText + * input string + * @return true if input string is formatted like plain text (i.e. HTML bits + * have been consumed by renderer) + */ + private boolean cellTextIsHTMLFormatted(String cellText) { + String regex = "\\(\\d+, \\d+\\)"; + return cellText.matches(regex); + } + +} -- cgit v1.2.3 From 6986117ced043eb01039dc61efe2d222c76981ce Mon Sep 17 00:00:00 2001 From: Denis Anisimov Date: Thu, 26 Mar 2015 19:56:07 +0200 Subject: Reset index of selected item when it's removed (#17248). Change-Id: Id38f48d84e9f55334af2e44b2dc49b1a3c7ef390 --- client/src/com/vaadin/client/ui/VAccordion.java | 5 +- .../accordion/AccordionRemoveComponent.java | 55 ++++++++++++++++++++++ .../accordion/AccordionRemoveComponentTest.java | 43 +++++++++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponent.java create mode 100644 uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponentTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/VAccordion.java b/client/src/com/vaadin/client/ui/VAccordion.java index 06eaecaf70..fc328dd56a 100644 --- a/client/src/com/vaadin/client/ui/VAccordion.java +++ b/client/src/com/vaadin/client/ui/VAccordion.java @@ -29,8 +29,8 @@ import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.ComplexPanel; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ComponentConnector; -import com.vaadin.client.WidgetUtil; import com.vaadin.client.VCaption; +import com.vaadin.client.WidgetUtil; import com.vaadin.client.ui.TouchScrollDelegate.TouchScrollHandler; import com.vaadin.shared.ComponentConstants; import com.vaadin.shared.ui.accordion.AccordionState; @@ -417,6 +417,9 @@ public class VAccordion extends VTabsheetBase { public void removeTab(int index) { StackItem item = getStackItem(index); remove(item); + if (selectedItemIndex == index) { + selectedItemIndex = -1; + } touchScrollHandler.removeElement(item.getContainerElement()); } diff --git a/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponent.java b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponent.java new file mode 100644 index 0000000000..80e0929f8d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponent.java @@ -0,0 +1,55 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.accordion; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Accordion; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; + +/** + * Test for removing component from Accordion. + * + * @author Vaadin Ltd + */ +public class AccordionRemoveComponent extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + final Accordion accordion = new Accordion(); + Button button = new Button("remove"); + button.addClickListener(new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + accordion.removeComponent(event.getButton()); + } + }); + accordion.addComponent(button); + addComponent(accordion); + } + + @Override + protected String getTestDescription() { + return "Reset selected index when tab is removed"; + } + + @Override + protected Integer getTicketNumber() { + return 17248; + } +} diff --git a/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponentTest.java b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponentTest.java new file mode 100644 index 0000000000..84f1734897 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/accordion/AccordionRemoveComponentTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.accordion; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test for removing component from Accordion + * + * @author Vaadin Ltd + */ +public class AccordionRemoveComponentTest extends MultiBrowserTest { + + @Test + public void removeComponent_noClientSideException() { + setDebug(true); + openTestURL(); + + $(ButtonElement.class).first().click(); + + Assert.assertFalse( + "Error notification with client side exception is shown", + isElementPresent(By.className("v-Notification-error"))); + } +} -- cgit v1.2.3 From 722072bb53f0699bc337446048db2beade0df421 Mon Sep 17 00:00:00 2001 From: Maciej Przepióra Date: Mon, 16 Mar 2015 15:44:43 +0100 Subject: Do proper cleanup in VDragAndDropManager.endDrag(boolean) (#17163) Change-Id: I5f9462923fce9f033bc89b791d68607a1e0fc5c7 --- .../vaadin/client/ui/dd/VDragAndDropManager.java | 35 +++--- uitest/src/com/vaadin/tests/dd/DDInterrupt.java | 87 ++++++++++++++ .../src/com/vaadin/tests/dd/DDInterruptTest.java | 97 ++++++++++++++++ uitest/src/com/vaadin/tests/dd/SpacebarPanner.java | 20 ++++ .../client/dd/SpacebarPannerConnector.java | 125 +++++++++++++++++++++ 5 files changed, 349 insertions(+), 15 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/dd/DDInterrupt.java create mode 100644 uitest/src/com/vaadin/tests/dd/DDInterruptTest.java create mode 100644 uitest/src/com/vaadin/tests/dd/SpacebarPanner.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/client/dd/SpacebarPannerConnector.java (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java index 3a0b52b6af..47f8eb1b66 100644 --- a/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java +++ b/client/src/com/vaadin/client/ui/dd/VDragAndDropManager.java @@ -433,23 +433,14 @@ public class VDragAndDropManager { .getNativeEvent()); if (Math.abs(startX - currentX) > MINIMUM_DISTANCE_TO_START_DRAG || Math.abs(startY - currentY) > MINIMUM_DISTANCE_TO_START_DRAG) { - if (deferredStartRegistration != null) { - deferredStartRegistration - .removeHandler(); - deferredStartRegistration = null; - } + ensureDeferredRegistrationCleanup(); currentDrag.setCurrentGwtEvent(event .getNativeEvent()); startDrag.execute(); } break; default: - // on any other events, clean up the - // deferred drag start - if (deferredStartRegistration != null) { - deferredStartRegistration.removeHandler(); - deferredStartRegistration = null; - } + ensureDeferredRegistrationCleanup(); currentDrag = null; clearDragElement(); break; @@ -540,10 +531,10 @@ public class VDragAndDropManager { } private void endDrag(boolean doDrop) { - if (handlerRegistration != null) { - handlerRegistration.removeHandler(); - handlerRegistration = null; - } + + ensureDeferredRegistrationCleanup(); + ensureHandlerRegistrationCleanup(); + boolean sendTransferableToServer = false; if (currentDropHandler != null) { if (doDrop) { @@ -601,6 +592,20 @@ public class VDragAndDropManager { } + private void ensureHandlerRegistrationCleanup() { + if (handlerRegistration != null) { + handlerRegistration.removeHandler(); + handlerRegistration = null; + } + } + + private void ensureDeferredRegistrationCleanup() { + if (deferredStartRegistration != null) { + deferredStartRegistration.removeHandler(); + deferredStartRegistration = null; + } + } + private void removeActiveDragSourceStyleName(ComponentConnector dragSource) { dragSource.getWidget().removeStyleName(ACTIVE_DRAG_SOURCE_STYLENAME); } diff --git a/uitest/src/com/vaadin/tests/dd/DDInterrupt.java b/uitest/src/com/vaadin/tests/dd/DDInterrupt.java new file mode 100644 index 0000000000..1939bbbce5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/dd/DDInterrupt.java @@ -0,0 +1,87 @@ +package com.vaadin.tests.dd; + +import com.vaadin.annotations.Widgetset; +import com.vaadin.event.dd.DragAndDropEvent; +import com.vaadin.event.dd.DropHandler; +import com.vaadin.event.dd.TargetDetailsImpl; +import com.vaadin.event.dd.acceptcriteria.AcceptAll; +import com.vaadin.event.dd.acceptcriteria.AcceptCriterion; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.DragAndDropWrapper; +import com.vaadin.ui.DragAndDropWrapper.DragStartMode; +import com.vaadin.ui.Label; + +/** + * Test for interrupting drag-and-drop. + * + * @author Vaadin Ltd + */ +@Widgetset(TestingWidgetSet.NAME) +public class DDInterrupt extends AbstractTestUI { + + private SpacebarPanner sp; + + @Override + protected void setup(VaadinRequest vaadinRequest) { + final CssLayout layout = new CssLayout(); + layout.setWidth("500px"); + layout.setHeight("500px"); + + addButton("Click to interrupt next drag.", new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + sp.interruptNext(); + } + }); + + final Label draggableLabel = new Label("Drag me"); + draggableLabel.setId("draggable"); + + DragAndDropWrapper dndLayoutWrapper = new DragAndDropWrapper(layout); + addComponent(dndLayoutWrapper); + + DragAndDropWrapper labelWrapper = new DragAndDropWrapper(draggableLabel); + draggableLabel.setSizeUndefined(); + labelWrapper.setDragStartMode(DragStartMode.COMPONENT); + labelWrapper.setSizeUndefined(); + + layout.addComponent(labelWrapper); + + dndLayoutWrapper.setDropHandler(new DropHandler() { + + @Override + public AcceptCriterion getAcceptCriterion() { + return AcceptAll.get(); + } + + @Override + public void drop(DragAndDropEvent event) { + TargetDetailsImpl targetDetails = (TargetDetailsImpl) event + .getTargetDetails(); + int x = targetDetails.getMouseEvent().getRelativeX(); + int y = targetDetails.getMouseEvent().getRelativeY(); + + draggableLabel.setWidth(x, Unit.PIXELS); + draggableLabel.setHeight(y, Unit.PIXELS); + } + }); + + sp = SpacebarPanner.wrap(this); + } + + @Override + protected Integer getTicketNumber() { + return 17163; + } + + @Override + protected String getTestDescription() { + return "Hold space while clicking and dragging the label, or click the button before draggin the label. There should be no client-side exception."; + } +} diff --git a/uitest/src/com/vaadin/tests/dd/DDInterruptTest.java b/uitest/src/com/vaadin/tests/dd/DDInterruptTest.java new file mode 100644 index 0000000000..e078bc4665 --- /dev/null +++ b/uitest/src/com/vaadin/tests/dd/DDInterruptTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.dd; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.support.ui.ExpectedCondition; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.testbench.elements.UIElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Test for interrupting drag-and-drop. + * + * @author Vaadin Ltd + */ +public class DDInterruptTest extends MultiBrowserTest { + + private UIElement ui; + + @Override + public void setup() throws Exception { + super.setup(); + openTestURL("debug"); + ui = $(UIElement.class).first(); + } + + @Test + public void testRegularDragging() { + dragElement(); + assertNoNotifications(); + assertDragged(true); + } + + @Test + public void testTriggeredDragging() { + $(ButtonElement.class).first().click(); + waitUntilTriggered(true); + + dragElement(); + + waitUntilTriggered(false); + assertNoNotifications(); + assertDragged(false); + } + + private void dragElement() { + LabelElement label = $(LabelElement.class).id("draggable"); + new Actions(driver).moveToElement(label).clickAndHold() + .moveByOffset(400, 400).perform(); + } + + private void assertNoNotifications() { + Assert.assertEquals( + "Notification found when there should have been none,", 0, + findElements(By.className("v-Notification")).size()); + } + + private void assertDragged(boolean dragged) { + Assert.assertEquals("Unexpected drag state,", dragged ? 1 : 0, + findElements(By.className("v-ddwrapper-over-bottom")).size()); + } + + private void waitUntilTriggered(final boolean triggered) { + waitUntil(new ExpectedCondition() { + + @Override + public Boolean apply(WebDriver arg0) { + return triggered == hasCssClass(ui, "triggered"); + } + + @Override + public String toString() { + return String.format("UI to %s stylename 'triggered'", + (triggered ? "get" : "lose")); + } + }); + } +} diff --git a/uitest/src/com/vaadin/tests/dd/SpacebarPanner.java b/uitest/src/com/vaadin/tests/dd/SpacebarPanner.java new file mode 100644 index 0000000000..d6179066fb --- /dev/null +++ b/uitest/src/com/vaadin/tests/dd/SpacebarPanner.java @@ -0,0 +1,20 @@ +package com.vaadin.tests.dd; + +import com.vaadin.server.AbstractExtension; +import com.vaadin.ui.UI; + +public class SpacebarPanner extends AbstractExtension { + + private static final long serialVersionUID = -7712258690917457123L; + + public static SpacebarPanner wrap(UI ui) { + SpacebarPanner panner = new SpacebarPanner(); + panner.extend(ui); + return panner; + } + + public void interruptNext() { + getState().enabled = !getState().enabled; + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/dd/SpacebarPannerConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/dd/SpacebarPannerConnector.java new file mode 100644 index 0000000000..e13dd5030b --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/dd/SpacebarPannerConnector.java @@ -0,0 +1,125 @@ +package com.vaadin.tests.widgetset.client.dd; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.event.dom.client.KeyCodes; +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.vaadin.client.ServerConnector; +import com.vaadin.client.annotations.OnStateChange; +import com.vaadin.client.extensions.AbstractExtensionConnector; +import com.vaadin.client.ui.VUI; +import com.vaadin.client.ui.dd.VDragAndDropManager; +import com.vaadin.client.ui.ui.UIConnector; +import com.vaadin.shared.ui.Connect; + +@Connect(com.vaadin.tests.dd.SpacebarPanner.class) +public class SpacebarPannerConnector extends AbstractExtensionConnector { + + Logger logger = Logger.getLogger(SpacebarPannerConnector.class + .getSimpleName()); + + private boolean trigger = false; + private VUI vui; + private boolean first = true; + + @Override + protected void extend(ServerConnector target) { + UIConnector uic = (UIConnector) target; + vui = uic.getWidget(); + Event.sinkEvents(vui.getElement(), Event.MOUSEEVENTS | Event.KEYEVENTS); + Event.addNativePreviewHandler(createNativePreviewHandler()); + } + + @OnStateChange("enabled") + private void trigger() { + if (first) { + // ignore initial state change + first = false; + } else { + trigger = true; + vui.addStyleName("triggered"); + } + } + + private NativePreviewHandler createNativePreviewHandler() { + return new NativePreviewHandler() { + + private boolean spacebarDown = false; + private boolean shouldPan = false; + private boolean mouseDown = false; + + private int lastMouseX; + private int lastMouseY; + + @Override + public void onPreviewNativeEvent(NativePreviewEvent event) { + NativeEvent ne = event.getNativeEvent(); + int type = event.getTypeInt(); + + switch (type) { + case Event.ONKEYDOWN: + if (ne.getKeyCode() == KeyCodes.KEY_SPACE) { + event.cancel(); + ne.preventDefault(); + ne.stopPropagation(); + spacebarDown = true; + break; + } + case Event.ONKEYUP: + if (ne.getKeyCode() == KeyCodes.KEY_SPACE) { + spacebarDown = false; + } + break; + case Event.ONMOUSEDOWN: + logger.log(Level.INFO, "Drag started"); + lastMouseX = ne.getClientX(); + lastMouseY = ne.getClientY(); + + shouldPan = spacebarDown || trigger; + mouseDown = true; + break; + + case Event.ONMOUSEUP: + shouldPan = false || trigger; + mouseDown = false; + break; + + case Event.ONMOUSEMOVE: + if (mouseDown && shouldPan) { + logger.log(Level.INFO, "In mousemove: mouseDown:" + + mouseDown + ", shouldPan: " + shouldPan); + trigger = false; + vui.removeStyleName("triggered"); + + logger.log(Level.INFO, "Panning!"); + int currentClientX = ne.getClientX(); + int currentClientY = ne.getClientY(); + + int deltaX = lastMouseX - currentClientX; + int deltaY = lastMouseY - currentClientY; + lastMouseX = currentClientX; + lastMouseY = currentClientY; + + // this causes #17163 + VDragAndDropManager.get().interruptDrag(); + + Element uiElement = vui.getElement(); + int top = uiElement.getScrollTop(); + int left = uiElement.getScrollLeft(); + + uiElement.setScrollTop(top + deltaY); + uiElement.setScrollLeft(left + deltaX); + } + + default: + break; + } + } + }; + } +} -- cgit v1.2.3 From 103b329d328ab0dde95da9426462491be510a8be Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Fri, 27 Mar 2015 13:57:51 +0200 Subject: Reduce reflows when sizing columns (#17315) This patch increases the reported fps from 10 to 17 in Chrome and from 5 to 10 in Firefox. No automatic test since performance testing on our shared testing infrastructure would be quite error-prone. Change-Id: I0bb6af250743058a8f32bb2df89da97660e94b52 --- .../src/com/vaadin/client/widgets/Escalator.java | 110 ++++++++++----- .../tests/components/grid/GridResizeTerror.java | 45 ++++++ .../com/vaadin/tests/util/ResizeTerrorizer.java | 51 +++++++ .../client/ResizeTerrorizerControlConnector.java | 157 +++++++++++++++++++++ .../rebind/TestWidgetRegistryGenerator.java | 3 + 5 files changed, 328 insertions(+), 38 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/GridResizeTerror.java create mode 100644 uitest/src/com/vaadin/tests/util/ResizeTerrorizer.java create mode 100644 uitest/src/com/vaadin/tests/widgetset/client/ResizeTerrorizerControlConnector.java (limited to 'client') diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java index 3d4459a0cc..83c176d6fd 100644 --- a/client/src/com/vaadin/client/widgets/Escalator.java +++ b/client/src/com/vaadin/client/widgets/Escalator.java @@ -16,6 +16,7 @@ package com.vaadin.client.widgets; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; @@ -2010,9 +2011,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker return new Cell(domRowIndex, domColumnIndex, cellElement); } - double getMaxCellWidth(int colIndex) throws IllegalArgumentException { - double maxCellWidth = -1; - + void createAutoSizeElements(int colIndex, + Collection elements) { assert isAttached() : "Can't measure max width of cell, since Escalator is not attached to the DOM."; NodeList rows = root.getRows(); @@ -2041,24 +2041,9 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker cellClone.getStyle().clearWidth(); rowElement.insertBefore(cellClone, cellOriginal); - double requiredWidth = WidgetUtil - .getRequiredWidthBoundingClientRectDouble(cellClone); - - if (BrowserInfo.get().isIE()) { - /* - * IE browsers have some issues with subpixels. Occasionally - * content is overflown even if not necessary. Increase the - * counted required size by 0.01 just to be on the safe - * side. - */ - requiredWidth += 0.01; - } - maxCellWidth = Math.max(requiredWidth, maxCellWidth); - cellClone.removeFromParent(); + elements.add(cellClone); } - - return maxCellWidth; } private boolean cellIsPartOfSpan(TableCellElement cell) { @@ -3789,7 +3774,8 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker if (px < 0) { if (isAttached()) { - calculateWidth(); + autosizeColumns(Collections.singletonList(columns + .indexOf(this))); } else { /* * the column's width is calculated at Escalator.onLoad @@ -3843,10 +3829,6 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker } return false; } - - private void calculateWidth() { - calculatedWidth = getMaxCellWidth(columns.indexOf(this)); - } } private final List columns = new ArrayList(); @@ -4151,6 +4133,7 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker return; } + List autosizeColumns = new ArrayList(); for (Entry entry : indexWidthMap.entrySet()) { int index = entry.getKey().intValue(); double width = entry.getValue().doubleValue(); @@ -4160,10 +4143,15 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker } checkValidColumnIndex(index); - columns.get(index).setWidth(width); - + if (width >= 0) { + columns.get(index).setWidth(width); + } else { + autosizeColumns.add(index); + } } + autosizeColumns(autosizeColumns); + widthsArray = null; header.reapplyColumnWidths(); body.reapplyColumnWidths(); @@ -4174,6 +4162,64 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker recalculateElementSizes(); } + private void autosizeColumns(List columns) { + if (columns.isEmpty()) { + return; + } + + // Must process columns in index order + Collections.sort(columns); + + Map> autoSizeElements = new HashMap>(); + try { + // Set up the entire DOM at once + for (int i = columns.size() - 1; i >= 0; i--) { + // Iterate backwards to not mess with the indexing + Integer colIndex = columns.get(i); + + ArrayList elements = new ArrayList(); + autoSizeElements.put(colIndex, elements); + + header.createAutoSizeElements(colIndex, elements); + body.createAutoSizeElements(colIndex, elements); + footer.createAutoSizeElements(colIndex, elements); + } + + // Extract all measurements & update values + for (Integer colIndex : columns) { + double maxWidth = Double.NEGATIVE_INFINITY; + List elements = autoSizeElements + .get(colIndex); + for (TableCellElement element : elements) { + + double cellWidth = WidgetUtil + .getRequiredWidthBoundingClientRectDouble(element); + + maxWidth = Math.max(maxWidth, cellWidth); + } + assert maxWidth >= 0 : "Got a negative max width for a column, which should be impossible."; + + if (BrowserInfo.get().isIE()) { + /* + * IE browsers have some issues with subpixels. + * Occasionally content is overflown even if not + * necessary. Increase the counted required size by 0.01 + * just to be on the safe side. + */ + maxWidth += 0.01; + } + + this.columns.get(colIndex).calculatedWidth = maxWidth; + } + } finally { + for (List list : autoSizeElements.values()) { + for (TableCellElement element : list) { + element.removeFromParent(); + } + } + } + } + private void checkValidColumnIndex(int index) throws IllegalArgumentException { if (!Range.withLength(0, getColumnCount()).contains(index)) { @@ -4193,18 +4239,6 @@ public class Escalator extends Widget implements RequiresResize, DeferredWorker return columns.get(index).getCalculatedWidth(); } - private double getMaxCellWidth(int colIndex) - throws IllegalArgumentException { - double headerWidth = header.getMaxCellWidth(colIndex); - double bodyWidth = body.getMaxCellWidth(colIndex); - double footerWidth = footer.getMaxCellWidth(colIndex); - - double maxWidth = Math.max(headerWidth, - Math.max(bodyWidth, footerWidth)); - assert maxWidth >= 0 : "Got a negative max width for a column, which should be impossible."; - return maxWidth; - } - /** * Calculates the width of the columns in a given range. * diff --git a/uitest/src/com/vaadin/tests/components/grid/GridResizeTerror.java b/uitest/src/com/vaadin/tests/components/grid/GridResizeTerror.java new file mode 100644 index 0000000000..365461caa9 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridResizeTerror.java @@ -0,0 +1,45 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.components.grid; + +import com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.util.ResizeTerrorizer; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.ui.Grid; +import com.vaadin.ui.UI; + +@Widgetset(TestingWidgetSet.NAME) +public class GridResizeTerror extends UI { + @Override + protected void init(VaadinRequest request) { + Grid grid = new Grid(); + + int cols = 10; + Object[] data = new Object[cols]; + + for (int i = 0; i < cols; i++) { + grid.addColumn("Col " + i); + data[i] = "Data " + i; + } + + for (int i = 0; i < 500; i++) { + grid.addRow(data); + } + + setContent(new ResizeTerrorizer(grid)); + } +} diff --git a/uitest/src/com/vaadin/tests/util/ResizeTerrorizer.java b/uitest/src/com/vaadin/tests/util/ResizeTerrorizer.java new file mode 100644 index 0000000000..f124305d8a --- /dev/null +++ b/uitest/src/com/vaadin/tests/util/ResizeTerrorizer.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.util; + +import com.vaadin.tests.widgetset.client.ResizeTerrorizerControlConnector.ResizeTerorrizerState; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.Component; +import com.vaadin.ui.VerticalLayout; + +public class ResizeTerrorizer extends VerticalLayout { + private final ResizeTerrorizerControl control; + + public class ResizeTerrorizerControl extends AbstractComponent implements + Component { + + public ResizeTerrorizerControl(Component target) { + getState().target = target; + } + + @Override + protected ResizeTerorrizerState getState() { + return (ResizeTerorrizerState) super.getState(); + } + } + + public ResizeTerrorizer(Component target) { + target.setWidth("700px"); + setSizeFull(); + addComponent(target); + setExpandRatio(target, 1); + control = new ResizeTerrorizerControl(target); + addComponent(control); + } + + public void setDefaultWidthOffset(int px) { + control.getState().defaultWidthOffset = px; + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/ResizeTerrorizerControlConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/ResizeTerrorizerControlConnector.java new file mode 100644 index 0000000000..9fe037706b --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/ResizeTerrorizerControlConnector.java @@ -0,0 +1,157 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.client; + +import com.google.gwt.animation.client.AnimationScheduler; +import com.google.gwt.animation.client.AnimationScheduler.AnimationCallback; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.IntegerBox; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.RequiresResize; +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.client.ui.PostLayoutListener; +import com.vaadin.shared.AbstractComponentState; +import com.vaadin.shared.Connector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.tests.util.ResizeTerrorizer; + +@Connect(ResizeTerrorizer.ResizeTerrorizerControl.class) +public class ResizeTerrorizerControlConnector extends + AbstractComponentConnector implements PostLayoutListener { + + public static class ResizeTerorrizerState extends AbstractComponentState { + public Connector target; + public int defaultWidthOffset = 200; + } + + public class ResizeTerrorizerControlPanel extends FlowPanel { + private Label results = new Label("Results"); + private IntegerBox startWidth = new IntegerBox(); + private IntegerBox endWidth = new IntegerBox(); + private final Button terrorizeButton = new Button("Terrorize", + new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + terrorize(startWidth.getValue(), endWidth.getValue(), + 1000); + } + }); + + public ResizeTerrorizerControlPanel() { + add(new Label("Start width")); + add(startWidth); + + add(new Label("End width")); + add(endWidth); + + add(terrorizeButton); + add(results); + + startWidth.getElement().setId("terror-start-width"); + endWidth.getElement().setId("terror-end-width"); + terrorizeButton.getElement().setId("terror-button"); + results.getElement().setId("terror-results"); + } + + private void showResults(String results) { + Integer temp = startWidth.getValue(); + startWidth.setValue(endWidth.getValue()); + endWidth.setValue(temp); + + this.results.setText(results); + } + } + + private void terrorize(final double startWidth, final double endWidth, + final double duration) { + final AbstractComponentConnector target = getTarget(); + + final AnimationScheduler scheduler = AnimationScheduler.get(); + AnimationCallback callback = new AnimationCallback() { + double startTime = -1; + int frameCount = 0; + + @Override + public void execute(double timestamp) { + frameCount++; + + boolean done = false; + if (startTime == -1) { + startTime = timestamp; + } + + double time = timestamp - startTime; + if (time > duration) { + time = duration; + done = true; + } + + double progress = time / duration; + double widthToSet = startWidth + (endWidth - startWidth) + * progress; + + // TODO Optionally inform LayoutManager as well + target.getWidget().setWidth(widthToSet + "px"); + if (target.getWidget() instanceof RequiresResize) { + ((RequiresResize) target.getWidget()).onResize(); + } + + if (!done) { + scheduler.requestAnimationFrame(this); + } else { + double fps = Math.round(frameCount / (duration / 1000)); + String results = frameCount + " frames, " + fps + " fps"; + + getWidget().showResults(results); + } + } + }; + scheduler.requestAnimationFrame(callback); + } + + private AbstractComponentConnector getTarget() { + return (AbstractComponentConnector) getState().target; + } + + @Override + public ResizeTerorrizerState getState() { + return (ResizeTerorrizerState) super.getState(); + } + + @Override + public ResizeTerrorizerControlPanel getWidget() { + return (ResizeTerrorizerControlPanel) super.getWidget(); + } + + @Override + protected ResizeTerrorizerControlPanel createWidget() { + return new ResizeTerrorizerControlPanel(); + } + + @Override + public void postLayout() { + if (getWidget().startWidth.getValue() == null) { + int width = getTarget().getWidget().getElement().getOffsetWidth(); + getWidget().startWidth.setValue(width); + getWidget().endWidth + .setValue(width + getState().defaultWidthOffset); + } + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java b/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java index 1bdbba2c36..c7b29e271b 100644 --- a/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java +++ b/uitest/src/com/vaadin/tests/widgetset/rebind/TestWidgetRegistryGenerator.java @@ -136,6 +136,9 @@ public class TestWidgetRegistryGenerator extends Generator { } else if (!widgetType.getPackage().getName() .startsWith(TestWidgetConnector.class.getPackage().getName())) { return false; + } else if (widgetType.getEnclosingType() != null + && !widgetType.isStatic()) { + return false; } return true; -- cgit v1.2.3 From 3ab82ace45827365e87f9540fad3dffaed0679b5 Mon Sep 17 00:00:00 2001 From: Pekka Hyvönen Date: Tue, 31 Mar 2015 12:03:56 +0300 Subject: Don't remove frozen columns when columns reordered in Grid #16901 Change-Id: Ib812ecd6afeb92d56bb179bcb120c65f20d26a8c --- client/src/com/vaadin/client/widgets/Grid.java | 4 +++- .../client/GridClientColumnPropertiesTest.java | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index 31cf4ec866..4b27e17e37 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -4680,7 +4680,6 @@ public class Grid extends ResizeComposite implements escalator.getColumnConfiguration() .setFrozenColumnCount(numberOfColumns); - } /** @@ -5960,6 +5959,9 @@ public class Grid extends ResizeComposite implements // Do ComplexRenderer.init and render new content conf.insertColumns(0, columns.size()); + // Number of frozen columns should be kept same #16901 + updateFrozenColumns(); + // Update column widths. for (Column column : columns) { column.reapplyWidth(); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java index 9e7256e0d3..2f5d0e7291 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java @@ -93,6 +93,23 @@ public class GridClientColumnPropertiesTest extends GridBasicClientFeaturesTest assertFalse(cellIsFrozen(1, 0)); } + @Test + public void testFrozenColumns_columnsReordered_frozenColumnsKept() { + openTestURL(); + + selectMenuPath("Component", "State", "Frozen column count", "2 columns"); + + assertTrue(cellIsFrozen(1, 0)); + assertTrue(cellIsFrozen(1, 1)); + assertFalse(cellIsFrozen(1, 2)); + + selectMenuPath("Component", "State", "Reverse grid columns"); + + assertTrue(cellIsFrozen(1, 0)); + assertTrue(cellIsFrozen(1, 1)); + assertFalse(cellIsFrozen(1, 2)); + } + @Test public void testBrokenRenderer() { setDebug(true); -- cgit v1.2.3