From 22271249251894dfc7cfbebad6b4d2faf4c0313e Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 12 May 2015 10:50:45 +0300 Subject: Add missing @since for 7.5 Change-Id: Id8f78c9ef7670c5413d3b7d28eef732dd1b7512d --- client/src/com/vaadin/client/connectors/GridConnector.java | 7 +++++++ client/src/com/vaadin/client/widgets/Escalator.java | 6 ++++++ client/src/com/vaadin/client/widgets/Grid.java | 2 ++ 3 files changed, 15 insertions(+) (limited to 'client') diff --git a/client/src/com/vaadin/client/connectors/GridConnector.java b/client/src/com/vaadin/client/connectors/GridConnector.java index d31baaa665..d3fa678c3e 100644 --- a/client/src/com/vaadin/client/connectors/GridConnector.java +++ b/client/src/com/vaadin/client/connectors/GridConnector.java @@ -1415,6 +1415,13 @@ public class GridConnector extends AbstractHasComponentsConnector implements || lazyDetailsScrollAdjuster.isWorkPending(); } + /** + * Gets the listener used by this connector for tracking when row detail + * visibility changes. + * + * @since 7.5.0 + * @return the used details listener + */ public DetailsListener getDetailsListener() { return detailsListener; } diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java index 7c18df3c7d..16d1a9f5c2 100644 --- a/client/src/com/vaadin/client/widgets/Escalator.java +++ b/client/src/com/vaadin/client/widgets/Escalator.java @@ -1354,6 +1354,8 @@ public class Escalator extends Widget implements RequiresResize, * Any extra content, such as spacers for the body, should not be * included in this count. * + * @since 7.5.0 + * * @return the actual DOM count of rows */ public abstract int getDomRowCount(); @@ -1755,6 +1757,8 @@ public class Escalator extends Widget implements RequiresResize, * In practice, this applies for all header and footer rows. For body * rows, it applies for all rows except spacer rows. * + * @since 7.5.0 + * * @param tr * the row element to check for if it is or has elements that * can be frozen @@ -2118,6 +2122,8 @@ public class Escalator extends Widget implements RequiresResize, * Note that {@link Escalator#getBody() the body} will calculate its * height, while the others will return a precomputed value. * + * @since 7.5.0 + * * @return the height of this table section */ protected abstract double getHeightOfSection(); diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index c20bdb0bd4..51f44edd8a 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -216,6 +216,8 @@ public class Grid extends ResizeComposite implements /** * Abstract base class for Grid header and footer sections. * + * @since 7.5.0 + * * @param * the type of the rows in the section */ -- cgit v1.2.3 From 0a7d5bcd585dcfc08ea7c4339dc03f29cea6fde4 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Tue, 24 Mar 2015 10:46:39 +0200 Subject: Revert "Moved accessibility shortcut handling to server-side. [#14843]" This reverts commit e88f71dd6d1d7634e3a90a7e53859ff6dc028e21. Change-Id: I1d4ed60ec4a194f6ed18fa5506134ef3a185a6cf --- client/src/com/vaadin/client/ui/VWindow.java | 4 +- server/src/com/vaadin/event/ShortcutAction.java | 38 ---- server/src/com/vaadin/ui/Window.java | 102 ++-------- .../tests/components/window/CloseShortcut.java | 121 ------------ .../tests/components/window/CloseShortcutTest.java | 219 --------------------- 5 files changed, 15 insertions(+), 469 deletions(-) delete mode 100644 uitest/src/com/vaadin/tests/components/window/CloseShortcut.java delete mode 100644 uitest/src/com/vaadin/tests/components/window/CloseShortcutTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/VWindow.java b/client/src/com/vaadin/client/ui/VWindow.java index d28686e777..c5cab8ff6b 100644 --- a/client/src/com/vaadin/client/ui/VWindow.java +++ b/client/src/com/vaadin/client/ui/VWindow.java @@ -1354,7 +1354,9 @@ public class VWindow extends VOverlay implements ShortcutActionHandlerOwner, @Override public void onKeyUp(KeyUpEvent event) { - // do nothing + if (isClosable() && event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) { + onCloseClick(); + } } @Override diff --git a/server/src/com/vaadin/event/ShortcutAction.java b/server/src/com/vaadin/event/ShortcutAction.java index 32b909e9f2..09accae1c7 100644 --- a/server/src/com/vaadin/event/ShortcutAction.java +++ b/server/src/com/vaadin/event/ShortcutAction.java @@ -17,8 +17,6 @@ package com.vaadin.event; import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -238,42 +236,6 @@ public class ShortcutAction extends Action { return modifiers; } - /** - * Checks whether the shortcut can be triggered with the given combination - * of keys. - * - * @param keyCode - * potential match for the {@link KeyCode} that this shortcut - * reacts to - * @param modifierKeys - * (optional) potential matches for the {@link ModifierKey}s - * required for this shortcut to react - * @return true if keyCode and modifierKeys are a match, - * false otherwise - */ - public boolean isTriggeredBy(int keyCode, int... modifierKeys) { - boolean result = false; - if (keyCode == this.keyCode) { - if (modifierKeys == null) { - result = (modifiers == null); - } else if (modifiers != null) { - List modifierList = new ArrayList(); - for (int modifier : modifiers) { - modifierList.add(modifier); - } - for (int modifierKey : modifierKeys) { - if (modifierList.contains(modifierKey)) { - modifierList.remove(modifierKey); - } else { - return false; - } - } - result = modifierList.isEmpty(); - } - } - return result; - } - /** * Key codes that can be used for shortcuts * diff --git a/server/src/com/vaadin/ui/Window.java b/server/src/com/vaadin/ui/Window.java index e7764ffd8d..61664fc95d 100644 --- a/server/src/com/vaadin/ui/Window.java +++ b/server/src/com/vaadin/ui/Window.java @@ -21,9 +21,6 @@ import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -133,7 +130,6 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, super(caption, content); registerRpc(rpc); setSizeUndefined(); - setCloseShortcut(ShortcutAction.KeyCode.ESCAPE); } /* ********************************************************************* */ @@ -820,48 +816,14 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, /* * Actions */ - private LinkedHashSet closeShortcuts = new LinkedHashSet(); - - protected Collection getCloseShortcuts() { - return Collections.unmodifiableCollection(closeShortcuts); - } - - /** - * Adds a keyboard shortcut for closing the window when user presses the - * given {@link KeyCode} and (optional) {@link ModifierKey}s.
- * Note that this shortcut only reacts while the window has focus, closing - * itself - if you want to close a window from a UI, use - * {@link UI#addAction(com.vaadin.event.Action)} of the UI instead. - *

- * If there is a prior CloseShortcut with the same keycode and modifiers, - * that gets removed before the new one is added. Prior CloseShortcuts with - * differing keycodes or modifiers are not affected. - * - * @param keyCode - * the keycode for invoking the shortcut - * @param modifiers - * the (optional) modifiers for invoking the shortcut, null for - * none - */ - public void addCloseShortcut(int keyCode, int... modifiers) { - // make sure there are no duplicates - removeCloseShortcut(keyCode, modifiers); - CloseShortcut closeShortcut = new CloseShortcut(this, keyCode, - modifiers); - closeShortcuts.add(closeShortcut); - addAction(closeShortcut); - } + protected CloseShortcut closeShortcut; /** - * Sets the keyboard shortcut for closing the window when user presses the - * given {@link KeyCode} and (optional) {@link ModifierKey}s.
+ * Makes is possible to close the window by pressing the given + * {@link KeyCode} and (optional) {@link ModifierKey}s.
* Note that this shortcut only reacts while the window has focus, closing * itself - if you want to close a window from a UI, use * {@link UI#addAction(com.vaadin.event.Action)} of the UI instead. - *

- * If there are any prior CloseShortcuts when this method is called those - * get removed before the new one is added. NOTE: this also removes the - * default shortcut that is added for accessibility purposes. * * @param keyCode * the keycode for invoking the shortcut @@ -870,61 +832,22 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, * none */ public void setCloseShortcut(int keyCode, int... modifiers) { - removeCloseShortcuts(); - addCloseShortcut(keyCode, modifiers); - } - - /** - * Removes a keyboard shortcut previously set with - * {@link #setCloseShortcut(int, int...)} or - * {@link #addCloseShortcut(int, int...)}. - * - * @param keyCode - * the keycode for invoking the shortcut - * @param modifiers - * the (optional) modifiers for invoking the shortcut, null for - * none - */ - public void removeCloseShortcut(int keyCode, int... modifiers) { - for (CloseShortcut closeShortcut : closeShortcuts) { - if (closeShortcut.isTriggeredBy(keyCode, modifiers)) { - removeAction(closeShortcut); - closeShortcuts.remove(closeShortcut); - break; - } + if (closeShortcut != null) { + removeAction(closeShortcut); } + closeShortcut = new CloseShortcut(this, keyCode, modifiers); + addAction(closeShortcut); } /** - * @deprecated use {@link #resetCloseShortcuts()} instead, or - * {@link #removeCloseShortcuts()} if you also want to get rid - * of the default shortcut + * Removes the keyboard shortcut previously set with + * {@link #setCloseShortcut(int, int...)}. */ - @Deprecated public void removeCloseShortcut() { - resetCloseShortcuts(); - } - - /** - * Removes all the keyboard shortcuts previously set with - * {@link #setCloseShortcut(int, int...)} or - * {@link #addCloseShortcut(int, int...)} and re-adds the default shortcut - * {@link KeyCode.ESCAPE}. - */ - public void resetCloseShortcuts() { - setCloseShortcut(ShortcutAction.KeyCode.ESCAPE); - } - - /** - * Removes all the keyboard shortcuts previously set with - * {@link #setCloseShortcut(int, int...)} or - * {@link #addCloseShortcut(int, int...)}. - */ - public void removeCloseShortcuts() { - for (CloseShortcut closeShortcut : closeShortcuts) { + if (closeShortcut != null) { removeAction(closeShortcut); + closeShortcut = null; } - closeShortcuts.clear(); } /** @@ -1391,8 +1314,7 @@ public class Window extends Panel implements FocusNotifier, BlurNotifier, } private CloseShortcut getCloseShortcut() { - Iterator i = getCloseShortcuts().iterator(); - return i.hasNext() ? i.next() : null; + return closeShortcut; } @Override diff --git a/uitest/src/com/vaadin/tests/components/window/CloseShortcut.java b/uitest/src/com/vaadin/tests/components/window/CloseShortcut.java deleted file mode 100644 index c7499134e0..0000000000 --- a/uitest/src/com/vaadin/tests/components/window/CloseShortcut.java +++ /dev/null @@ -1,121 +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.components.window; - -import com.vaadin.data.Property; -import com.vaadin.data.Property.ValueChangeEvent; -import com.vaadin.event.ShortcutAction.KeyCode; -import com.vaadin.event.ShortcutAction.ModifierKey; -import com.vaadin.server.VaadinRequest; -import com.vaadin.tests.components.AbstractTestUI; -import com.vaadin.ui.Button; -import com.vaadin.ui.Button.ClickEvent; -import com.vaadin.ui.CheckBox; -import com.vaadin.ui.TextField; -import com.vaadin.ui.VerticalLayout; -import com.vaadin.ui.Window; - -/** - * Tests close shortcuts for Window. - * - * @author Vaadin Ltd - */ -public class CloseShortcut extends AbstractTestUI { - - @Override - protected void setup(VaadinRequest request) { - final Window w = new Window(); - w.setWidth("300px"); - w.setHeight("300px"); - w.center(); - addWindow(w); - w.focus(); - - // add textfield to the window to give TestBench something to send the - // keys to - VerticalLayout content = new VerticalLayout(); - content.setMargin(true); - TextField textField = new TextField(); - textField.setSizeFull(); - content.addComponent(textField); - w.setContent(content); - - final CheckBox cbDefault = new CheckBox("Use default (ESC) shortcut"); - cbDefault.setId("default"); - addComponent(cbDefault); - final CheckBox cbOther = new CheckBox("Use R shortcut"); - cbOther.setId("other"); - addComponent(cbOther); - final CheckBox cbCtrl = new CheckBox("Use CTRL+A shortcut"); - cbCtrl.setId("control"); - addComponent(cbCtrl); - final CheckBox cbShift = new CheckBox("Use SHIFT+H shortcut"); - cbShift.setId("shift"); - addComponent(cbShift); - - cbOther.setValue(true); - cbCtrl.setValue(true); - cbShift.setValue(true); - - Property.ValueChangeListener listener = new Property.ValueChangeListener() { - - @Override - public void valueChange(ValueChangeEvent event) { - if (Boolean.TRUE.equals(cbDefault.getValue())) { - w.resetCloseShortcuts(); - } else { - w.removeCloseShortcuts(); - } - if (Boolean.TRUE.equals(cbOther.getValue())) { - w.addCloseShortcut(KeyCode.R); - } - if (Boolean.TRUE.equals(cbCtrl.getValue())) { - w.addCloseShortcut(KeyCode.A, ModifierKey.CTRL); - } - if (Boolean.TRUE.equals(cbShift.getValue())) { - w.addCloseShortcut(KeyCode.H, ModifierKey.SHIFT); - } - } - }; - cbDefault.addValueChangeListener(listener); - cbOther.addValueChangeListener(listener); - cbCtrl.addValueChangeListener(listener); - cbShift.addValueChangeListener(listener); - - cbDefault.setValue(true); // trigger value change - - Button button = new Button("Reopen window", new Button.ClickListener() { - - @Override - public void buttonClick(ClickEvent event) { - w.close(); - addWindow(w); - w.focus(); - } - }); - addComponent(button); - } - - @Override - protected String getTestDescription() { - return "It should be possible to have multiple shortcuts at the same time, and to remove the default shortcut ESC."; - } - - @Override - protected Integer getTicketNumber() { - return 14843; - } -} diff --git a/uitest/src/com/vaadin/tests/components/window/CloseShortcutTest.java b/uitest/src/com/vaadin/tests/components/window/CloseShortcutTest.java deleted file mode 100644 index df7b7cad0c..0000000000 --- a/uitest/src/com/vaadin/tests/components/window/CloseShortcutTest.java +++ /dev/null @@ -1,219 +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.components.window; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.junit.Before; -import org.junit.Test; -import org.openqa.selenium.By; -import org.openqa.selenium.Keys; -import org.openqa.selenium.WebDriver; -import org.openqa.selenium.interactions.Actions; -import org.openqa.selenium.remote.DesiredCapabilities; -import org.openqa.selenium.support.ui.ExpectedCondition; - -import com.vaadin.testbench.elements.CheckBoxElement; -import com.vaadin.testbench.elements.TextFieldElement; -import com.vaadin.testbench.elements.WindowElement; -import com.vaadin.testbench.parallel.BrowserUtil; -import com.vaadin.tests.tb3.MultiBrowserTest; - -/** - * Tests close shortcuts for Window. - * - * @author Vaadin Ltd - */ -public class CloseShortcutTest extends MultiBrowserTest { - - private WindowElement window; - private CheckBoxElement cbDefault; - private CheckBoxElement cbOther; - private CheckBoxElement cbCtrl; - private CheckBoxElement cbShift; - - @Override - @Before - public void setup() throws Exception { - super.setup(); - openTestURL(); - waitForElementPresent(By.className("v-window")); - - window = $(WindowElement.class).first(); - cbDefault = $(CheckBoxElement.class).id("default"); - cbOther = $(CheckBoxElement.class).id("other"); - cbCtrl = $(CheckBoxElement.class).id("control"); - cbShift = $(CheckBoxElement.class).id("shift"); - } - - @Test - public void testAllCheckBoxesSelected() { - assertTrue("Default wasn't selected initially.", isChecked(cbDefault)); - assertTrue("Other wasn't selected initially.", isChecked(cbOther)); - assertTrue("Ctrl+A wasn't selected initially.", isChecked(cbCtrl)); - assertTrue("Shift+H wasn't selected initially.", isChecked(cbShift)); - } - - @Test - public void testAllCheckBoxesClickable() { - click(cbDefault); - click(cbOther); - click(cbCtrl); - click(cbShift); - - assertFalse("Default was selected when it shouldn't have been.", - isChecked(cbDefault)); - assertFalse("Other was selected when it shouldn't have been.", - isChecked(cbOther)); - assertFalse("Ctrl+A was selected when it shouldn't have been.", - isChecked(cbCtrl)); - assertFalse("Shift+H was selected when it shouldn't have been.", - isChecked(cbShift)); - } - - @Test - public void testDefaultWithAll() { - attemptDefaultShortcut(); - ensureWindowClosed(); - } - - @Test - public void testDefaultWithoutSelection() { - click(cbDefault); - - attemptDefaultShortcut(); - ensureWindowOpen(); - } - - @Test - public void testOtherWithAll() { - attemptOtherShortcut(); - // TODO: remove this check once #14902 has been fixed - DesiredCapabilities cap = getDesiredCapabilities(); - if ((BrowserUtil.isIE(cap) && !BrowserUtil.isIE8(cap)) - || BrowserUtil.isPhantomJS(cap)) { - ensureWindowClosed(); - } - } - - @Test - public void testOtherWithoutSelection() { - click(cbOther); - - attemptOtherShortcut(); - ensureWindowOpen(); - } - - @Test - public void testCtrlWithAll() { - attemptCtrlShortcut(); - // TODO: remove this check once #14902 has been fixed - if (BrowserUtil.isPhantomJS(getDesiredCapabilities())) { - ensureWindowClosed(); - } - } - - @Test - public void testCtrlWithoutSelection() { - click(cbCtrl); - - attemptCtrlShortcut(); - ensureWindowOpen(); - } - - @Test - public void testShiftWithAll() { - attemptShiftShortcut(); - // TODO: remove this check once #14902 has been fixed - DesiredCapabilities capabilities = getDesiredCapabilities(); - if (!BrowserUtil.isIE(capabilities) || BrowserUtil.isIE8(capabilities)) { - ensureWindowClosed(); - } - } - - @Test - public void testShiftWithoutSelection() { - click(cbShift); - - attemptShiftShortcut(); - ensureWindowOpen(); - } - - private boolean isChecked(CheckBoxElement cb) { - String checked = cb.findElement(By.tagName("input")).getAttribute( - "checked"); - if ("true".equals(checked)) { - return true; - } else if (checked == null) { - return false; - } - throw new IllegalStateException( - "Unexpected attribute value for 'checked': " + checked); - } - - @Override - protected void click(final CheckBoxElement cb) { - final boolean initial = isChecked(cb); - super.click(cb); - waitUntil(new ExpectedCondition() { - @Override - public Boolean apply(WebDriver input) { - return initial != isChecked(cb); - } - - @Override - public String toString() { - // Timed out after 10 seconds waiting for ... - return "checked state to change"; - } - }); - } - - private void attemptDefaultShortcut() { - window.focus(); - $(TextFieldElement.class).first().sendKeys(Keys.ESCAPE); - } - - private void attemptOtherShortcut() { - window.focus(); - $(TextFieldElement.class).first().sendKeys("R"); - } - - private void attemptCtrlShortcut() { - window.focus(); - new Actions(driver).keyDown(Keys.CONTROL).perform(); - $(TextFieldElement.class).first().sendKeys("A"); - new Actions(driver).keyUp(Keys.CONTROL).perform(); - } - - private void attemptShiftShortcut() { - window.focus(); - new Actions(driver).keyDown(Keys.SHIFT).perform(); - $(TextFieldElement.class).first().sendKeys("H"); - new Actions(driver).keyUp(Keys.SHIFT).perform(); - } - - private void ensureWindowClosed() { - assertTrue("Window didn't close as expected.", $(WindowElement.class) - .all().isEmpty()); - } - - private void ensureWindowOpen() { - assertFalse("Window closed when it shouldn't have.", - $(WindowElement.class).all().isEmpty()); - } -} -- cgit v1.2.3 From 46d0e0c60077665f3cf1f80503bd30313d7fa61e Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Tue, 12 May 2015 11:49:50 +0300 Subject: Fix Grid and Escalator accessing of SubPartArguments This patch removes an extra static method from Escalator and makes Grid and Escalator call SubPartArguments create(String) method directly. Change-Id: I6825bc89540c6183a8fddeded8133fb7ef8e23f1 --- client/src/com/vaadin/client/widgets/Escalator.java | 6 +----- client/src/com/vaadin/client/widgets/Grid.java | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java index 16d1a9f5c2..a196c7f7d7 100644 --- a/client/src/com/vaadin/client/widgets/Escalator.java +++ b/client/src/com/vaadin/client/widgets/Escalator.java @@ -6653,7 +6653,7 @@ public class Escalator extends Widget implements RequiresResize, @Override @SuppressWarnings("deprecation") public com.google.gwt.user.client.Element getSubPartElement(String subPart) { - SubPartArguments args = parseSubPartArguments(subPart); + SubPartArguments args = SubPartArguments.create(subPart); Element tableStructureElement = getSubPartElementTableStructure(args); if (tableStructureElement != null) { @@ -6816,8 +6816,4 @@ public class Escalator extends Widget implements RequiresResize, private String getSubPartNameSpacer(Element subElement) { return body.spacerContainer.getSubPartName(subElement); } - - public static SubPartArguments parseSubPartArguments(String subPart) { - return SubPartArguments.create(subPart); - } } diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index 51f44edd8a..92827c47f0 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -6513,7 +6513,7 @@ public class Grid extends ResizeComposite implements return DOM.asOld(escalatorElement); } - SubPartArguments args = Escalator.parseSubPartArguments(subPart); + SubPartArguments args = SubPartArguments.create(subPart); Element editor = getSubPartElementEditor(args); if (editor != null) { -- cgit v1.2.3 From 5e0ac1f31c73537fdfce39e5a9d0c246a9deedd7 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Tue, 12 May 2015 12:18:50 +0300 Subject: Add missing JavaDoc for Escalator.SubPartArguments (#17814) Change-Id: Ib90f9325426898d65584cf9928a7730e18745c5d --- client/src/com/vaadin/client/widgets/Escalator.java | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'client') diff --git a/client/src/com/vaadin/client/widgets/Escalator.java b/client/src/com/vaadin/client/widgets/Escalator.java index a196c7f7d7..bb497e7e13 100644 --- a/client/src/com/vaadin/client/widgets/Escalator.java +++ b/client/src/com/vaadin/client/widgets/Escalator.java @@ -5471,6 +5471,12 @@ public class Escalator extends Widget implements RequiresResize, } } + /** + * Utility class for parsing and storing SubPart request string attributes + * for Grid and Escalator. + * + * @since 7.5.0 + */ public static class SubPartArguments { private String type; private int[] indices; -- cgit v1.2.3 From 0d1bbc946c5372994ef5587438023e42ddcfa54c Mon Sep 17 00:00:00 2001 From: Pekka Hyvönen Date: Wed, 13 May 2015 14:56:20 +0300 Subject: Fixes regression in Notifications and tests (#14872) Change-Id: Ifa52508f5555c47b778cb7f80aa09f665b03b8d4 --- .../src/com/vaadin/client/ApplicationConnection.java | 10 ++++++++-- client/src/com/vaadin/client/ui/VNotification.java | 17 ++++++++++++++--- .../vaadin/tests/themes/valo/NotificationStyle.java | 19 +++++++++++++++++-- .../tests/themes/valo/NotificationStyleTest.java | 15 ++++++++------- 4 files changed, 47 insertions(+), 14 deletions(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index af86818fb3..3a8d69f25a 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -1285,12 +1285,18 @@ public class ApplicationConnection implements HasHandlers { StringBuilder html = new StringBuilder(); if (caption != null) { - html.append("

"); + html.append("

"); html.append(caption); html.append("

"); } if (message != null) { - html.append("

"); + html.append("

"); html.append(message); html.append("

"); } diff --git a/client/src/com/vaadin/client/ui/VNotification.java b/client/src/com/vaadin/client/ui/VNotification.java index 2892d4e3ac..4f0c2eb625 100644 --- a/client/src/com/vaadin/client/ui/VNotification.java +++ b/client/src/com/vaadin/client/ui/VNotification.java @@ -63,8 +63,8 @@ public class VNotification extends VOverlay { private static final String STYLENAME_POSITION_CENTER = "v-position-center"; private static final String STYLENAME_POSITION_ASSISTIVE = "v-position-assistive"; - private static final String CAPTION = "caption"; - private static final String DESCRIPTION = "description"; + public static final String CAPTION = "caption"; + public static final String DESCRIPTION = "description"; /** * Position that is only accessible for assistive devices, invisible for @@ -532,7 +532,18 @@ public class VNotification extends VOverlay { html, position, style); } - private static String getDependentStyle(ApplicationConnection client, + /** + * Meant for internal usage only. + * + * @since 7.5.0 + * @param client + * application connection + * @param style + * the dependent style name + * @return the given dependent style name prefixed with current notification + * primary style + */ + public static String getDependentStyle(ApplicationConnection client, String style) { VNotification notification = createNotification(-1, client .getUIConnector().getWidget()); diff --git a/uitest/src/com/vaadin/tests/themes/valo/NotificationStyle.java b/uitest/src/com/vaadin/tests/themes/valo/NotificationStyle.java index c7abcf9303..e918bb64d0 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/NotificationStyle.java +++ b/uitest/src/com/vaadin/tests/themes/valo/NotificationStyle.java @@ -32,14 +32,29 @@ public class NotificationStyle extends AbstractTestUI { @Override protected void setup(VaadinRequest request) { - Button button = new Button("Show notification", + Button button = new Button("Show notification with h1", new Button.ClickListener() { @Override public void buttonClick(ClickEvent event) { Notification notification = new Notification( "

Caption

", - "

Description

"); + "

Description

" + + "

tested p

"); + notification.setHtmlContentAllowed(true); + notification.setDelayMsec(50000); + notification.show(getPage()); + } + }); + addComponent(button); + button = new Button("Show notification with p", + new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + Notification notification = new Notification( + "

Caption

", + "Description text

tested p text

"); notification.setHtmlContentAllowed(true); notification.setDelayMsec(50000); notification.show(getPage()); diff --git a/uitest/src/com/vaadin/tests/themes/valo/NotificationStyleTest.java b/uitest/src/com/vaadin/tests/themes/valo/NotificationStyleTest.java index 829ad27a94..b2db29443a 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/NotificationStyleTest.java +++ b/uitest/src/com/vaadin/tests/themes/valo/NotificationStyleTest.java @@ -57,19 +57,20 @@ public class NotificationStyleTest extends MultiBrowserTest { public void testNotificationPStyle() { openTestURL(); - $(ButtonElement.class).first().click(); + $(ButtonElement.class).get(1).click(); new Actions(getDriver()).moveByOffset(10, 10).perform(); waitUntil(notificationPresentCondition(), 2); WebElement notification = findElement(By.className("v-Notification")); - List headers = notification.findElements(By.tagName("p")); - String lineHeight = headers.get(0).getCssValue("line-height"); - String lineHeightInnerHeader = headers.get(1) - .getCssValue("line-height"); + WebElement description = notification.findElement(By + .className("v-Notification-description")); + String display = description.getCssValue("display"); + String displayP2 = notification.findElement( + By.className("tested-p")).getCssValue("display"); Assert.assertNotEquals("Styles for notification defined 'p' tag " - + "and custom HTML tag are the same", lineHeight, - lineHeightInnerHeader); + + "and custom HTML tag are the same", display, + displayP2); } private ExpectedCondition notificationPresentCondition() { -- cgit v1.2.3 From 7e122bed24ff0d91039fcc1c4083b317f51a0af0 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Thu, 20 Nov 2014 15:23:44 +0200 Subject: Don't show loading spinner if there are no tabs (#15241) Change-Id: Ib2f08fc036d0f9940a865353c43d2433767df1fc --- client/src/com/vaadin/client/ui/VTabsheet.java | 1 - .../vaadin/tests/components/tabsheet/EmptyTabSheetTest.java | 13 +++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/VTabsheet.java b/client/src/com/vaadin/client/ui/VTabsheet.java index a02679a0fc..8e4f3cb643 100644 --- a/client/src/com/vaadin/client/ui/VTabsheet.java +++ b/client/src/com/vaadin/client/ui/VTabsheet.java @@ -909,7 +909,6 @@ public class VTabsheet extends VTabsheetBase implements Focusable, SubPartAware deco = DOM.createDiv(); - addStyleDependentName("loading"); // Indicate initial progress tb.setStyleName(CLASSNAME + "-tabs"); DOM.setElementProperty(contentNode, "className", CLASSNAME + "-content"); DOM.setElementProperty(deco, "className", CLASSNAME + "-deco"); diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/EmptyTabSheetTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/EmptyTabSheetTest.java index cebb00c11b..6d0b78debd 100644 --- a/uitest/src/com/vaadin/tests/components/tabsheet/EmptyTabSheetTest.java +++ b/uitest/src/com/vaadin/tests/components/tabsheet/EmptyTabSheetTest.java @@ -15,7 +15,10 @@ */ package com.vaadin.tests.components.tabsheet; +import org.junit.Assert; import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; import com.vaadin.tests.tb3.MultiBrowserTest; @@ -27,4 +30,14 @@ public class EmptyTabSheetTest extends MultiBrowserTest { compareScreen("empty"); } + @Test + public void emptyTabSheetValo() { + openTestURL("theme=valo"); + + WebElement deco = getDriver().findElement( + By.className("v-tabsheet-deco")); + + Assert.assertEquals("none", deco.getCssValue("display")); + } + } -- cgit v1.2.3 From 3a5cd8e4cd36a9db986978c01fe39356b3cbe3b6 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Mon, 30 Mar 2015 16:02:05 +0300 Subject: Make FormLayout work with HTML captions (#17143) Change-Id: I334441fd2f8d5f6d9e0629f5d7b564e9008f3fe5 --- client/src/com/vaadin/client/ui/VFormLayout.java | 20 +++++--- .../formlayout/HtmlCaptionInFormLayout.java | 43 ++++++++++++++++ .../formlayout/HtmlCaptionInFormLayoutTest.java | 59 ++++++++++++++++++++++ 3 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/formlayout/HtmlCaptionInFormLayout.java create mode 100644 uitest/src/com/vaadin/tests/components/formlayout/HtmlCaptionInFormLayoutTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/VFormLayout.java b/client/src/com/vaadin/client/ui/VFormLayout.java index 3781305e52..42dbbde32a 100644 --- a/client/src/com/vaadin/client/ui/VFormLayout.java +++ b/client/src/com/vaadin/client/ui/VFormLayout.java @@ -223,7 +223,7 @@ public class VFormLayout extends SimplePanel { private Icon icon; - private Element captionText; + private Element captionContent; /** * @@ -274,13 +274,13 @@ public class VFormLayout extends SimplePanel { } if (state.caption != null) { - if (captionText == null) { - captionText = DOM.createSpan(); + if (captionContent == null) { + captionContent = DOM.createSpan(); - AriaHelper.bindCaption(owner.getWidget(), captionText); + AriaHelper.bindCaption(owner.getWidget(), captionContent); - DOM.insertChild(getElement(), captionText, icon == null ? 0 - : 1); + DOM.insertChild(getElement(), captionContent, + icon == null ? 0 : 1); } String c = state.caption; if (c == null) { @@ -288,12 +288,16 @@ public class VFormLayout extends SimplePanel { } else { isEmpty = false; } - DOM.setInnerText(captionText, c); + if (state.captionAsHtml) { + captionContent.setInnerHTML(c); + } else { + captionContent.setInnerText(c); + } } else { // TODO should span also be removed } - if (state.description != null && captionText != null) { + if (state.description != null && captionContent != null) { addStyleDependentName("hasdescription"); } else { removeStyleDependentName("hasdescription"); diff --git a/uitest/src/com/vaadin/tests/components/formlayout/HtmlCaptionInFormLayout.java b/uitest/src/com/vaadin/tests/components/formlayout/HtmlCaptionInFormLayout.java new file mode 100644 index 0000000000..fc90427c79 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/formlayout/HtmlCaptionInFormLayout.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.formlayout; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.FormLayout; +import com.vaadin.ui.TextField; + +public class HtmlCaptionInFormLayout extends AbstractTestUI { + @Override + protected void setup(VaadinRequest request) { + final TextField asHtml = new TextField("Contains HTML"); + asHtml.setCaptionAsHtml(true); + + final TextField asText = new TextField("Contains HTML"); + + addComponent(new FormLayout(asHtml, asText)); + + addComponent(new Button("Toggle", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + asHtml.setCaptionAsHtml(!asHtml.isCaptionAsHtml()); + asText.setCaptionAsHtml(!asText.isCaptionAsHtml()); + } + })); + } +} diff --git a/uitest/src/com/vaadin/tests/components/formlayout/HtmlCaptionInFormLayoutTest.java b/uitest/src/com/vaadin/tests/components/formlayout/HtmlCaptionInFormLayoutTest.java new file mode 100644 index 0000000000..95130e8a0c --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/formlayout/HtmlCaptionInFormLayoutTest.java @@ -0,0 +1,59 @@ +/* + * 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.formlayout; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class HtmlCaptionInFormLayoutTest extends SingleBrowserTest { + @Test + public void testHtmlCaptions() { + openTestURL(); + + List captions = getDriver().findElements( + By.cssSelector(".v-formlayout-captioncell span")); + + Assert.assertEquals("Should be two formlayout captions", 2, + captions.size()); + + Assert.assertEquals("Contains HTML", captions.get(0).getText()); + Assert.assertEquals("Contains HTML", captions.get(1).getText()); + } + + @Test + public void testHtmlCaptionToggle() { + openTestURL(); + + $(ButtonElement.class).caption("Toggle").first().click(); + + List captions = getDriver().findElements( + By.cssSelector(".v-formlayout-captioncell span")); + + Assert.assertEquals("Should be two formlayout captions", 2, + captions.size()); + + Assert.assertEquals("Contains HTML", captions.get(0).getText()); + Assert.assertEquals("Contains HTML", captions.get(1).getText()); + } + +} -- cgit v1.2.3 From bdc28f77c6c629eec0a0129a1a791855a6fc435d Mon Sep 17 00:00:00 2001 From: Pekka Hyvönen Date: Wed, 6 May 2015 11:52:47 +0300 Subject: Wrong floating element pos. on DND column reorder Grid #17693 When Grid was wider, the floating element did follow mouse to the right after some point. Also makes sure floating element is not shown on top of frozen columns when auto scrolling left. Change-Id: Ied779222c484f1f22119f89c0e720f868bbc898e --- client/src/com/vaadin/client/widgets/Grid.java | 18 +++++++------- .../server/GridColumnReorderTest.java | 28 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 8 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 92827c47f0..07074eeddf 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -3541,24 +3541,26 @@ public class Grid extends ResizeComposite implements private void resolveDragElementHorizontalPosition(final int clientX) { double left = clientX - table.getAbsoluteLeft(); - final double frozenColumnsWidth = getFrozenColumnsWidth(); - if (left < frozenColumnsWidth) { - left = (int) frozenColumnsWidth; - } - // do not show the drag element beyond a spanned header cell + // Do not show the drag element beyond a spanned header cell // limitation final Double leftBound = possibleDropPositions.firstKey(); final Double rightBound = possibleDropPositions.lastKey(); - double scrollLeft = getScrollLeft(); + final double scrollLeft = getScrollLeft(); if (left + scrollLeft < leftBound) { left = leftBound - scrollLeft + autoScrollX; } else if (left + scrollLeft > rightBound) { left = rightBound - scrollLeft + autoScrollX; } - // do not show the drag element beyond the grid - left = Math.max(0, Math.min(left, table.getClientWidth())); + // Do not show the drag element beyond the grid + final int bodyOffsetWidth = getEscalator().getBody().getElement() + .getOffsetWidth(); + // Do not show on left of the frozen columns (even if scrolled) + final int frozenColumnsWidth = (int) getFrozenColumnsWidth(); + + left = Math + .max(frozenColumnsWidth, Math.min(left, bodyOffsetWidth)); left -= dragElement.getClientWidth() / 2; dragElement.getStyle().setLeft(left, Unit.PX); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java index 0d62797ea4..1714cdaaf3 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java @@ -22,8 +22,12 @@ import java.util.List; import org.junit.Before; import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; import com.vaadin.testbench.TestBenchElement; +import com.vaadin.testbench.elements.GridElement.GridCellElement; import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; /** @@ -320,6 +324,30 @@ public class GridColumnReorderTest extends GridBasicFeaturesTest { assertColumnHeaderOrder(1, 2, 0, 3); } + @Test + public void testColumnReordering_bigWidth_dragElementPositionCorrect() { + openTestURL(); + toggleColumnReordering(); + selectMenuPath("Component", "Size", "Width", "900px"); + assertColumnHeaderOrder(0, 1, 2, 3); + + GridCellElement draggedHeaderCell = getGridElement() + .getHeaderCell(0, 1); + final int xOffset = 500; + new Actions(getDriver()).moveToElement(draggedHeaderCell, 5, 5) + .clickAndHold().moveByOffset(xOffset, 0).build().perform(); + + WebElement floatingDragElement = findElement(By + .className("dragged-column-header")); + + int expectedLeft = draggedHeaderCell.getLocation().getX() + xOffset + 5 + - (floatingDragElement.getSize().getWidth() / 2); + int realLeft = floatingDragElement.getLocation().getX(); + + assertTrue("Dragged element location wrong, expected " + expectedLeft + + " was " + realLeft, Math.abs(expectedLeft - realLeft) < 5); + } + private void toggleColumnReordering() { selectMenuPath(COLUMN_REORDERING_PATH); } -- cgit v1.2.3 From 8bafe0f91947c9f33b2d22c1595a17fb016bef8e Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Mon, 18 May 2015 13:39:06 +0300 Subject: Ensure VDebugWindow.get() always returns the real instance (#17871) Change-Id: Ia0af0cc3e6c3129a117dd31e6bce54e1226eb9c7 --- client/src/com/vaadin/client/ApplicationConfiguration.java | 2 +- client/src/com/vaadin/client/debug/internal/VDebugWindow.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/ApplicationConfiguration.java b/client/src/com/vaadin/client/ApplicationConfiguration.java index f4b2c93111..0db8dc297e 100644 --- a/client/src/com/vaadin/client/ApplicationConfiguration.java +++ b/client/src/com/vaadin/client/ApplicationConfiguration.java @@ -688,7 +688,7 @@ public class ApplicationConfiguration implements EntryPoint { * cleared up when an API for extending the debug window is * implemented. */ - VDebugWindow window = GWT.create(VDebugWindow.class); + VDebugWindow window = VDebugWindow.get(); if (LogConfiguration.loggingIsEnabled()) { window.addSection((Section) GWT.create(LogSection.class)); diff --git a/client/src/com/vaadin/client/debug/internal/VDebugWindow.java b/client/src/com/vaadin/client/debug/internal/VDebugWindow.java index 3393d7371b..b543c23e4d 100644 --- a/client/src/com/vaadin/client/debug/internal/VDebugWindow.java +++ b/client/src/com/vaadin/client/debug/internal/VDebugWindow.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.Date; import com.google.gwt.core.client.Duration; +import com.google.gwt.core.shared.GWT; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.NativeEvent; import com.google.gwt.dom.client.Style; @@ -174,7 +175,6 @@ public final class VDebugWindow extends VOverlay { */ public VDebugWindow() { super(false, false); - instance = this; getElement().getStyle().setOverflow(Overflow.HIDDEN); setStylePrimaryName(STYLENAME); @@ -255,7 +255,7 @@ public final class VDebugWindow extends VOverlay { */ public static VDebugWindow get() { if (instance == null) { - instance = new VDebugWindow(); + instance = GWT.create(VDebugWindow.class); } return instance; } -- cgit v1.2.3 From 08dfe45d09baffd3cf60d5a65639117f6269aae4 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Thu, 21 May 2015 08:45:20 +0300 Subject: Fix adding a column to Table and immediately changing its size (#17927) Change-Id: I970c771f647b7587aac3985ebeea0f0b20805fec --- client/src/com/vaadin/client/ui/VScrollTable.java | 17 +++--- .../components/table/TableColumnAddAndResize.java | 70 ++++++++++++++++++++++ .../table/TableColumnAddAndResizeTest.java | 41 +++++++++++++ 3 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/table/TableColumnAddAndResize.java create mode 100644 uitest/src/com/vaadin/tests/components/table/TableColumnAddAndResizeTest.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 6a8ce67678..d3958a2f00 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -3659,16 +3659,15 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // Do a more thorough update if a column is resized from // the server *after* the header has been properly // initialized - final int colIx = getColIndexByKey(c.cid); final int newWidth = width; - Scheduler.get().scheduleDeferred( - new ScheduledCommand() { + Scheduler.get().scheduleFinally(new ScheduledCommand() { - @Override - public void execute() { - setColWidth(colIx, newWidth, true); - } - }); + @Override + public void execute() { + final int colIx = getColIndexByKey(cid); + setColWidth(colIx, newWidth, true); + } + }); refreshContentWidths = true; } else { // get min width with no indent or padding @@ -3710,7 +3709,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, if (refreshContentWidths) { // Recalculate the column sizings if any column has changed - Scheduler.get().scheduleDeferred(new ScheduledCommand() { + Scheduler.get().scheduleFinally(new ScheduledCommand() { @Override public void execute() { diff --git a/uitest/src/com/vaadin/tests/components/table/TableColumnAddAndResize.java b/uitest/src/com/vaadin/tests/components/table/TableColumnAddAndResize.java new file mode 100644 index 0000000000..40751047b1 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableColumnAddAndResize.java @@ -0,0 +1,70 @@ +/* + * 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 com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.Table; +import com.vaadin.ui.VerticalLayout; + +public class TableColumnAddAndResize extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + String people[][] = { + { "Galileo", "Liked to go around the Sun" }, + { "Monnier", "Liked star charts" }, + { "VÀisÀlÀ", "Liked optics" }, + { "Oterma", "Liked comets" }, + { + "Valtaoja", + "Likes cosmology and still " + + "lives unlike the others above" }, }; + + VerticalLayout content = new VerticalLayout(); + + final Table table = new Table("Awesome Table"); + table.setSizeFull(); + table.addContainerProperty("Id1", String.class, "TestString"); + table.addContainerProperty("Id2", String.class, "TestString2"); + + for (String[] p : people) { + table.addItem(p); + } + table.setColumnWidth("Id1", 100); + + table.setColumnWidth("Id2", 100); + + table.setVisibleColumns("Id1"); + content.addComponent(table); + Button button = new Button("Add and Resize"); + button.addClickListener(new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + table.setVisibleColumns("Id1", "Id2"); + table.setColumnWidth("Id2", 200); + + } + }); + content.addComponent(button); + addComponent(content); + + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/TableColumnAddAndResizeTest.java b/uitest/src/com/vaadin/tests/components/table/TableColumnAddAndResizeTest.java new file mode 100644 index 0000000000..e42f86a975 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/TableColumnAddAndResizeTest.java @@ -0,0 +1,41 @@ +/* + * 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.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import org.junit.Test; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.NotificationElement; +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TableColumnAddAndResizeTest extends MultiBrowserTest { + + @Test + public void testAddAndResizeColumn() { + setDebug(true); + openTestURL(); + + $(ButtonElement.class).caption("Add and Resize").first().click(); + assertFalse("Error notification present.", $(NotificationElement.class) + .exists()); + assertEquals("Unexpected column width. ", 200, $(TableElement.class) + .first().getCell(0, 1).getSize().getWidth()); + } +} -- cgit v1.2.3 From dab615749386a089afc7965485942f667af154e4 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Fri, 22 May 2015 09:40:14 +0300 Subject: Add pointer to new location for methods moved to WidgetUtil (#17952) Change-Id: I0614f598337eacc647d82068776e934074e3ac29 --- client/src/com/vaadin/client/Util.java | 201 +++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) (limited to 'client') diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java index 197300f549..ccafd874a2 100644 --- a/client/src/com/vaadin/client/Util.java +++ b/client/src/com/vaadin/client/Util.java @@ -51,6 +51,8 @@ public class Util { * * Stops execution on firefox browsers on a breakpoint. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#browserDebugger()} + * instead. */ @Deprecated public static void browserDebugger() { @@ -62,6 +64,9 @@ public class Util { * space bar (because space is considered as char). If return 0 use * getCharCode. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#getKeyCode(KeyEvent)} + * instead. + * * @param event * @return return key code * @since 7.2.4 @@ -78,6 +83,9 @@ public class Util { * TODO fix crossplat issues clientX vs pageX. See quircksmode. Not critical * for vaadin as we scroll div istead of page. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getElementFromPoint(int, int)} instead. + * * @param x * @param y * @return the element at given coordinates @@ -136,6 +144,10 @@ public class Util { return null; } + /** + * @deprecated As of 7.4.0, use {@link WidgetUtil#parseRelativeSize(String)} + * instead. + */ @Deprecated public static float parseRelativeSize(String size) { return WidgetUtil.parseRelativeSize(size); @@ -144,6 +156,9 @@ public class Util { /** * Converts html entities to text. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#escapeHTML(String)} + * instead. + * * @param html * @return escaped string presentation of given html */ @@ -155,6 +170,9 @@ public class Util { /** * Escapes the string so it is safe to write inside an HTML attribute. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#escapeAttribute(String)} + * instead. + * * @param attribute * The string to escape * @return An escaped version of attribute. @@ -169,6 +187,9 @@ public class Util { * * Deprecate this if there appears similar method into GWT someday. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#cloneNode(Element, boolean)} instead. + * * @param element * @param deep * clone child tree also @@ -180,6 +201,11 @@ public class Util { return DOM.asOld(WidgetUtil.cloneNode(element, deep)); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#measureHorizontalPaddingAndBorder(Element, int)} + * instead. + */ @Deprecated public static int measureHorizontalPaddingAndBorder(Element element, int paddingGuess) { @@ -187,6 +213,11 @@ public class Util { paddingGuess); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#measureVerticalPaddingAndBorder(Element, int)} + * instead. + */ @Deprecated public static int measureVerticalPaddingAndBorder(Element element, int paddingGuess) { @@ -194,21 +225,38 @@ public class Util { .measureVerticalPaddingAndBorder(element, paddingGuess); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#measureHorizontalBorder(Element)} instead. + */ @Deprecated public static int measureHorizontalBorder(Element element) { return WidgetUtil.measureHorizontalBorder(element); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#measureVerticalBorder(Element)} instead. + */ @Deprecated public static int measureVerticalBorder(Element element) { return WidgetUtil.measureVerticalBorder(element); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#measureMarginLeft(Element)} instead. + */ @Deprecated public static int measureMarginLeft(Element element) { return WidgetUtil.measureMarginLeft(element); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#setHeightExcludingPaddingAndBorder(Widget, String, int)} + * instead. + */ @Deprecated public static int setHeightExcludingPaddingAndBorder(Widget widget, String height, int paddingBorderGuess) { @@ -216,6 +264,11 @@ public class Util { paddingBorderGuess); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#setWidthExcludingPaddingAndBorder(Widget, String, int)} + * instead. + */ @Deprecated public static int setWidthExcludingPaddingAndBorder(Widget widget, String width, int paddingBorderGuess) { @@ -223,6 +276,11 @@ public class Util { paddingBorderGuess); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#setWidthExcludingPaddingAndBorder(Element, int, int, boolean)} + * instead. + */ @Deprecated public static int setWidthExcludingPaddingAndBorder(Element element, int requestedWidth, int horizontalPaddingBorderGuess, @@ -232,6 +290,11 @@ public class Util { requestedWidthIncludesPaddingBorder); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#setHeightExcludingPaddingAndBorder(Element, int, int, boolean)} + * instead. + */ @Deprecated public static int setHeightExcludingPaddingAndBorder(Element element, int requestedHeight, int verticalPaddingBorderGuess, @@ -241,6 +304,9 @@ public class Util { requestedHeightIncludesPaddingBorder); } + /** + * @deprecated As of 7.4, use {@link Class#getSimpleName()} instead. + */ @Deprecated public static String getSimpleName(Object widget) { if (widget == null) { @@ -251,11 +317,19 @@ public class Util { return name.substring(name.lastIndexOf('.') + 1); } + /** + * @deprecated As of 7.4.0, use {@link WidgetUtil#setFloat(Element, String)} + * instead. + */ @Deprecated public static void setFloat(Element element, String value) { WidgetUtil.setFloat(element, value); } + /** + * @deprecated As of 7.4.0, use {@link WidgetUtil#getNativeScrollbarSize()} + * instead. + */ @Deprecated public static int getNativeScrollbarSize() { return WidgetUtil.getNativeScrollbarSize(); @@ -264,6 +338,10 @@ public class Util { /** * Defers the execution of {@link #runWebkitOverflowAutoFix(Element)} * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#runWebkitOverflowAutoFixDeferred(Element)} + * instead. + * * @since 7.2.6 * @param elem * with overflow auto @@ -278,6 +356,9 @@ public class Util { * * See: our bug #2138 and https://bugs.webkit.org/show_bug.cgi?id=21462 * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#runWebkitOverflowAutoFix(Element)} instead. + * * @param elem * with overflow auto */ @@ -314,6 +395,9 @@ public class Util { return uidl.getBooleanAttribute("cached"); } + /** + * @deprecated As of 7.4.0, use {@link WidgetUtil#alert(String)} instead. + */ @Deprecated public static void alert(String string) { WidgetUtil.alert(string); @@ -345,6 +429,9 @@ public class Util { * Gets the border-box width for the given element, i.e. element width + * border + padding. Always rounds up to nearest integer. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#getRequiredWidth(Element)} + * instead. + * * @param element * The element to check * @return The border-box width for the element @@ -358,6 +445,9 @@ public class Util { * Gets the border-box height for the given element, i.e. element height + * border + padding. Always rounds up to nearest integer. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getRequiredHeight(Element)} instead. + * * @param element * The element to check * @return The border-box height for the element @@ -368,35 +458,63 @@ public class Util { return WidgetUtil.getRequiredHeight(element); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getRequiredWidthBoundingClientRect(Element)} + * instead. + */ @Deprecated public int getRequiredWidthBoundingClientRect( com.google.gwt.dom.client.Element element) { return WidgetUtil.getRequiredWidthBoundingClientRect(element); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getRequiredHeightComputedStyle(Element)} + * instead. + */ @Deprecated public static int getRequiredHeightComputedStyle( com.google.gwt.dom.client.Element element) { return WidgetUtil.getRequiredHeightComputedStyle(element); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getRequiredWidthComputedStyle(Element)} + * instead. + */ @Deprecated public static int getRequiredWidthComputedStyle( com.google.gwt.dom.client.Element element) { return WidgetUtil.getRequiredWidthComputedStyle(element); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getRequiredHeightBoundingClientRect(Element)} + * instead. + */ @Deprecated public static int getRequiredHeightBoundingClientRect( com.google.gwt.dom.client.Element element) { return WidgetUtil.getRequiredHeightBoundingClientRect(element); } + /** + * @deprecated As of 7.4.0, use {@link WidgetUtil#getRequiredWidth(Widget)} + * instead. + */ @Deprecated public static int getRequiredWidth(Widget widget) { return WidgetUtil.getRequiredWidth(widget); } + /** + * @deprecated As of 7.4.0, use {@link WidgetUtil#getRequiredHeight(Widget)} + * instead. + */ @Deprecated public static int getRequiredHeight(Widget widget) { return WidgetUtil.getRequiredHeight(widget); @@ -405,6 +523,9 @@ public class Util { /** * Detects what is currently the overflow style attribute in given element. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#mayHaveScrollBars(Element)} instead. + * * @param pe * the element to detect * @return true if auto or scroll @@ -481,6 +602,8 @@ public class Util { /** * Will (attempt) to focus the given DOM Element. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#focus(Element)} instead. + * * @param el * the element to focus */ @@ -511,6 +634,9 @@ public class Util { * Helper method to find first instance of given Widget type found by * traversing DOM upwards from given element. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#findWidget(Element, Class)} instead. + * * @param element * the element where to start seeking of Widget * @param class1 @@ -525,6 +651,9 @@ public class Util { /** * Force webkit to redraw an element * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#forceWebkitRedraw(Element)} instead. + * * @param element * The element that should be redrawn */ @@ -538,6 +667,9 @@ public class Util { * necessary in cases where IE8 "forgets" to update child elements when they * resize. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#forceIE8Redraw(Element)} + * instead. + * * @param e * The element to perform the hack on */ @@ -551,6 +683,9 @@ public class Util { * necessary in cases where IE "forgets" to update child elements when they * resize. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#forceIERedraw(Element)} + * instead. + * * @since 7.3 * @param e * The element to perform the hack on @@ -566,6 +701,9 @@ public class Util { * * Does nothing if the element is not attached to the DOM. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#detachAttach(Element)} + * instead. + * * @param element * The element to detach and re-attach */ @@ -574,6 +712,10 @@ public class Util { WidgetUtil.detachAttach(element); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#sinkOnloadForImages(Element)} instead. + */ @Deprecated public static void sinkOnloadForImages(Element element) { WidgetUtil.sinkOnloadForImages(element); @@ -582,6 +724,9 @@ public class Util { /** * Returns the index of the childElement within its parent. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getChildElementIndex(Element)} instead. + * * @param subElement * @return */ @@ -656,6 +801,10 @@ public class Util { * resets it to its current value. Used mainly to work around rendering * issues in IE (and possibly in other browsers) * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#setStyleTemporarily(Element, String, String)} + * instead. + * * @param element * The target element * @param styleProperty @@ -674,6 +823,9 @@ public class Util { * position from either first changed touch (if touch event) or from the * event itself. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getTouchOrMouseClientX(Event)} instead. + * * @param event * @return */ @@ -687,6 +839,9 @@ public class Util { * event. Please note that this is not always the same as the target of the * event e.g. if event capture is used. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getElementUnderMouse(NativeEvent)} instead. + * * @param event * the mouse event to get coordinates from * @return the element at the coordinates of the event @@ -702,6 +857,9 @@ public class Util { * position from either first changed touch (if touch event) or from the * event itself. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getTouchOrMouseClientY(Event)} instead. + * * @param event * @return */ @@ -711,6 +869,9 @@ public class Util { } /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getTouchOrMouseClientY(NativeEvent)} + * instead. * * @see #getTouchOrMouseClientY(Event) * @param currentGwtEvent @@ -722,6 +883,10 @@ public class Util { } /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#getTouchOrMouseClientX(NativeEvent)} + * instead. + * * @see #getTouchOrMouseClientX(Event) * * @param event @@ -732,16 +897,29 @@ public class Util { return WidgetUtil.getTouchOrMouseClientX(event); } + /** + * @deprecated As of 7.4.0, use {@link WidgetUtil#isTouchEvent(Event)} + * instead. + */ @Deprecated public static boolean isTouchEvent(Event event) { return WidgetUtil.isTouchEvent(event); } + /** + * @deprecated As of 7.4.0, use {@link WidgetUtil#isTouchEvent(NativeEvent)} + * instead. + */ @Deprecated public static boolean isTouchEvent(NativeEvent event) { return WidgetUtil.isTouchEvent(event); } + /** + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#simulateClickFromTouchEvent(Event, Widget)} + * instead. + */ @Deprecated public static void simulateClickFromTouchEvent(Event touchevent, Widget widget) { @@ -751,6 +929,9 @@ public class Util { /** * Gets the currently focused element. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#getFocusedElement()} + * instead. + * * @return The active element or null if no active element could be found. */ @Deprecated @@ -772,6 +953,9 @@ public class Util { /** * Gets currently focused element and checks if it's editable * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#isFocusedElementEditable()} instead. + * * @since 7.4 * * @return true if focused element is editable @@ -787,6 +971,9 @@ public class Util { * be e.g used to check whether component should react to some events or * not. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#isAttachedAndDisplayed(Widget)} instead. + * * @param widget * @return true if attached and displayed */ @@ -799,6 +986,9 @@ public class Util { * Scrolls an element into view vertically only. Modified version of * Element.scrollIntoView. * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#scrollIntoViewVertically(Element)} instead. + * * @param elem * The element to scroll into view */ @@ -811,6 +1001,10 @@ public class Util { * Checks if the given event is either a touch event or caused by the left * mouse button * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#isTouchEventOrLeftMouseButton(Event)} + * instead. + * * @param event * @return true if the event is a touch event or caused by the left mouse * button, false otherwise @@ -868,6 +1062,9 @@ public class Util { * Resolve a relative URL to an absolute URL based on the current document's * location. * + * @deprecated As of 7.4.0, use {@link WidgetUtil#getAbsoluteUrl(String)} + * instead. + * * @param url * a string with the relative URL to resolve * @return the corresponding absolute URL as a string @@ -885,6 +1082,10 @@ public class Util { * to the start. This makes Firefox work the same way as other browsers * (#13477) * + * @deprecated As of 7.4.0, use + * {@link WidgetUtil#setSelectionRange(Element, int, int, String)} + * instead. + * * @param elem * the html input element. * @param pos -- cgit v1.2.3 From a562635f09cbb9d7a7d550a7429de754609bc384 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Mon, 18 May 2015 23:40:25 +0300 Subject: Only sort when enter is pressed on default header (#16732) Change-Id: I3bae7c341064f26c6be3c9b66b33239716043fec --- client/src/com/vaadin/client/widgets/Grid.java | 9 +++++--- .../grid/basicfeatures/server/GridSortingTest.java | 27 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 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 07074eeddf..53e0566e8d 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -5056,9 +5056,12 @@ public class Grid extends ResizeComposite implements if (event.getNativeKeyCode() != KeyCodes.KEY_ENTER) { return; } - - sorter.sort(event.getFocusedCell().getColumn(), - event.isShiftKeyDown()); + if (getHeader().getRow(event.getFocusedCell().getRowIndex()) + .isDefault()) { + // Only sort for enter on the default header + sorter.sort(event.getFocusedCell().getColumn(), + event.isShiftKeyDown()); + } } }); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java index b06644f0c8..cff8ade054 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java @@ -212,6 +212,33 @@ public class GridSortingTest extends GridBasicFeaturesTest { new Actions(getDriver()).keyUp(key).perform(); } + @Test + public void testKeyboardSortingMultipleHeaders() { + openTestURL(); + selectMenuPath("Component", "Header", "Append row"); + + // Sort according to first column by clicking + getGridElement().getHeaderCell(0, 0).click(); + assertColumnIsSorted(0); + + // Try to sort according to second column by pressing enter on the new + // header + sendKey(Keys.ARROW_RIGHT); + sendKey(Keys.ARROW_DOWN); + sendKey(Keys.ENTER); + + // Should not have sorted + assertColumnIsSorted(0); + + // Sort using default header + sendKey(Keys.ARROW_UP); + sendKey(Keys.ENTER); + + // Should have sorted + assertColumnIsSorted(1); + + } + @Test public void testKeyboardSorting() { openTestURL(); -- cgit v1.2.3 From ac92875a94262e0801052a35b964213f5ee37148 Mon Sep 17 00:00:00 2001 From: Leif Åstrand Date: Fri, 22 May 2015 13:17:28 +0300 Subject: Update active tab index when overriding selection (#15274) Change-Id: I0480b640cec251bb430cdb9224e2a23ea26b7259 --- .../client/ui/tabsheet/TabsheetConnector.java | 1 + .../tests/components/tabsheet/VetoTabChange.java | 50 ++++++++++++++++++++++ .../components/tabsheet/VetoTabChangeTest.java | 47 ++++++++++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 uitest/src/com/vaadin/tests/components/tabsheet/VetoTabChange.java create mode 100644 uitest/src/com/vaadin/tests/components/tabsheet/VetoTabChangeTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java b/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java index 469fc6ba95..1b043c8a51 100644 --- a/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java +++ b/client/src/com/vaadin/client/ui/tabsheet/TabsheetConnector.java @@ -42,6 +42,7 @@ public class TabsheetConnector extends TabsheetBaseConnector implements final boolean selected = key.equals(getState().selected); if (selected) { getWidget().waitingForResponse = false; + getWidget().setActiveTabIndex(i); getWidget().selectTab(i); break; } diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/VetoTabChange.java b/uitest/src/com/vaadin/tests/components/tabsheet/VetoTabChange.java new file mode 100644 index 0000000000..6671b8641d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/VetoTabChange.java @@ -0,0 +1,50 @@ +/* + * 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.tabsheet; + +import com.vaadin.annotations.Theme; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Label; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.TabSheet.SelectedTabChangeEvent; +import com.vaadin.ui.TabSheet.SelectedTabChangeListener; + +@Theme("valo") +public class VetoTabChange extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + final TabSheet ts = new TabSheet(); + ts.addSelectedTabChangeListener(new SelectedTabChangeListener() { + @Override + public void selectedTabChange(SelectedTabChangeEvent event) { + ts.setSelectedTab(0); + } + }); + + ts.addTab(new Label("Tab 1"), "Tab 1"); + ts.addTab(new Label("Tab 2"), "Tab 2"); + + addComponent(ts); + } + + @Override + public String getDescription() { + return "Tests the behavior when there's a listener that always changes back to the first tab."; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/tabsheet/VetoTabChangeTest.java b/uitest/src/com/vaadin/tests/components/tabsheet/VetoTabChangeTest.java new file mode 100644 index 0000000000..a30299f683 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/tabsheet/VetoTabChangeTest.java @@ -0,0 +1,47 @@ +/* + * 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.tabsheet; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.testbench.elements.TabSheetElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class VetoTabChangeTest extends SingleBrowserTest { + @Test + public void testReselectTabAfterVeto() { + openTestURL(); + + TabSheetElement tabSheet = $(TabSheetElement.class).first(); + Assert.assertEquals("Tab 1 should be there by default", "Tab 1", + getTabContent(tabSheet)); + + tabSheet.openTab(1); + + Assert.assertEquals("Tab should not have changed", "Tab 1", + getTabContent(tabSheet)); + + tabSheet.openTab(0); + Assert.assertEquals("Tab should still be there", "Tab 1", + getTabContent(tabSheet)); + } + + private String getTabContent(TabSheetElement tabSheet) { + return tabSheet.getContent(LabelElement.class).getText(); + } +} -- cgit v1.2.3 From 0a7b430d50dc8d82e2ca23296381939a7f444846 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Tue, 26 May 2015 15:44:25 +0300 Subject: Use GWT.create instead of new in Grid client-side (#18011) Change-Id: I34db328092965e0dd8c63c9e65504b637a3fa9e5 --- client/src/com/vaadin/client/widgets/Grid.java | 6 +++--- 1 file changed, 3 insertions(+), 3 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 53e0566e8d..50bc778736 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -3854,7 +3854,7 @@ public class Grid extends ResizeComposite implements @Override protected SelectionModel createModel() { - return new SelectionModelSingle(); + return GWT.create(SelectionModelSingle.class); } }, @@ -3865,7 +3865,7 @@ public class Grid extends ResizeComposite implements @Override protected SelectionModel createModel() { - return new SelectionModelMulti(); + return GWT.create(SelectionModelMulti.class); } }, @@ -3876,7 +3876,7 @@ public class Grid extends ResizeComposite implements @Override protected SelectionModel createModel() { - return new SelectionModelNone(); + return GWT.create(SelectionModelNone.class); } }; -- cgit v1.2.3 From a95f757546892a855def121ec5ce5e5bda927a29 Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Mon, 25 May 2015 15:14:39 +0300 Subject: Fix Grid client-side event support (#17986) Added a public API to get an EventCellReference for the most recent fired event. Also EventCellReference now contains information on Grid section and some related helpers. Change-Id: Ia8a166da6f322084d65f9b1cb242e22b0e66e53b --- .../vaadin/client/renderers/ClickableRenderer.java | 5 +- .../client/widget/grid/EventCellReference.java | 62 ++++++++++++++++++-- client/src/com/vaadin/client/widgets/Grid.java | 29 +++++++++- .../client/GridClientContextMenuEventTest.java | 67 ++++++++++++++++++++++ .../client/grid/GridBasicClientFeaturesWidget.java | 44 ++++++++++++++ 5 files changed, 201 insertions(+), 6 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientContextMenuEventTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/renderers/ClickableRenderer.java b/client/src/com/vaadin/client/renderers/ClickableRenderer.java index f5368d31c9..83059f8f01 100644 --- a/client/src/com/vaadin/client/renderers/ClickableRenderer.java +++ b/client/src/com/vaadin/client/renderers/ClickableRenderer.java @@ -33,6 +33,7 @@ import com.vaadin.client.widget.grid.CellReference; import com.vaadin.client.widget.grid.EventCellReference; import com.vaadin.client.widgets.Escalator; import com.vaadin.client.widgets.Grid; +import com.vaadin.client.widgets.Grid.Section; /** * An abstract superclass for renderers that render clickable widgets. Click @@ -152,7 +153,9 @@ public abstract class ClickableRenderer extends Cell cell = container.getCell(e); EventCellReference cellReference = new EventCellReference( grid); - cellReference.set(cell); + // FIXME: Section is currently always body. Might be useful for the + // future to have an actual check. + cellReference.set(cell, Section.BODY); return cellReference; } diff --git a/client/src/com/vaadin/client/widget/grid/EventCellReference.java b/client/src/com/vaadin/client/widget/grid/EventCellReference.java index 7ca1d5de75..98878339d1 100644 --- a/client/src/com/vaadin/client/widget/grid/EventCellReference.java +++ b/client/src/com/vaadin/client/widget/grid/EventCellReference.java @@ -19,6 +19,7 @@ import com.google.gwt.dom.client.TableCellElement; import com.vaadin.client.widget.escalator.Cell; import com.vaadin.client.widgets.Grid; import com.vaadin.client.widgets.Grid.Column; +import com.vaadin.client.widgets.Grid.Section; /** * A data class which contains information which identifies a cell being the @@ -33,12 +34,11 @@ import com.vaadin.client.widgets.Grid.Column; */ public class EventCellReference extends CellReference { - private Grid grid; + private Section section; private TableCellElement element; public EventCellReference(Grid grid) { super(new RowReference(grid)); - this.grid = grid; } /** @@ -47,22 +47,76 @@ public class EventCellReference extends CellReference { * @param targetCell * cell to point to */ - public void set(Cell targetCell) { + public void set(Cell targetCell, Section section) { + Grid grid = getGrid(); int row = targetCell.getRow(); int columnIndexDOM = targetCell.getColumn(); Column column = grid.getVisibleColumns().get(columnIndexDOM); + // Row objects only make sense for body section of Grid. + T rowObject; + if (section == Section.BODY) { + rowObject = grid.getDataSource().getRow(row); + } else { + rowObject = null; + } + // At least for now we don't need to have the actual TableRowElement // available. - getRowReference().set(row, grid.getDataSource().getRow(row), null); + getRowReference().set(row, rowObject, null); + int columnIndex = grid.getColumns().indexOf(column); set(columnIndexDOM, columnIndex, column); this.element = targetCell.getElement(); + this.section = section; } @Override public TableCellElement getElement() { return element; } + + /** + * Is the cell reference for a cell in the header of the Grid. + * + * @since + * @return true if referenced cell is in the header, + * false if not + */ + public boolean isHeader() { + return section == Section.HEADER; + } + + /** + * Is the cell reference for a cell in the body of the Grid. + * + * @since + * @return true if referenced cell is in the body, + * false if not + */ + public boolean isBody() { + return section == Section.BODY; + } + + /** + * Is the cell reference for a cell in the footer of the Grid. + * + * @since + * @return true if referenced cell is in the footer, + * false if not + */ + public boolean isFooter() { + return section == Section.FOOTER; + } + + /** + * Gets the Grid section where the referenced cell is. + * + * @since + * @return grid section + */ + public Section getSection() { + return section; + } } diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index 50bc778736..f1edefc8ba 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -6202,7 +6202,7 @@ public class Grid extends ResizeComposite implements assert cell != null : "received " + eventType + "-event with a null cell target"; - eventCell.set(cell); + eventCell.set(cell, getSectionFromContainer(container)); // Editor can steal focus from Grid and is still handled if (handleEditorEvent(event, container)) { @@ -6237,6 +6237,20 @@ public class Grid extends ResizeComposite implements } } + private Section getSectionFromContainer(RowContainer container) { + assert container != null : "RowContainer should not be null"; + + if (container == escalator.getBody()) { + return Section.BODY; + } else if (container == escalator.getFooter()) { + return Section.FOOTER; + } else if (container == escalator.getHeader()) { + return Section.HEADER; + } + assert false : "RowContainer was not header, footer or body."; + return null; + } + private boolean isOrContainsInSpacer(Node node) { Node n = node; while (n != null && n != getElement()) { @@ -7780,4 +7794,17 @@ public class Grid extends ResizeComposite implements sidebar.close(); } } + + /** + * Returns the {@link EventCellReference} for the latest event fired from + * this Grid. + *

+ * Note: This cell reference will be updated when firing the next event. + * + * @since + * @return event cell reference + */ + public EventCellReference getEventCell() { + return eventCell; + } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientContextMenuEventTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientContextMenuEventTest.java new file mode 100644 index 0000000000..b7242c87be --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientContextMenuEventTest.java @@ -0,0 +1,67 @@ +/* + * 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.basicfeatures.client; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; + +public class GridClientContextMenuEventTest extends GridBasicClientFeaturesTest { + + @Override + public List getBrowsersToTest() { + // PhantomJS doesn't support context click.. + return getBrowsersExcludingPhantomJS(); + } + + @Test + public void testContextMenuEventIsHandledCorrectly() { + setDebug(true); + openTestURL(); + + selectMenuPath("Component", "Internals", "Listeners", + "Add context menu listener"); + + openDebugLogTab(); + clearDebugMessages(); + + new Actions(getDriver()) + .moveToElement(getGridElement().getCell(0, 0), 5, 5) + .contextClick().perform(); + + assertTrue( + "Debug log was not visible", + isElementPresent(By + .xpath("//span[text() = 'Prevented opening a context menu in grid body']"))); + + new Actions(getDriver()) + .moveToElement(getGridElement().getHeaderCell(0, 0), 5, 5) + .contextClick().perform(); + + assertTrue( + "Debug log was not visible", + isElementPresent(By + .xpath("//span[text() = 'Prevented opening a context menu in grid header']"))); + + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java index 81f000c44e..12c2443c01 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java @@ -28,7 +28,10 @@ import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.dom.client.ContextMenuEvent; +import com.google.gwt.event.dom.client.ContextMenuHandler; import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; @@ -52,6 +55,7 @@ import com.vaadin.client.widget.grid.CellReference; import com.vaadin.client.widget.grid.CellStyleGenerator; import com.vaadin.client.widget.grid.DetailsGenerator; import com.vaadin.client.widget.grid.EditorHandler; +import com.vaadin.client.widget.grid.EventCellReference; import com.vaadin.client.widget.grid.RendererCellReference; import com.vaadin.client.widget.grid.RowReference; import com.vaadin.client.widget.grid.RowStyleGenerator; @@ -521,6 +525,46 @@ public class GridBasicClientFeaturesWidget extends .addColumnVisibilityChangeHandler(handler); } }, listenersPath); + addMenuCommand("Add context menu listener", new ScheduledCommand() { + + HandlerRegistration handler = null; + ContextMenuHandler contextMenuHandler = new ContextMenuHandler() { + + @Override + public void onContextMenu(ContextMenuEvent event) { + event.preventDefault(); + final String location; + EventCellReference cellRef = grid + .getEventCell(); + if (cellRef.isHeader()) { + location = "header"; + } else if (cellRef.isBody()) { + location = "body"; + } else if (cellRef.isFooter()) { + location = "footer"; + } else { + location = "somewhere"; + } + + getLogger().info( + "Prevented opening a context menu in grid " + + location); + } + }; + + @Override + public void execute() { + if (handler != null) { + grid.unsinkEvents(Event.ONCONTEXTMENU); + handler.removeHandler(); + } else { + grid.sinkEvents(Event.ONCONTEXTMENU); + handler = grid.addDomHandler(contextMenuHandler, + ContextMenuEvent.getType()); + } + } + + }, listenersPath); } private void createStateMenu() { -- cgit v1.2.3 From 7925e4ce136b98e2807725ffe6ef86f3d40e69bc Mon Sep 17 00:00:00 2001 From: Teemu Suo-Anttila Date: Wed, 27 May 2015 11:07:00 +0300 Subject: Add class name for not editable editor cells (#18021) Change-Id: Ib9bfb1fd3fe2f3caef745aa0d8fad5913759cb9e --- client/src/com/vaadin/client/widgets/Grid.java | 3 +++ .../components/grid/basicfeatures/server/GridEditorTest.java | 10 +++++++++- 2 files changed, 12 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 f1edefc8ba..274daeacb4 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -1105,6 +1105,7 @@ public class Grid extends ResizeComposite implements public static final int KEYCODE_HIDE = KeyCodes.KEY_ESCAPE; private static final String ERROR_CLASS_NAME = "error"; + private static final String NOT_EDITABLE_CLASS_NAME = "not-editable"; protected enum State { INACTIVE, ACTIVATING, BINDING, ACTIVE, SAVING @@ -1488,6 +1489,8 @@ public class Grid extends ResizeComposite implements columnToWidget.put(column, editor); attachWidget(editor, cell); } + } else { + cell.addClassName(NOT_EDITABLE_CLASS_NAME); } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java index 2d9d4018e6..5f42bd66d3 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java @@ -298,8 +298,16 @@ public class GridEditorTest extends GridBasicFeaturesTest { selectMenuPath(EDIT_ITEM_5); assertEditorOpen(); + GridEditorElement editor = getGridElement().getEditor(); assertFalse("Uneditable column should not have an editor widget", - getGridElement().getEditor().isEditable(3)); + editor.isEditable(3)); + assertEquals( + "Not editable cell did not contain correct classname", + "not-editable", + editor.findElement(By.className("v-grid-editor-cells")) + .findElements(By.xpath("./div")).get(3) + .getAttribute("class")); + } private WebElement getSaveButton() { -- cgit v1.2.3 From 7ff6cc3fe73b43ba0ed5603a85bc5e40dafac2ca Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Mon, 25 May 2015 20:27:46 +0300 Subject: Select all checkbox when pressing space on the cell (#16685) Change-Id: I71ca4d7d390bdaf42cf3d9317564e6ad8f96cc25 --- client/src/com/vaadin/client/widgets/Grid.java | 20 +++++++++++++- .../basicfeatures/GridBasicClientFeaturesTest.java | 24 +++++++++++++++++ .../client/GridClientKeyEventsTest.java | 31 ++++++++++++++++++++++ .../client/GridClientSelectionTest.java | 24 ----------------- 4 files changed, 74 insertions(+), 25 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 274daeacb4..383139135e 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -2299,8 +2299,26 @@ public class Grid extends ResizeComposite implements } }); checkBox.setValue(selected); - selectionCell.setWidget(checkBox); + // Select all with space when "select all" cell is active + addHeaderKeyUpHandler(new HeaderKeyUpHandler() { + @Override + public void onKeyUp(GridKeyUpEvent event) { + if (event.getNativeKeyCode() != KeyCodes.KEY_SPACE) { + return; + } + HeaderRow targetHeaderRow = getHeader().getRow( + event.getFocusedCell().getRowIndex()); + if (!targetHeaderRow.isDefault()) { + return; + } + if (event.getFocusedCell().getColumn() == SelectionColumn.this) { + // Send events to ensure row selection state is + // updated + checkBox.setValue(!checkBox.getValue(), true); + } + } + }); } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java index 5d15e53a20..0a1b1735fa 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java @@ -87,4 +87,28 @@ public abstract class GridBasicClientFeaturesTest extends GridBasicFeaturesTest selectMenuPath("Component", "State", "Column Reordering"); } + protected boolean isRowSelected(int index) { + boolean selected = getGridElement().getRow(index).isSelected(); + return selected; + } + + protected void setSelectionModelMulti() { + setSelectionModel("multi"); + } + + protected void setSelectionModelSingle(boolean deselectAllowed) { + String mode = "single"; + if (!deselectAllowed) { + mode += " (no deselect)"; + } + setSelectionModel(mode); + } + + protected void setSelectionModelNone() { + setSelectionModel("none"); + } + + protected void setSelectionModel(String model) { + selectMenuPath("Component", "State", "Selection mode", model); + } } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java index dc4dedd3a0..bb8edee4b5 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.util.Arrays; import java.util.List; +import org.junit.Assert; import org.junit.Test; import org.openqa.selenium.Keys; import org.openqa.selenium.interactions.Actions; @@ -84,6 +85,36 @@ public class GridClientKeyEventsTest extends GridBasicClientFeaturesTest { } } + @Test + public void selectAllUsingKeyboard() { + openTestURL(); + + selectMenuPath("Component", "Header", "Prepend row"); + selectMenuPath("Component", "Header", "Append row"); + selectMenuPath("Component", "State", "Selection mode", "multi"); + + // Focus cell above select all checkbox + getGridElement().getHeaderCell(0, 0).click(); + Assert.assertFalse(isRowSelected(1)); + new Actions(getDriver()).sendKeys(" ").perform(); + Assert.assertFalse(isRowSelected(1)); + + // Move down to select all checkbox cell + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + Assert.assertFalse(isRowSelected(1)); + new Actions(getDriver()).sendKeys(" ").perform(); // select all + Assert.assertTrue(isRowSelected(1)); + new Actions(getDriver()).sendKeys(" ").perform(); // deselect all + Assert.assertFalse(isRowSelected(1)); + + // Move down to header below select all checkbox cell + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + Assert.assertFalse(isRowSelected(1)); + new Actions(getDriver()).sendKeys(" ").perform(); // deselect all + Assert.assertFalse(isRowSelected(1)); + + } + @Test public void testFooterKeyEvents() throws IOException { openTestURL(); diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java index 57950de5e2..a341e39b74 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java @@ -195,28 +195,4 @@ public class GridClientSelectionTest extends GridBasicClientFeaturesTest { isRowSelected(1)); } - private boolean isRowSelected(int index) { - boolean selected = getGridElement().getRow(index).isSelected(); - return selected; - } - - private void setSelectionModelMulti() { - setSelectionModel("multi"); - } - - private void setSelectionModelSingle(boolean deselectAllowed) { - String mode = "single"; - if (!deselectAllowed) { - mode += " (no deselect)"; - } - setSelectionModel(mode); - } - - private void setSelectionModelNone() { - setSelectionModel("none"); - } - - private void setSelectionModel(String model) { - selectMenuPath("Component", "State", "Selection mode", model); - } } -- cgit v1.2.3 From 3b7ddf8aa06379a09ff534ae1a89977164937b89 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 17 Apr 2015 22:36:03 +0300 Subject: Backport a resynchronization fix for 7.5 (#15405) Change-Id: I62178ada54de6a814704dd7e166e9e9e3403c83b --- .../com/vaadin/client/ApplicationConnection.java | 31 ++++++++++++++++++---- .../server/communication/ServerRpcHandler.java | 24 ++++++++++++++++- .../server/communication/UidlRequestHandler.java | 4 ++- .../com/vaadin/shared/ApplicationConstants.java | 5 ++++ 4 files changed, 57 insertions(+), 7 deletions(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index 3a8d69f25a..64511059d9 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -863,7 +863,11 @@ public class ApplicationConnection implements HasHandlers { + ApplicationConstants.UIDL_PATH + '/'); if (extraParams != null && extraParams.length() > 0) { - uri = SharedUtil.addGetParameters(uri, extraParams); + if (extraParams.equals(getRepaintAllParameters())) { + payload.put(ApplicationConstants.RESYNCHRONIZE_ID, true); + } else { + uri = SharedUtil.addGetParameters(uri, extraParams); + } } uri = SharedUtil.addGetParameters(uri, UIConstants.UI_ID_PARAMETER + "=" + configuration.getUIId()); @@ -1550,10 +1554,27 @@ public class ApplicationConnection implements HasHandlers { * e.g. critical server-side notifications */ if (syncId != -1) { - assert (lastSeenServerSyncId == UNDEFINED_SYNC_ID || syncId == lastSeenServerSyncId + 1) : "Newly retrieved server sync id was not exactly one larger than the previous one (new: " - + syncId + ", last seen: " + lastSeenServerSyncId + ")"; - - lastSeenServerSyncId = syncId; + if (lastSeenServerSyncId == UNDEFINED_SYNC_ID + || syncId == (lastSeenServerSyncId + 1)) { + lastSeenServerSyncId = syncId; + } else { + getLogger().warning( + "Expected sync id: " + (lastSeenServerSyncId + 1) + + ", received: " + syncId + + ". Resynchronizing from server."); + lastSeenServerSyncId = syncId; + + // Copied from below... + ValueMap meta = json.getValueMap("meta"); + if (meta == null || !meta.containsKey("async")) { + // End the request if the received message was a + // response, not sent asynchronously + endRequest(); + } + resumeResponseHandling(lock); + repaintAll(); + return; + } } } else { syncId = -1; diff --git a/server/src/com/vaadin/server/communication/ServerRpcHandler.java b/server/src/com/vaadin/server/communication/ServerRpcHandler.java index 450c11f5c4..65fb144810 100644 --- a/server/src/com/vaadin/server/communication/ServerRpcHandler.java +++ b/server/src/com/vaadin/server/communication/ServerRpcHandler.java @@ -76,13 +76,14 @@ public class ServerRpcHandler implements Serializable { private final JsonArray invocations; private final int syncId; private final JsonObject json; + private final boolean resynchronize; public RpcRequest(String jsonString, VaadinRequest request) { json = JsonUtil.parse(jsonString); JsonValue token = json.get(ApplicationConstants.CSRF_TOKEN); if (token == null) { - this.csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE; + csrfToken = ApplicationConstants.CSRF_TOKEN_DEFAULT_VALUE; } else { String csrfToken = token.asString(); if (csrfToken.equals("")) { @@ -98,6 +99,14 @@ public class ServerRpcHandler implements Serializable { } else { syncId = -1; } + + if (json.hasKey(ApplicationConstants.RESYNCHRONIZE_ID)) { + resynchronize = json + .getBoolean(ApplicationConstants.RESYNCHRONIZE_ID); + } else { + resynchronize = false; + } + invocations = json.getArray(ApplicationConstants.RPC_INVOCATIONS); } @@ -130,6 +139,15 @@ public class ServerRpcHandler implements Serializable { return syncId; } + /** + * Checks if this is a request to resynchronize the client side + * + * @return true if this is a resynchronization request, false otherwise + */ + public boolean isResynchronize() { + return resynchronize; + } + /** * Gets the entire request in JSON format, as it was received from the * client. @@ -186,6 +204,10 @@ public class ServerRpcHandler implements Serializable { ui.getConnectorTracker().cleanConcurrentlyRemovedConnectorIds( rpcRequest.getSyncId()); + + if (rpcRequest.isResynchronize()) { + ui.getSession().getCommunicationManager().repaintAll(ui); + } } /** diff --git a/server/src/com/vaadin/server/communication/UidlRequestHandler.java b/server/src/com/vaadin/server/communication/UidlRequestHandler.java index 6e338c5773..33a3669b7f 100644 --- a/server/src/com/vaadin/server/communication/UidlRequestHandler.java +++ b/server/src/com/vaadin/server/communication/UidlRequestHandler.java @@ -80,10 +80,12 @@ public class UidlRequestHandler extends SynchronizedRequestHandler implements // repaint requested or session has timed out and new one is created boolean repaintAll; - // TODO PUSH repaintAll, analyzeLayouts should be + // TODO PUSH analyzeLayouts should be // part of the message payload to make the functionality transport // agnostic + // Resynchronize is sent in the payload but will still support the + // parameter also for compatibility reasons repaintAll = (request .getParameter(ApplicationConstants.URL_PARAMETER_REPAINT_ALL) != null); diff --git a/shared/src/com/vaadin/shared/ApplicationConstants.java b/shared/src/com/vaadin/shared/ApplicationConstants.java index 37bf5c8a00..3431387b77 100644 --- a/shared/src/com/vaadin/shared/ApplicationConstants.java +++ b/shared/src/com/vaadin/shared/ApplicationConstants.java @@ -137,4 +137,9 @@ public class ApplicationConstants implements Serializable { */ public static final String CSRF_TOKEN_DEFAULT_VALUE = "init"; + /** + * The name of the parameter used for re-synchronizing. + */ + public static final String RESYNCHRONIZE_ID = "resynchronize"; + } -- cgit v1.2.3 From 9f6cfbce67583dd5c5133d1de5c1fedc58916de0 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Fri, 22 May 2015 20:38:35 +0300 Subject: Show declarative output for component selected in debug window (#17960) Change-Id: I975eef2f06db4395925f76e40c044078028b0e66 --- .../client/debug/internal/HierarchySection.java | 141 ++++++++++++++++++--- .../src/com/vaadin/client/debug/internal/Icon.java | 2 + .../vaadin/client/debug/internal/theme/font.eot | Bin 7388 -> 7752 bytes .../vaadin/client/debug/internal/theme/font.svg | 1 + .../vaadin/client/debug/internal/theme/font.ttf | Bin 7224 -> 7588 bytes .../vaadin/client/debug/internal/theme/font.woff | Bin 7300 -> 7664 bytes .../src/com/vaadin/client/ui/ui/UIConnector.java | 13 +- server/src/com/vaadin/ui/UI.java | 29 +++++ .../vaadin/shared/ui/ui/DebugWindowServerRpc.java | 10 ++ 9 files changed, 177 insertions(+), 19 deletions(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/debug/internal/HierarchySection.java b/client/src/com/vaadin/client/debug/internal/HierarchySection.java index c772a9d267..ffb4042e69 100644 --- a/client/src/com/vaadin/client/debug/internal/HierarchySection.java +++ b/client/src/com/vaadin/client/debug/internal/HierarchySection.java @@ -66,9 +66,69 @@ public class HierarchySection implements Section { "Show used connectors and how to optimize widgetset"); private final Button showHierarchy = new DebugButton(Icon.HIERARCHY, "Show the connector hierarchy tree"); + private final Button generateDesign = new DebugButton(Icon.SHOW_DESIGN, + "Generate a declarative design for the given component sub tree"); private HandlerRegistration highlightModeRegistration = null; + public interface FindHandler { + + /** + * Called when the user hovers over a connector, which is highlighted. + * Also called when hovering outside the tree, e.g. over the debug + * console, but in this case the connector is null + * + * @param connector + */ + void onHover(ComponentConnector connector); + + /** + * Called when the user clicks on a highlighted connector. + * + * @param connector + */ + void onSelected(ComponentConnector connector); + + } + + private FindHandler inspectComponent = new FindHandler() { + + @Override + public void onHover(ComponentConnector connector) { + if (connector == null) { + infoPanel.clear(); + } else { + printState(connector, false); + } + } + + @Override + public void onSelected(ComponentConnector connector) { + stopFind(); + printState(connector, true); + } + + }; + private FindHandler showComponentDesign = new FindHandler() { + + @Override + public void onHover(ComponentConnector connector) { + Highlight.showOnly(connector); + } + + @Override + public void onSelected(ComponentConnector connector) { + stopFind(); + connector.getConnection().getUIConnector() + .showServerDesign(connector); + content.setWidget(new HTML( + "Design file for component sent to server log")); + } + + }; + + private FindHandler activeFindHandler; + public HierarchySection() { controls.add(showHierarchy); showHierarchy.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON); @@ -84,7 +144,7 @@ public class HierarchySection implements Section { find.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { - toggleFind(); + toggleFind(inspectComponent); } }); @@ -107,6 +167,17 @@ public class HierarchySection implements Section { } }); + controls.add(generateDesign); + generateDesign.setStylePrimaryName(VDebugWindow.STYLENAME_BUTTON); + generateDesign.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + content.setWidget(new HTML( + "Select a layout or component to generate the declarative design")); + toggleFind(showComponentDesign); + } + }); + hierarchyPanel.addListener(new SelectConnectorListener() { @Override public void select(ServerConnector connector, Element element) { @@ -132,7 +203,8 @@ public class HierarchySection implements Section { + showHierarchy.getTitle() + "
" + find.getHTML() + " " + find.getTitle() + "
" + analyze.getHTML() + " " + analyze.getTitle() + "
" + generateWS.getHTML() + " " - + generateWS.getTitle() + "
"); + + generateWS.getTitle() + "
" + generateDesign.getHTML() + + " " + generateDesign.getTitle() + "
"); info.setStyleName(VDebugWindow.STYLENAME + "-info"); helpPanel.add(info); } @@ -189,33 +261,62 @@ public class HierarchySection implements Section { // NOP } + private boolean isFindMode(FindHandler handler) { + return activeFindHandler == handler; + } + private boolean isFindMode() { - return (highlightModeRegistration != null); + return (activeFindHandler != null); } - private void toggleFind() { + private void toggleFind(FindHandler handler) { if (isFindMode()) { - stopFind(); + // Currently finding something + if (isFindMode(handler)) { + // Toggle off, stop finding + stopFind(); + return; + } else { + // Stop finding something else, start finding this + stopFind(); + startFind(handler); + } } else { - startFind(); + // Not currently finding anything + startFind(handler); } } - private void startFind() { + private void startFind(FindHandler handler) { + if (isFindMode()) { + stopFind(); + } Highlight.hideAll(); - if (!isFindMode()) { - highlightModeRegistration = Event - .addNativePreviewHandler(highlightModeHandler); + + highlightModeRegistration = Event + .addNativePreviewHandler(highlightModeHandler); + activeFindHandler = handler; + if (handler == inspectComponent) { find.addStyleDependentName(VDebugWindow.STYLENAME_ACTIVE); + } else if (handler == showComponentDesign) { + generateDesign.addStyleDependentName(VDebugWindow.STYLENAME_ACTIVE); } + } + /** + * Stop any current find operation, regardless of the handler + */ private void stopFind() { - if (isFindMode()) { - highlightModeRegistration.removeHandler(); - highlightModeRegistration = null; - find.removeStyleDependentName(VDebugWindow.STYLENAME_ACTIVE); + if (!isFindMode()) { + return; } + + highlightModeRegistration.removeHandler(); + highlightModeRegistration = null; + find.removeStyleDependentName(VDebugWindow.STYLENAME_ACTIVE); + generateDesign.removeStyleDependentName(VDebugWindow.STYLENAME_ACTIVE); + activeFindHandler = null; } private void printState(ServerConnector connector, boolean serverDebug) { @@ -244,7 +345,9 @@ public class HierarchySection implements Section { Element eventTarget = WidgetUtil.getElementFromPoint(event .getNativeEvent().getClientX(), event.getNativeEvent() .getClientY()); + if (VDebugWindow.get().getElement().isOrHasChild(eventTarget)) { + // Do not prevent using debug window controls infoPanel.clear(); return; } @@ -258,21 +361,21 @@ public class HierarchySection implements Section { RootPanel.get(), eventTarget); } if (connector != null) { - printState(connector, false); + activeFindHandler.onHover(connector); event.cancel(); event.consume(); event.getNativeEvent().stopPropagation(); return; } } - infoPanel.clear(); + // Not over any connector + activeFindHandler.onHover(null); } if (event.getTypeInt() == Event.ONCLICK) { Highlight.hideAll(); event.cancel(); event.consume(); event.getNativeEvent().stopPropagation(); - stopFind(); Element eventTarget = WidgetUtil.getElementFromPoint(event .getNativeEvent().getClientX(), event.getNativeEvent() .getClientY()); @@ -286,10 +389,12 @@ public class HierarchySection implements Section { } if (connector != null) { - printState(connector, true); + activeFindHandler.onSelected(connector); return; } } + // Click on something else -> stop find operation + stopFind(); } event.cancel(); } diff --git a/client/src/com/vaadin/client/debug/internal/Icon.java b/client/src/com/vaadin/client/debug/internal/Icon.java index d05eca2f6f..a30dc05fcb 100644 --- a/client/src/com/vaadin/client/debug/internal/Icon.java +++ b/client/src/com/vaadin/client/debug/internal/Icon.java @@ -18,6 +18,7 @@ package com.vaadin.client.debug.internal; public enum Icon { + // Font can be updated using e.g. http://icomoon.io/ SEARCH(""), // OK(""), // REMOVE(""), // @@ -46,6 +47,7 @@ public enum Icon { RESET(""), // PERSIST(""), // TESTBENCH(""), // + SHOW_DESIGN(""), // ; private String id; diff --git a/client/src/com/vaadin/client/debug/internal/theme/font.eot b/client/src/com/vaadin/client/debug/internal/theme/font.eot index cf38942e0a..0244d9afcc 100755 Binary files a/client/src/com/vaadin/client/debug/internal/theme/font.eot and b/client/src/com/vaadin/client/debug/internal/theme/font.eot differ diff --git a/client/src/com/vaadin/client/debug/internal/theme/font.svg b/client/src/com/vaadin/client/debug/internal/theme/font.svg index c5a97a6c8b..313645c78f 100755 --- a/client/src/com/vaadin/client/debug/internal/theme/font.svg +++ b/client/src/com/vaadin/client/debug/internal/theme/font.svg @@ -33,4 +33,5 @@ + \ No newline at end of file diff --git a/client/src/com/vaadin/client/debug/internal/theme/font.ttf b/client/src/com/vaadin/client/debug/internal/theme/font.ttf index 734e69ac3f..56ed0cfbff 100755 Binary files a/client/src/com/vaadin/client/debug/internal/theme/font.ttf and b/client/src/com/vaadin/client/debug/internal/theme/font.ttf differ diff --git a/client/src/com/vaadin/client/debug/internal/theme/font.woff b/client/src/com/vaadin/client/debug/internal/theme/font.woff index a9e6d5576b..9f5ed668ec 100755 Binary files a/client/src/com/vaadin/client/debug/internal/theme/font.woff and b/client/src/com/vaadin/client/debug/internal/theme/font.woff differ diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index e7c252f26a..26ccff1191 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -810,6 +810,18 @@ public class UIConnector extends AbstractSingleComponentContainerConnector serverConnector); } + /** + * Sends a request to the server to print a design to the console for the + * given component. + * + * @since + * @param connector + * the component connector to output a declarative design for + */ + public void showServerDesign(ServerConnector connector) { + getRpcProxy(DebugWindowServerRpc.class).showServerDesign(connector); + } + @OnStateChange("theme") void onThemeChange() { final String oldTheme = activeTheme; @@ -1061,5 +1073,4 @@ public class UIConnector extends AbstractSingleComponentContainerConnector private static Logger getLogger() { return Logger.getLogger(UIConnector.class.getName()); } - } diff --git a/server/src/com/vaadin/ui/UI.java b/server/src/com/vaadin/ui/UI.java index 8dd600ddd0..b16d7e32d3 100644 --- a/server/src/com/vaadin/ui/UI.java +++ b/server/src/com/vaadin/ui/UI.java @@ -16,6 +16,8 @@ package com.vaadin.ui; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.net.URI; import java.util.ArrayList; import java.util.Collection; @@ -67,6 +69,7 @@ import com.vaadin.shared.ui.ui.UIConstants; import com.vaadin.shared.ui.ui.UIServerRpc; import com.vaadin.shared.ui.ui.UIState; import com.vaadin.ui.Component.Focusable; +import com.vaadin.ui.declarative.Design; import com.vaadin.util.ConnectorHelper; import com.vaadin.util.CurrentInstance; @@ -211,6 +214,32 @@ public abstract class UI extends AbstractSingleComponentContainer implements json.toString()); } + @Override + public void showServerDesign(Connector connector) { + if (!(connector instanceof Component)) { + getLogger().severe( + "Tried to output declarative design for " + connector + + ", which is not a component"); + return; + } + if (connector instanceof UI) { + // We want to see the content of the UI, so we can add it to + // another UI or component container + connector = ((UI) connector).getContent(); + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + Design.write((Component) connector, baos); + getLogger().info( + "Design for " + connector + + " requested from debug window:\n" + + baos.toString("UTF-8")); + } catch (IOException e) { + getLogger().log(Level.WARNING, + "Error producing design for " + connector, e); + } + + } }; /** diff --git a/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java b/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java index cb94a9b081..9ca0a0a1bb 100644 --- a/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java +++ b/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java @@ -47,4 +47,14 @@ public interface DebugWindowServerRpc extends ServerRpc { */ public void analyzeLayouts(); + /** + * Sends a request to the server to print a design to the console for the + * given component. + * + * @since + * @param connector + * the component connector to output a declarative design for + */ + public void showServerDesign(Connector connector); + } -- cgit v1.2.3 From 550bd1e5e42b97de54ebcd02fda17325d52ef67d Mon Sep 17 00:00:00 2001 From: Johannes Dahlström Date: Mon, 25 May 2015 18:05:31 +0300 Subject: Focus the field in the the active cell when manually opening Grid editor Also move focus back to Grid when manually closing the editor. Change-Id: I3ec54c00500ddd3872e7d20109191ac7db8bb950 --- client/src/com/vaadin/client/widgets/Grid.java | 90 +++++++++++++++++----- .../basicfeatures/client/GridEditorClientTest.java | 55 +++++++++++++ .../grid/basicfeatures/server/GridEditorTest.java | 63 ++++++++++++++- .../client/grid/PureGWTTestApplication.java | 1 + 4 files changed, 186 insertions(+), 23 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 383139135e..1fed0574dd 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -74,12 +74,14 @@ import com.google.gwt.user.client.ui.ResizeComposite; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.BrowserInfo; import com.vaadin.client.DeferredWorker; +import com.vaadin.client.Focusable; import com.vaadin.client.WidgetUtil; import com.vaadin.client.data.DataChangeHandler; import com.vaadin.client.data.DataSource; import com.vaadin.client.renderers.ComplexRenderer; import com.vaadin.client.renderers.Renderer; import com.vaadin.client.renderers.WidgetRenderer; +import com.vaadin.client.ui.FocusUtil; import com.vaadin.client.ui.SubPartAware; import com.vaadin.client.ui.dd.DragAndDropHandler; import com.vaadin.client.widget.escalator.Cell; @@ -1131,6 +1133,7 @@ public class Grid extends ResizeComposite implements private boolean enabled = false; private State state = State.INACTIVE; private int rowIndex = -1; + private int columnIndex = -1; private String styleName = null; private HandlerRegistration scrollHandler; @@ -1196,8 +1199,11 @@ public class Grid extends ResizeComposite implements state = State.ACTIVE; bindTimeout.cancel(); - showOverlay(grid.getEscalator().getBody() - .getRowElement(request.getRowIndex())); + assert rowIndex == request.getRowIndex() : "Request row index " + + request.getRowIndex() + + " did not match the saved row index " + rowIndex; + + showOverlay(); } } @@ -1257,17 +1263,33 @@ public class Grid extends ResizeComposite implements } /** - * Opens the editor over the row with the given index. + * Equivalent to {@code editRow(rowIndex, -1)}. + * + * @see #editRow(int, int) + */ + public void editRow(int rowIndex) { + editRow(rowIndex, -1); + } + + /** + * Opens the editor over the row with the given index and attempts to + * focus the editor widget in the given column index. Does not move + * focus if the widget is not focusable or if the column index is -1. * * @param rowIndex * the index of the row to be edited + * @param columnIndex + * the column index of the editor widget that should be + * initially focused or -1 to not set focus * * @throws IllegalStateException * if this editor is not enabled * @throws IllegalStateException * if this editor is already in edit mode + * + * @since */ - public void editRow(int rowIndex) { + public void editRow(int rowIndex, int columnIndex) { if (!enabled) { throw new IllegalStateException( "Cannot edit row: editor is not enabled"); @@ -1278,6 +1300,7 @@ public class Grid extends ResizeComposite implements } this.rowIndex = rowIndex; + this.columnIndex = columnIndex; state = State.ACTIVATING; @@ -1457,15 +1480,31 @@ public class Grid extends ResizeComposite implements } /** - * Opens the editor overlay over the given table row. + * Equivalent to {@code showOverlay()}. The argument is ignored. + * + * @param unused + * ignored argument * - * @param tr - * the row to be edited + * @deprecated As of 7.5, use {@link #showOverlay()} instead. */ - protected void showOverlay(TableRowElement tr) { + @Deprecated + protected void showOverlay(TableRowElement unused) { + showOverlay(); + } + + /** + * Opens the editor overlay over the table row indicated by + * {@link #getRow()}. + * + * @since + */ + protected void showOverlay() { DivElement gridElement = DivElement.as(grid.getElement()); + TableRowElement tr = grid.getEscalator().getBody() + .getRowElement(rowIndex); + scrollHandler = grid.addScrollHandler(new ScrollHandler() { @Override public void onScroll(ScrollEvent event) { @@ -1485,10 +1524,20 @@ public class Grid extends ResizeComposite implements Column column = grid.getVisibleColumn(i); if (column.isEditable()) { Widget editor = getHandler().getWidget(column); + if (editor != null) { columnToWidget.put(column, editor); attachWidget(editor, cell); } + + if (i == columnIndex) { + if (editor instanceof Focusable) { + ((Focusable) editor).focus(); + } else if (editor instanceof com.google.gwt.user.client.ui.Focusable) { + ((com.google.gwt.user.client.ui.Focusable) editor) + .setFocus(true); + } + } } else { cell.addClassName(NOT_EDITABLE_CLASS_NAME); } @@ -1521,7 +1570,7 @@ public class Grid extends ResizeComposite implements // Move message and buttons wrapper on top of cell wrapper if // there is not enough space visible space under and fix the // overlay from the bottom - editorOverlay.appendChild(cellWrapper); + editorOverlay.insertFirst(messageAndButtonsWrapper); int gridHeight = grid.getElement().getOffsetHeight(); editorOverlay.getStyle() .setBottom( @@ -6309,24 +6358,25 @@ public class Grid extends ResizeComposite implements private boolean handleEditorEvent(Event event, RowContainer container) { + final boolean closeEvent = event.getTypeInt() == Event.ONKEYDOWN + && event.getKeyCode() == Editor.KEYCODE_HIDE; + final boolean openEvent = event.getTypeInt() == Event.ONDBLCLICK + || (event.getTypeInt() == Event.ONKEYDOWN && event.getKeyCode() == Editor.KEYCODE_SHOW); + if (editor.getState() != Editor.State.INACTIVE) { - if (event.getTypeInt() == Event.ONKEYDOWN - && event.getKeyCode() == Editor.KEYCODE_HIDE) { + if (closeEvent) { editor.cancel(); + FocusUtil.setFocus(this, true); } return true; } - if (container == escalator.getBody() && editor.isEnabled()) { - if (event.getTypeInt() == Event.ONDBLCLICK) { - editor.editRow(eventCell.getRowIndex()); - return true; - } else if (event.getTypeInt() == Event.ONKEYDOWN - && event.getKeyCode() == Editor.KEYCODE_SHOW) { - editor.editRow(cellFocusHandler.rowWithFocus); - return true; - } + if (container == escalator.getBody() && editor.isEnabled() && openEvent) { + editor.editRow(eventCell.getRowIndex(), + eventCell.getColumnIndexDOM()); + return true; } + return false; } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java index 04f5e1558d..87b0ba17de 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorClientTest.java @@ -33,6 +33,7 @@ import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import com.vaadin.shared.ui.grid.GridConstants; +import com.vaadin.testbench.elements.GridElement.GridCellElement; import com.vaadin.testbench.elements.GridElement.GridEditorElement; import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; @@ -73,6 +74,22 @@ public class GridEditorClientTest extends GridBasicClientFeaturesTest { getGridElement().getCell(200, 0); } + @Test + public void testMouseOpeningClosing() { + + getGridElement().getCell(4, 0).doubleClick(); + assertNotNull(getEditor()); + + getCancelButton().click(); + assertNull(getEditor()); + + // Disable editor + selectMenuPath("Component", "Editor", "Enabled"); + + getGridElement().getCell(4, 0).doubleClick(); + assertNull(getEditor()); + } + @Test public void testKeyboardOpeningClosing() { @@ -219,6 +236,44 @@ public class GridEditorClientTest extends GridBasicClientFeaturesTest { editor.getErrorMessage()); } + @Test + public void testFocusOnMouseOpen() { + + GridCellElement cell = getGridElement().getCell(4, 2); + + cell.doubleClick(); + + WebElement focused = getFocusedElement(); + + assertEquals("", "input", focused.getTagName()); + assertEquals("", cell.getText(), focused.getAttribute("value")); + } + + @Test + public void testFocusOnKeyboardOpen() { + + GridCellElement cell = getGridElement().getCell(4, 2); + + cell.click(); + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + WebElement focused = getFocusedElement(); + + assertEquals("", "input", focused.getTagName()); + assertEquals("", cell.getText(), focused.getAttribute("value")); + } + + @Test + public void testNoFocusOnProgrammaticOpen() { + + selectMenuPath(EDIT_ROW_5); + + WebElement focused = getFocusedElement(); + + // GWT menubar loses focus after clicking a menuitem + assertEquals("Focus should be in body", "body", focused.getTagName()); + } + protected WebElement getSaveButton() { return getEditor().findElement(By.className("v-grid-editor-save")); } diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java index 5f42bd66d3..0c39b3e509 100644 --- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridEditorTest.java @@ -94,6 +94,20 @@ public class GridEditorTest extends GridBasicFeaturesTest { getGridElement().getCell(200, 0); } + @Test + public void testMouseOpeningClosing() { + + getGridElement().getCell(4, 0).doubleClick(); + assertEditorOpen(); + + getCancelButton().click(); + assertEditorClosed(); + + selectMenuPath(TOGGLE_EDIT_ENABLED); + getGridElement().getCell(4, 0).doubleClick(); + assertEditorClosed(); + } + @Test public void testKeyboardOpeningClosing() { @@ -234,7 +248,7 @@ public class GridEditorTest extends GridBasicFeaturesTest { } @Test - public void testNoScrollAfterEditByAPI() { + public void testNoScrollAfterProgrammaticOpen() { int originalScrollPos = getGridVerticalScrollPos(); selectMenuPath(EDIT_ITEM_5); @@ -245,7 +259,7 @@ public class GridEditorTest extends GridBasicFeaturesTest { } @Test - public void testNoScrollAfterEditByMouse() { + public void testNoScrollAfterMouseOpen() { int originalScrollPos = getGridVerticalScrollPos(); GridCellElement cell_5_0 = getGridElement().getCell(5, 0); @@ -257,7 +271,7 @@ public class GridEditorTest extends GridBasicFeaturesTest { } @Test - public void testNoScrollAfterEditByKeyboard() { + public void testNoScrollAfterKeyboardOpen() { int originalScrollPos = getGridVerticalScrollPos(); GridCellElement cell_5_0 = getGridElement().getCell(5, 0); @@ -293,6 +307,49 @@ public class GridEditorTest extends GridBasicFeaturesTest { originalScrollPos, getGridVerticalScrollPos()); } + @Test + public void testFocusOnMouseOpen() { + + GridCellElement cell = getGridElement().getCell(4, 2); + + cell.doubleClick(); + + WebElement focused = getFocusedElement(); + + assertEquals("", "input", focused.getTagName()); + assertEquals("", cell.getText(), focused.getAttribute("value")); + } + + @Test + public void testFocusOnKeyboardOpen() { + + GridCellElement cell = getGridElement().getCell(4, 2); + + cell.click(); + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + WebElement focused = getFocusedElement(); + + assertEquals("", "input", focused.getTagName()); + assertEquals("", cell.getText(), focused.getAttribute("value")); + } + + @Test + public void testNoFocusOnProgrammaticOpen() { + + selectMenuPath(EDIT_ITEM_5); + + WebElement focused = getFocusedElement(); + + assertEquals("Focus should remain in the menu", "menu", + focused.getAttribute("id")); + } + + @Override + protected WebElement getFocusedElement() { + return (WebElement) executeScript("return document.activeElement;"); + } + @Test public void testUneditableColumn() { selectMenuPath(EDIT_ITEM_5); diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java index e9c126f232..bda1a0c33e 100644 --- a/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java @@ -98,6 +98,7 @@ public abstract class PureGWTTestApplication extends DockLayoutPanel private Menu() { title = ""; menubar = new MenuBar(); + menubar.getElement().setId("menu"); children = new ArrayList

(); items = new ArrayList(); } -- cgit v1.2.3 From 96c08cd52e13e6d2ba5fee0580e9c2c7a5091a0f Mon Sep 17 00:00:00 2001 From: Ilia Motornyi Date: Tue, 17 Mar 2015 11:47:53 +0200 Subject: Adds a textual null representation to Grid renderers(#16560) Adds an optional textual value for null to Grid.AbstractRenderer Change-Id: I4998476308e4259306f1774f309968520d8672e5 --- .../client/connectors/ImageRendererConnector.java | 6 +- .../com/vaadin/client/renderers/ImageRenderer.java | 9 +- server/src/com/vaadin/ui/Grid.java | 23 ++- .../ui/renderers/AbstractJavaScriptRenderer.java | 6 +- .../com/vaadin/ui/renderers/ButtonRenderer.java | 38 ++++- .../com/vaadin/ui/renderers/ClickableRenderer.java | 6 +- .../src/com/vaadin/ui/renderers/DateRenderer.java | 91 +++++++++++- .../src/com/vaadin/ui/renderers/HtmlRenderer.java | 21 ++- .../src/com/vaadin/ui/renderers/ImageRenderer.java | 4 +- .../com/vaadin/ui/renderers/NumberRenderer.java | 77 +++++++--- .../vaadin/ui/renderers/ProgressBarRenderer.java | 8 +- .../src/com/vaadin/ui/renderers/TextRenderer.java | 17 ++- .../vaadin/tests/server/renderer/RendererTest.java | 161 ++++++++++++++------- .../tests/components/grid/IntArrayRenderer.java | 2 +- .../tests/components/grid/MyBeanJSRenderer.java | 2 +- .../tests/components/grid/NullRenderers.java | 131 +++++++++++++++++ .../tests/components/grid/NullRenderersTest.java | 65 +++++++++ .../tests/components/grid/RowAwareRenderer.java | 2 +- 18 files changed, 568 insertions(+), 101 deletions(-) create mode 100644 uitest/src/com/vaadin/tests/components/grid/NullRenderers.java create mode 100644 uitest/src/com/vaadin/tests/components/grid/NullRenderersTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/connectors/ImageRendererConnector.java b/client/src/com/vaadin/client/connectors/ImageRendererConnector.java index ef54daaaa1..f7690cb6fe 100644 --- a/client/src/com/vaadin/client/connectors/ImageRendererConnector.java +++ b/client/src/com/vaadin/client/connectors/ImageRendererConnector.java @@ -42,9 +42,11 @@ public class ImageRendererConnector extends ClickableRendererConnector { @Override public String decode(JsonValue value) { - return ((URLReference) JsonDecoder.decodeValue( + URLReference reference = (URLReference) JsonDecoder.decodeValue( TypeDataStore.getType(URLReference.class), value, null, - getConnection())).getURL(); + getConnection()); + + return reference != null ? reference.getURL() : null; } @Override diff --git a/client/src/com/vaadin/client/renderers/ImageRenderer.java b/client/src/com/vaadin/client/renderers/ImageRenderer.java index b1e8ce5702..9e61e60919 100644 --- a/client/src/com/vaadin/client/renderers/ImageRenderer.java +++ b/client/src/com/vaadin/client/renderers/ImageRenderer.java @@ -29,6 +29,8 @@ import com.vaadin.client.widget.grid.RendererCellReference; */ public class ImageRenderer extends ClickableRenderer { + public static final String TRANSPARENT_GIF_1PX = "data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs="; + @Override public Image createWidget() { Image image = GWT.create(Image.class); @@ -38,6 +40,11 @@ public class ImageRenderer extends ClickableRenderer { @Override public void render(RendererCellReference cell, String url, Image image) { - image.setUrl(url); + if (url == null) { + image.setUrl(TRANSPARENT_GIF_1PX); + } + else { + image.setUrl(url); + } } } diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index 2c7e63ddf8..73d3a91176 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -3286,8 +3286,15 @@ public class Grid extends AbstractComponent implements SelectionNotifier, private final Class presentationType; - protected AbstractRenderer(Class presentationType) { + private final String nullRepresentation; + + protected AbstractRenderer(Class presentationType, String nullRepresentation) { this.presentationType = presentationType; + this.nullRepresentation = nullRepresentation; + } + + protected AbstractRenderer(Class presentationType) { + this(presentationType, null); } /** @@ -3317,7 +3324,19 @@ public class Grid extends AbstractComponent implements SelectionNotifier, @Override public JsonValue encode(T value) { - return encode(value, getPresentationType()); + if (value == null) { + return encode(getNullRepresentation(), String.class); + } else { + return encode(value, getPresentationType()); + } + } + + /** + * Null representation for the renderer + * @return a textual representation of {@code null} + */ + protected String getNullRepresentation() { + return nullRepresentation; } /** diff --git a/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java b/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java index bed34cf6e3..104e07f02f 100644 --- a/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java +++ b/server/src/com/vaadin/ui/renderers/AbstractJavaScriptRenderer.java @@ -105,8 +105,12 @@ public abstract class AbstractJavaScriptRenderer extends AbstractRenderer private JavaScriptCallbackHelper callbackHelper = new JavaScriptCallbackHelper( this); + protected AbstractJavaScriptRenderer(Class presentationType, String nullRepresentation) { + super(presentationType, nullRepresentation); + } + protected AbstractJavaScriptRenderer(Class presentationType) { - super(presentationType); + super(presentationType, null); } @Override diff --git a/server/src/com/vaadin/ui/renderers/ButtonRenderer.java b/server/src/com/vaadin/ui/renderers/ButtonRenderer.java index 0b070d3f69..a747e45713 100644 --- a/server/src/com/vaadin/ui/renderers/ButtonRenderer.java +++ b/server/src/com/vaadin/ui/renderers/ButtonRenderer.java @@ -15,6 +15,8 @@ */ package com.vaadin.ui.renderers; +import elemental.json.JsonValue; + /** * A Renderer that displays a button with a textual caption. The value of the * corresponding property is used as the caption. Click listeners can be added @@ -27,9 +29,12 @@ public class ButtonRenderer extends ClickableRenderer { /** * Creates a new button renderer. + * + * @param nullRepresentation + * the textual representation of {@code null} value */ - public ButtonRenderer() { - super(String.class); + public ButtonRenderer(String nullRepresentation) { + super(String.class, nullRepresentation); } /** @@ -37,9 +42,34 @@ public class ButtonRenderer extends ClickableRenderer { * * @param listener * the click listener to register + * @param nullRepresentation + * the textual representation of {@code null} value */ - public ButtonRenderer(RendererClickListener listener) { - this(); + public ButtonRenderer(RendererClickListener listener, String nullRepresentation) { + this(nullRepresentation); addClickListener(listener); } + + /** + * Creates a new button renderer. + */ + public ButtonRenderer() { + this(""); + } + + /** + * Creates a new button renderer and adds the given click listener to it. + * + * @param listener + * the click listener to register + */ + public ButtonRenderer(RendererClickListener listener) { + this(listener, ""); + } + + @Override + public String getNullRepresentation() { + return super.getNullRepresentation(); + } + } diff --git a/server/src/com/vaadin/ui/renderers/ClickableRenderer.java b/server/src/com/vaadin/ui/renderers/ClickableRenderer.java index 38e9acef9c..01e939bb67 100644 --- a/server/src/com/vaadin/ui/renderers/ClickableRenderer.java +++ b/server/src/com/vaadin/ui/renderers/ClickableRenderer.java @@ -103,7 +103,11 @@ public class ClickableRenderer extends AbstractRenderer { } protected ClickableRenderer(Class presentationType) { - super(presentationType); + this(presentationType, null); + } + + protected ClickableRenderer(Class presentationType, String nullRepresentation) { + super(presentationType, nullRepresentation); registerRpc(new RendererClickRpc() { @Override public void click(String rowKey, String columnId, diff --git a/server/src/com/vaadin/ui/renderers/DateRenderer.java b/server/src/com/vaadin/ui/renderers/DateRenderer.java index 9dd4d19e87..092b3f405e 100644 --- a/server/src/com/vaadin/ui/renderers/DateRenderer.java +++ b/server/src/com/vaadin/ui/renderers/DateRenderer.java @@ -41,7 +41,7 @@ public class DateRenderer extends AbstractRenderer { * representation for the default locale. */ public DateRenderer() { - this(Locale.getDefault()); + this(Locale.getDefault(), ""); } /** @@ -56,7 +56,24 @@ public class DateRenderer extends AbstractRenderer { * if {@code locale} is {@code null} */ public DateRenderer(Locale locale) throws IllegalArgumentException { - this("%s", locale); + this("%s", locale, ""); + } + + /** + * Creates a new date renderer. + *

+ * The renderer is configured to render with the {@link Date#toString()} + * representation for the given locale. + * + * @param locale + * the locale in which to present dates + * @param nullRepresentation + * the textual representation of {@code null} value + * @throws IllegalArgumentException + * if {@code locale} is {@code null} + */ + public DateRenderer(Locale locale, String nullRepresentation) throws IllegalArgumentException { + this("%s", locale, nullRepresentation); } /** @@ -74,7 +91,27 @@ public class DateRenderer extends AbstractRenderer { * String Syntax */ public DateRenderer(String formatString) throws IllegalArgumentException { - this(formatString, Locale.getDefault()); + this(formatString, ""); + } + + /** + * Creates a new date renderer. + *

+ * The renderer is configured to render with the given string format, as + * displayed in the default locale. + * + * @param formatString + * the format string with which to format the date + * @param nullRepresentation + * the textual representation of {@code null} value + * @throws IllegalArgumentException + * if {@code formatString} is {@code null} + * @see Format + * String Syntax + */ + public DateRenderer(String formatString, String nullRepresentation) throws IllegalArgumentException { + this(formatString, Locale.getDefault(), nullRepresentation); } /** @@ -95,7 +132,29 @@ public class DateRenderer extends AbstractRenderer { */ public DateRenderer(String formatString, Locale locale) throws IllegalArgumentException { - super(Date.class); + this(formatString,locale, ""); + } + /** + * Creates a new date renderer. + *

+ * The renderer is configured to render with the given string format, as + * displayed in the given locale. + * + * @param formatString + * the format string to format the date with + * @param locale + * the locale to use + * @param nullRepresentation + * the textual representation of {@code null} value + * @throws IllegalArgumentException + * if either argument is {@code null} + * @see Format + * String Syntax + */ + public DateRenderer(String formatString, Locale locale, String nullRepresentation) + throws IllegalArgumentException { + super(Date.class, nullRepresentation); if (formatString == null) { throw new IllegalArgumentException("format string may not be null"); @@ -121,7 +180,20 @@ public class DateRenderer extends AbstractRenderer { * if {@code dateFormat} is {@code null} */ public DateRenderer(DateFormat dateFormat) throws IllegalArgumentException { - super(Date.class); + this(dateFormat, ""); + } + /** + * Creates a new date renderer. + *

+ * The renderer is configured to render with he given date format. + * + * @param dateFormat + * the date format to use when rendering dates + * @throws IllegalArgumentException + * if {@code dateFormat} is {@code null} + */ + public DateRenderer(DateFormat dateFormat, String nullRepresentation) throws IllegalArgumentException { + super(Date.class, nullRepresentation); if (dateFormat == null) { throw new IllegalArgumentException("date format may not be null"); } @@ -131,10 +203,17 @@ public class DateRenderer extends AbstractRenderer { this.dateFormat = dateFormat; } + @Override + public String getNullRepresentation() { + return super.getNullRepresentation(); + } + @Override public JsonValue encode(Date value) { String dateString; - if (dateFormat != null) { + if (value == null) { + dateString = getNullRepresentation(); + } else if (dateFormat != null) { dateString = dateFormat.format(value); } else { dateString = String.format(locale, formatString, value); diff --git a/server/src/com/vaadin/ui/renderers/HtmlRenderer.java b/server/src/com/vaadin/ui/renderers/HtmlRenderer.java index 34774b3825..df89c60ad2 100644 --- a/server/src/com/vaadin/ui/renderers/HtmlRenderer.java +++ b/server/src/com/vaadin/ui/renderers/HtmlRenderer.java @@ -16,18 +16,33 @@ package com.vaadin.ui.renderers; import com.vaadin.ui.Grid.AbstractRenderer; +import elemental.json.JsonValue; /** * A renderer for presenting HTML content. - * - * @since 7.4 + * * @author Vaadin Ltd + * @since 7.4 */ public class HtmlRenderer extends AbstractRenderer { + /** + * Creates a new HTML renderer. + * + * @param nullRepresentation the html representation of {@code null} value + */ + public HtmlRenderer(String nullRepresentation) { + super(String.class, nullRepresentation); + } + /** * Creates a new HTML renderer. */ public HtmlRenderer() { - super(String.class); + this(""); + } + + @Override + public String getNullRepresentation() { + return super.getNullRepresentation(); } } diff --git a/server/src/com/vaadin/ui/renderers/ImageRenderer.java b/server/src/com/vaadin/ui/renderers/ImageRenderer.java index 4bb3671033..2fb872583e 100644 --- a/server/src/com/vaadin/ui/renderers/ImageRenderer.java +++ b/server/src/com/vaadin/ui/renderers/ImageRenderer.java @@ -39,7 +39,7 @@ public class ImageRenderer extends ClickableRenderer { * Creates a new image renderer. */ public ImageRenderer() { - super(Resource.class); + super(Resource.class, null); } /** @@ -55,7 +55,7 @@ public class ImageRenderer extends ClickableRenderer { @Override public JsonValue encode(Resource resource) { - if (!(resource instanceof ExternalResource || resource instanceof ThemeResource)) { + if (!(resource == null || resource instanceof ExternalResource || resource instanceof ThemeResource)) { throw new IllegalArgumentException( "ImageRenderer only supports ExternalResource and ThemeResource (" + resource.getClass().getSimpleName() + "given )"); diff --git a/server/src/com/vaadin/ui/renderers/NumberRenderer.java b/server/src/com/vaadin/ui/renderers/NumberRenderer.java index 5c30e55b17..1d4d7e0ec9 100644 --- a/server/src/com/vaadin/ui/renderers/NumberRenderer.java +++ b/server/src/com/vaadin/ui/renderers/NumberRenderer.java @@ -24,7 +24,7 @@ import elemental.json.JsonValue; /** * A renderer for presenting number values. - * + * * @since 7.4 * @author Vaadin Ltd */ @@ -35,7 +35,7 @@ public class NumberRenderer extends AbstractRenderer { /** * Creates a new number renderer. - *

+ *

* The renderer is configured to render with the number's natural string * representation in the default locale. */ @@ -45,18 +45,35 @@ public class NumberRenderer extends AbstractRenderer { /** * Creates a new number renderer. - *

+ *

* The renderer is configured to render the number as defined with the given * number format. - * + * * @param numberFormat * the number format with which to display numbers * @throws IllegalArgumentException * if {@code numberFormat} is {@code null} */ - public NumberRenderer(NumberFormat numberFormat) + public NumberRenderer(NumberFormat numberFormat) { + this(numberFormat, ""); + } + + /** + * Creates a new number renderer. + *

+ * The renderer is configured to render the number as defined with the given + * number format. + * + * @param numberFormat + * the number format with which to display numbers + * @param nullRepresentation + * the textual representation of {@code null} value + * @throws IllegalArgumentException + * if {@code numberFormat} is {@code null} + */ + public NumberRenderer(NumberFormat numberFormat, String nullRepresentation) throws IllegalArgumentException { - super(Number.class); + super(Number.class, nullRepresentation); if (numberFormat == null) { throw new IllegalArgumentException("Number format may not be null"); @@ -69,10 +86,10 @@ public class NumberRenderer extends AbstractRenderer { /** * Creates a new number renderer. - *

+ *

* The renderer is configured to render with the number's natural string * representation in the given locale. - * + * * @param locale * the locale in which to display numbers * @throws IllegalArgumentException @@ -84,12 +101,29 @@ public class NumberRenderer extends AbstractRenderer { /** * Creates a new number renderer. - *

- * The renderer is configured to render with the given format string in the - * default locale. - * + *

+ * The renderer is configured to render with the number's natural string + * representation in the given locale. + * * @param formatString * the format string with which to format the number + * @param locale + * the locale in which to display numbers + * @throws IllegalArgumentException + * if {@code locale} is {@code null} + */ + public NumberRenderer(String formatString, Locale locale) throws IllegalArgumentException { + this(formatString, locale, ""); //This will call #toString() during formatting + } + + /** + * Creates a new number renderer. + *

+ * The renderer is configured to render with the given format string in the + * default locale. + * + * @param + * formatString the format string with which to format the number * @throws IllegalArgumentException * if {@code formatString} is {@code null} * @see { * String Syntax */ public NumberRenderer(String formatString) throws IllegalArgumentException { - this(formatString, Locale.getDefault()); + this(formatString, Locale.getDefault(), ""); } /** * Creates a new number renderer. - *

+ *

* The renderer is configured to render with the given format string in the * given locale. - * + * * @param formatString * the format string with which to format the number * @param locale @@ -116,8 +150,8 @@ public class NumberRenderer extends AbstractRenderer { * href="http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html#syntax">Format * String Syntax */ - public NumberRenderer(String formatString, Locale locale) { - super(Number.class); + public NumberRenderer(String formatString, Locale locale, String nullRepresentation) { + super(Number.class, nullRepresentation); if (formatString == null) { throw new IllegalArgumentException("Format string may not be null"); @@ -135,7 +169,9 @@ public class NumberRenderer extends AbstractRenderer { @Override public JsonValue encode(Number value) { String stringValue; - if (formatString != null && locale != null) { + if (value == null) { + stringValue = getNullRepresentation(); + } else if (formatString != null && locale != null) { stringValue = String.format(locale, formatString, value); } else if (numberFormat != null) { stringValue = numberFormat.format(value); @@ -160,4 +196,9 @@ public class NumberRenderer extends AbstractRenderer { return String.format("%s [%s]", getClass().getSimpleName(), fieldInfo); } + + @Override + public String getNullRepresentation() { + return super.getNullRepresentation(); + } } diff --git a/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java b/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java index a077cd8012..1566c47222 100644 --- a/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java +++ b/server/src/com/vaadin/ui/renderers/ProgressBarRenderer.java @@ -21,9 +21,9 @@ import elemental.json.JsonValue; /** * A renderer that represents a double values as a graphical progress bar. - * - * @since 7.4 + * * @author Vaadin Ltd + * @since 7.4 */ public class ProgressBarRenderer extends AbstractRenderer { @@ -31,13 +31,15 @@ public class ProgressBarRenderer extends AbstractRenderer { * Creates a new text renderer */ public ProgressBarRenderer() { - super(Double.class); + super(Double.class, null); } @Override public JsonValue encode(Double value) { if (value != null) { value = Math.max(Math.min(value, 1), 0); + } else { + value = 0d; } return super.encode(value); } diff --git a/server/src/com/vaadin/ui/renderers/TextRenderer.java b/server/src/com/vaadin/ui/renderers/TextRenderer.java index 3723a45f70..0045024b2f 100644 --- a/server/src/com/vaadin/ui/renderers/TextRenderer.java +++ b/server/src/com/vaadin/ui/renderers/TextRenderer.java @@ -16,6 +16,7 @@ package com.vaadin.ui.renderers; import com.vaadin.ui.Grid.AbstractRenderer; +import elemental.json.JsonValue; /** * A renderer for presenting simple plain-text string values. @@ -29,6 +30,20 @@ public class TextRenderer extends AbstractRenderer { * Creates a new text renderer */ public TextRenderer() { - super(String.class); + this(""); + } + + /** + * Creates a new text renderer + * @param nullRepresentation + * the textual representation of {@code null} value + */ + public TextRenderer(String nullRepresentation) { + super(String.class, nullRepresentation); + } + + @Override + public String getNullRepresentation() { + return super.getNullRepresentation(); } } diff --git a/server/tests/src/com/vaadin/tests/server/renderer/RendererTest.java b/server/tests/src/com/vaadin/tests/server/renderer/RendererTest.java index 8bcbc6a5a9..8a01464180 100644 --- a/server/tests/src/com/vaadin/tests/server/renderer/RendererTest.java +++ b/server/tests/src/com/vaadin/tests/server/renderer/RendererTest.java @@ -15,15 +15,6 @@ */ package com.vaadin.tests.server.renderer; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - -import java.util.Locale; - -import org.junit.Before; -import org.junit.Test; - import com.vaadin.data.Item; import com.vaadin.data.RpcDataProviderExtension; import com.vaadin.data.util.IndexedContainer; @@ -34,9 +25,21 @@ import com.vaadin.tests.server.component.grid.TestGrid; import com.vaadin.tests.util.AlwaysLockedVaadinSession; import com.vaadin.ui.Grid; import com.vaadin.ui.Grid.Column; +import com.vaadin.ui.renderers.ButtonRenderer; +import com.vaadin.ui.renderers.DateRenderer; +import com.vaadin.ui.renderers.HtmlRenderer; +import com.vaadin.ui.renderers.NumberRenderer; import com.vaadin.ui.renderers.TextRenderer; - import elemental.json.JsonValue; +import org.junit.Before; +import org.junit.Test; + +import java.util.Date; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; public class RendererTest { @@ -64,14 +67,14 @@ public class RendererTest { @Override public TestBean convertToModel(String value, - Class targetType, Locale locale) + Class targetType, Locale locale) throws ConversionException { return null; } @Override public String convertToPresentation(TestBean value, - Class targetType, Locale locale) + Class targetType, Locale locale) throws ConversionException { if (value instanceof ExtendedBean) { return "ExtendedBean(" + value.i + ", " @@ -94,101 +97,151 @@ public class RendererTest { private Grid grid; - private Column foo; - private Column bar; - private Column baz; - private Column bah; + private Column intColumn; + private Column textColumn; + private Column beanColumn; + private Column htmlColumn; + private Column numberColumn; + private Column dateColumn; + private Column extendedBeanColumn; + private Column buttonColumn; @Before + @SuppressWarnings("unchecked") public void setUp() { VaadinSession.setCurrent(new AlwaysLockedVaadinSession(null)); IndexedContainer c = new IndexedContainer(); - c.addContainerProperty("foo", Integer.class, 0); - c.addContainerProperty("bar", String.class, ""); - c.addContainerProperty("baz", TestBean.class, null); - c.addContainerProperty("bah", ExtendedBean.class, null); + c.addContainerProperty("int", Integer.class, 0); + c.addContainerProperty("text", String.class, ""); + c.addContainerProperty("html", String.class, ""); + c.addContainerProperty("number", Number.class, null); + c.addContainerProperty("date", Date.class, null); + c.addContainerProperty("bean", TestBean.class, null); + c.addContainerProperty("button", String.class, null); + c.addContainerProperty("extendedBean", ExtendedBean.class, null); Object id = c.addItem(); Item item = c.getItem(id); - item.getItemProperty("foo").setValue(123); - item.getItemProperty("bar").setValue("321"); - item.getItemProperty("baz").setValue(new TestBean()); - item.getItemProperty("bah").setValue(new ExtendedBean()); + item.getItemProperty("int").setValue(123); + item.getItemProperty("text").setValue("321"); + item.getItemProperty("html").setValue("html"); + item.getItemProperty("number").setValue(3.14); + item.getItemProperty("date").setValue(new Date(123456789)); + item.getItemProperty("bean").setValue(new TestBean()); + item.getItemProperty("extendedBean").setValue(new ExtendedBean()); grid = new TestGrid(c); - foo = grid.getColumn("foo"); - bar = grid.getColumn("bar"); - baz = grid.getColumn("baz"); - bah = grid.getColumn("bah"); + intColumn = grid.getColumn("int"); + textColumn = grid.getColumn("text"); + htmlColumn = grid.getColumn("html"); + numberColumn = grid.getColumn("number"); + dateColumn = grid.getColumn("date"); + beanColumn = grid.getColumn("bean"); + extendedBeanColumn = grid.getColumn("extendedBean"); + buttonColumn = grid.getColumn("button"); + } @Test public void testDefaultRendererAndConverter() throws Exception { - assertSame(TextRenderer.class, foo.getRenderer().getClass()); - assertSame(StringToIntegerConverter.class, foo.getConverter() + assertSame(TextRenderer.class, intColumn.getRenderer().getClass()); + assertSame(StringToIntegerConverter.class, intColumn.getConverter() .getClass()); - assertSame(TextRenderer.class, bar.getRenderer().getClass()); + assertSame(TextRenderer.class, textColumn.getRenderer().getClass()); // String->String; converter not needed - assertNull(bar.getConverter()); + assertNull(textColumn.getConverter()); - assertSame(TextRenderer.class, baz.getRenderer().getClass()); + assertSame(TextRenderer.class, beanColumn.getRenderer().getClass()); // MyBean->String; converter not found - assertNull(baz.getConverter()); + assertNull(beanColumn.getConverter()); } @Test public void testFindCompatibleConverter() throws Exception { - foo.setRenderer(renderer()); - assertSame(StringToIntegerConverter.class, foo.getConverter() + intColumn.setRenderer(renderer()); + assertSame(StringToIntegerConverter.class, intColumn.getConverter() .getClass()); - bar.setRenderer(renderer()); - assertNull(bar.getConverter()); + textColumn.setRenderer(renderer()); + assertNull(textColumn.getConverter()); } @Test(expected = IllegalArgumentException.class) public void testCannotFindConverter() { - baz.setRenderer(renderer()); + beanColumn.setRenderer(renderer()); } @Test public void testExplicitConverter() throws Exception { - baz.setRenderer(renderer(), converter()); - bah.setRenderer(renderer(), converter()); + beanColumn.setRenderer(renderer(), converter()); + extendedBeanColumn.setRenderer(renderer(), converter()); } @Test public void testEncoding() throws Exception { - assertEquals("42", render(foo, 42).asString()); - foo.setRenderer(renderer()); - assertEquals("renderer(42)", render(foo, 42).asString()); + assertEquals("42", render(intColumn, 42).asString()); + intColumn.setRenderer(renderer()); + assertEquals("renderer(42)", render(intColumn, 42).asString()); - assertEquals("2.72", render(bar, "2.72").asString()); - bar.setRenderer(new TestRenderer()); - assertEquals("renderer(2.72)", render(bar, "2.72").asString()); + assertEquals("2.72", render(textColumn, "2.72").asString()); + textColumn.setRenderer(new TestRenderer()); + assertEquals("renderer(2.72)", render(textColumn, "2.72").asString()); } @Test public void testEncodingWithoutConverter() throws Exception { - assertEquals("TestBean [42]", render(baz, new TestBean()).asString()); + assertEquals("TestBean [42]", render(beanColumn, new TestBean()) + .asString()); } @Test public void testBeanEncoding() throws Exception { - baz.setRenderer(renderer(), converter()); - bah.setRenderer(renderer(), converter()); + beanColumn.setRenderer(renderer(), converter()); + extendedBeanColumn.setRenderer(renderer(), converter()); - assertEquals("renderer(TestBean(42))", render(baz, new TestBean()) - .asString()); + assertEquals("renderer(TestBean(42))", + render(beanColumn, new TestBean()).asString()); assertEquals("renderer(ExtendedBean(42, 3.14))", - render(baz, new ExtendedBean()).asString()); + render(beanColumn, new ExtendedBean()).asString()); assertEquals("renderer(ExtendedBean(42, 3.14))", - render(bah, new ExtendedBean()).asString()); + render(extendedBeanColumn, new ExtendedBean()).asString()); + } + + @Test + public void testNullEncoding() { + + textColumn.setRenderer(new TextRenderer()); + htmlColumn.setRenderer(new HtmlRenderer()); + numberColumn.setRenderer(new NumberRenderer()); + dateColumn.setRenderer(new DateRenderer()); + buttonColumn.setRenderer(new ButtonRenderer()); + + assertEquals("", textColumn.getRenderer().encode(null).asString()); + assertEquals("", htmlColumn.getRenderer().encode(null).asString()); + assertEquals("", numberColumn.getRenderer().encode(null).asString()); + assertEquals("", dateColumn.getRenderer().encode(null).asString()); + assertEquals("", buttonColumn.getRenderer().encode(null).asString()); + } + @Test + + public void testNullEncodingWithDefault() { + + textColumn.setRenderer(new TextRenderer("default value")); + htmlColumn.setRenderer(new HtmlRenderer("default value")); + numberColumn.setRenderer(new NumberRenderer("%s", Locale.getDefault(), "default value")); + dateColumn.setRenderer(new DateRenderer("%s", "default value")); + buttonColumn.setRenderer(new ButtonRenderer("default value")); + + assertEquals("default value", textColumn.getRenderer().encode(null).asString()); + assertEquals("default value", htmlColumn.getRenderer().encode(null).asString()); + assertEquals("default value", numberColumn.getRenderer().encode(null).asString()); + assertEquals("default value", dateColumn.getRenderer().encode(null).asString()); + assertEquals("default value", buttonColumn.getRenderer().encode(null).asString()); } private TestConverter converter() { diff --git a/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java index ce15676b60..ba3fc9cd0b 100644 --- a/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java +++ b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java @@ -19,6 +19,6 @@ import com.vaadin.ui.Grid.AbstractRenderer; public class IntArrayRenderer extends AbstractRenderer { public IntArrayRenderer() { - super(int[].class); + super(int[].class, ""); } } diff --git a/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java b/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java index af76054722..a2d1c08ea0 100644 --- a/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java +++ b/uitest/src/com/vaadin/tests/components/grid/MyBeanJSRenderer.java @@ -28,7 +28,7 @@ import com.vaadin.ui.renderers.AbstractJavaScriptRenderer; public class MyBeanJSRenderer extends AbstractJavaScriptRenderer { public MyBeanJSRenderer() { - super(MyBean.class); + super(MyBean.class, ""); } } diff --git a/uitest/src/com/vaadin/tests/components/grid/NullRenderers.java b/uitest/src/com/vaadin/tests/components/grid/NullRenderers.java new file mode 100644 index 0000000000..5ef5c12a7b --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/NullRenderers.java @@ -0,0 +1,131 @@ +/* + * 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 java.util.Date; +import java.util.Locale; + +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.Resource; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Grid; +import com.vaadin.ui.Grid.SelectionMode; +import com.vaadin.ui.renderers.ButtonRenderer; +import com.vaadin.ui.renderers.ClickableRenderer.RendererClickEvent; +import com.vaadin.ui.renderers.ClickableRenderer.RendererClickListener; +import com.vaadin.ui.renderers.DateRenderer; +import com.vaadin.ui.renderers.HtmlRenderer; +import com.vaadin.ui.renderers.ImageRenderer; +import com.vaadin.ui.renderers.NumberRenderer; +import com.vaadin.ui.renderers.ProgressBarRenderer; +import com.vaadin.ui.renderers.TextRenderer; + +@SuppressWarnings("all") +public class NullRenderers extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + IndexedContainer container = new IndexedContainer(); + + container.addContainerProperty(TextRenderer.class, String.class, null); + container.addContainerProperty(HtmlRenderer.class, String.class, null); + container.addContainerProperty(DateRenderer.class, Date.class, null); + container + .addContainerProperty(NumberRenderer.class, Number.class, null); + + container.addContainerProperty(ProgressBarRenderer.class, Double.class, + null); + container + .addContainerProperty(ButtonRenderer.class, String.class, null); + container.addContainerProperty(ImageRenderer.class, Resource.class, + null); + + container.addItem(); + + final Grid gridDefaults = new Grid(container); + + gridDefaults.setId("test-grid-defaults"); + gridDefaults.setSelectionMode(SelectionMode.NONE); + gridDefaults.setWidth("100%"); + + gridDefaults.getColumn(TextRenderer.class).setRenderer(new TextRenderer("-- No Text --")); + gridDefaults.getColumn(HtmlRenderer.class).setRenderer(new HtmlRenderer("-- No Jokes --")); + gridDefaults.getColumn(DateRenderer.class).setRenderer(new DateRenderer("%s", Locale.getDefault(), "-- Never --")); + gridDefaults.getColumn(NumberRenderer.class).setRenderer(new NumberRenderer("%s", Locale.getDefault(),"-- Nothing --")); + + gridDefaults.getColumn(ProgressBarRenderer.class).setRenderer( + new ProgressBarRenderer()); + + gridDefaults.getColumn(ButtonRenderer.class).setRenderer( + new ButtonRenderer(new RendererClickListener() { + @Override + public void click(RendererClickEvent event) { + } + }, "-- No Control --")); + + gridDefaults.getColumn(ImageRenderer.class).setRenderer( + new ImageRenderer(new RendererClickListener() { + + @Override + public void click(RendererClickEvent event) { + } + })); + + addComponent(gridDefaults); + + final Grid gridNoDefaults = new Grid(container); + + gridNoDefaults.setId("test-grid"); + gridNoDefaults.setSelectionMode(SelectionMode.NONE); + gridNoDefaults.setWidth("100%"); + + gridNoDefaults.getColumn(TextRenderer.class).setRenderer(new TextRenderer()); + gridNoDefaults.getColumn(HtmlRenderer.class).setRenderer(new HtmlRenderer()); + gridNoDefaults.getColumn(DateRenderer.class).setRenderer(new DateRenderer()); + gridNoDefaults.getColumn(NumberRenderer.class).setRenderer(new NumberRenderer()); + + gridNoDefaults.getColumn(ProgressBarRenderer.class).setRenderer( + new ProgressBarRenderer()); + + gridNoDefaults.getColumn(ButtonRenderer.class).setRenderer( + new ButtonRenderer(new RendererClickListener() { + @Override + public void click(RendererClickEvent event) { + } + })); + + gridNoDefaults.getColumn(ImageRenderer.class).setRenderer( + new ImageRenderer(new RendererClickListener() { + + @Override + public void click(RendererClickEvent event) { + } + })); + + addComponent(gridNoDefaults); + } + + @Override + protected String getTestDescription() { + return "Tests the functionality of widget-based renderers"; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(13334); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/NullRenderersTest.java b/uitest/src/com/vaadin/tests/components/grid/NullRenderersTest.java new file mode 100644 index 0000000000..4cc40e5769 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/NullRenderersTest.java @@ -0,0 +1,65 @@ +/* + * 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.testbench.elements.GridElement; +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.testbench.parallel.TestCategory; +import com.vaadin.tests.tb3.MultiBrowserTest; +import org.junit.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +@TestCategory("grid") +public class NullRenderersTest extends MultiBrowserTest { + @Test + public void testDefaults() throws Exception { + openTestURL(); + + GridElement grid = findGridWithDefaults(); + assertEquals("-- No Text --", grid.getCell(0, 0).getText()); + assertEquals("-- No Jokes --", grid.getCell(0, 1).getText()); + assertEquals("-- Never --", grid.getCell(0, 2).getText()); + assertEquals("-- Nothing --", grid.getCell(0, 3).getText()); + assertEquals("-- No Control --", grid.getCell(0, 5).getText()); + } + + @Test + public void testNoDefaults() throws Exception { + openTestURL(); + + GridElement grid = findGridNoDefaults(); + assertEquals("", grid.getCell(0, 0).getText()); + assertEquals("", grid.getCell(0, 1).getText()); + assertEquals("", grid.getCell(0, 2).getText()); + assertEquals("", grid.getCell(0, 3).getText()); + assertEquals("", grid.getCell(0, 5).getText()); + } + + private GridElement findGridWithDefaults() { + return $(GridElement.class).id("test-grid-defaults"); + } + + private GridElement findGridNoDefaults() { + return $(GridElement.class).id("test-grid"); + } + + private LabelElement findDebugLabel() { + return $(LabelElement.class).id(CustomRenderer.DEBUG_LABEL_ID); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java b/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java index 7b3390a7e7..02919f5c1b 100644 --- a/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java +++ b/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java @@ -21,7 +21,7 @@ import com.vaadin.ui.Label; public class RowAwareRenderer extends AbstractRenderer { public RowAwareRenderer(final Label debugLabel) { - super(Void.class); + super(Void.class, ""); registerRpc(new RowAwareRendererRpc() { @Override public void clicky(String key) { -- cgit v1.2.3 From c61187a34cf7fe6a38030231f3529400a34e9087 Mon Sep 17 00:00:00 2001 From: Anna Koskinen Date: Thu, 28 May 2015 16:41:07 +0300 Subject: Input prompt shouldn't get set when input has focus (#18027) Change-Id: Ide792fec9bf9050cea0b7616536965e42d74b16a --- client/src/com/vaadin/client/ui/VTextualDate.java | 7 +- .../datefield/PopupDateFieldInputPrompt.java | 68 ++++++++++++++++ .../datefield/PopupDateFieldInputPromptTest.java | 90 ++++++++++++++++++++++ 3 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldInputPrompt.java create mode 100644 uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldInputPromptTest.java (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/VTextualDate.java b/client/src/com/vaadin/client/ui/VTextualDate.java index 9055609e69..4d80b30f4f 100644 --- a/client/src/com/vaadin/client/ui/VTextualDate.java +++ b/client/src/com/vaadin/client/ui/VTextualDate.java @@ -363,7 +363,12 @@ public class VTextualDate extends VDateField implements Field, ChangeHandler, } protected void setText(String text) { - if (inputPrompt != null && (text == null || "".equals(text))) { + if (inputPrompt != null + && (text == null || "".equals(text)) + && !this.text.getStyleName() + .contains( + VTextField.CLASSNAME + "-" + + VTextField.CLASSNAME_FOCUS)) { text = readonly ? "" : inputPrompt; setPrompting(true); } else { diff --git a/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldInputPrompt.java b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldInputPrompt.java new file mode 100644 index 0000000000..a267d72b7f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldInputPrompt.java @@ -0,0 +1,68 @@ +/* + * 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.datefield; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.PopupDateField; +import com.vaadin.ui.TextField; + +/** + * Tests that state change doesn't set input prompt back to PopupDateField if + * focus is still in the input field. + * + * @author Vaadin Ltd + */ +public class PopupDateFieldInputPrompt extends AbstractTestUI { + + private TextField text = new TextField("TextField"); + private PopupDateField dateField = new PopupDateField(); + + @Override + protected void setup(VaadinRequest request) { + + text.addValueChangeListener(new ValueChangeListener() { + private static final long serialVersionUID = 1L; + + @Override + public void valueChange(ValueChangeEvent event) { + // update PopupDateField's state + dateField.setRequired(!dateField.isRequired()); + } + }); + + dateField.setInputPrompt("prompt"); + dateField.setCaption("PopupDateField"); + + addComponent(text); + addComponent(dateField); + } + + @Override + protected String getTestDescription() { + return "Write something to the TextField and use tabulator to move to PopupDateField." + + "
PopupDateField shouldn't get input prompt back before focus leaves the input field," + + "
even if TextField's value change updates PopupDateField's state."; + } + + @Override + protected Integer getTicketNumber() { + return 18027; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldInputPromptTest.java b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldInputPromptTest.java new file mode 100644 index 0000000000..4e5fa744c7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/datefield/PopupDateFieldInputPromptTest.java @@ -0,0 +1,90 @@ +/* + * 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.datefield; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; + +import com.vaadin.testbench.elements.PopupDateFieldElement; +import com.vaadin.testbench.elements.TextFieldElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * Tests that state change doesn't set input prompt back to PopupDateField if + * focus is still in the input field. + * + * @author Vaadin Ltd + */ +public class PopupDateFieldInputPromptTest extends MultiBrowserTest { + + @Test + public void testInputPrompt() { + openTestURL(); + TextFieldElement textField = $(TextFieldElement.class).first(); + final PopupDateFieldElement dateField = $(PopupDateFieldElement.class) + .first(); + + // ensure initial state + Assert.assertFalse("DateField required when it shouldn't be.", + isRequired(dateField)); + WebElement input = dateField.findElement(By.className("v-textfield")); + Assert.assertEquals("prompt", input.getAttribute("value")); + + // trigger ValueChange and move focus + textField.sendKeys("foo", Keys.TAB); + + // wait for ValueChange to update DateField's state and the DateField to + // gain focus. + waitForElementRequiredAndFocused(dateField, + By.className("v-textfield-focus")); + + // ensure prompt hasn't come back when field was set required + Assert.assertNotEquals("prompt", input.getAttribute("value")); + } + + private void waitForElementRequiredAndFocused( + final PopupDateFieldElement dateField, final By locator) { + waitUntil(new ExpectedCondition() { + + @Override + public Boolean apply(WebDriver arg0) { + if (isRequired(dateField)) { + List elements = dateField.findElements(locator); + return !elements.isEmpty(); + } + + return false; + } + + @Override + public String toString() { + return "dateField to become required and presence of element located by: " + + locator; + } + }); + } + + private boolean isRequired(PopupDateFieldElement dateField) { + return dateField.getAttribute("class").contains("v-required"); + } +} -- cgit v1.2.3 From d75ad04109dbe5fb77b87009a273282b32fec717 Mon Sep 17 00:00:00 2001 From: Mika Murtojarvi Date: Fri, 29 May 2015 13:41:53 +0300 Subject: Add @since 7.5 Change-Id: I860b5cf00415bc17a28b52b4a8109392a6939dc6 --- client/src/com/vaadin/client/ui/ui/UIConnector.java | 2 +- client/src/com/vaadin/client/widget/grid/EventCellReference.java | 8 ++++---- client/src/com/vaadin/client/widgets/Grid.java | 6 +++--- server/src/com/vaadin/ui/Grid.java | 2 +- shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/ui/UIConnector.java b/client/src/com/vaadin/client/ui/ui/UIConnector.java index 26ccff1191..264b2de0e1 100644 --- a/client/src/com/vaadin/client/ui/ui/UIConnector.java +++ b/client/src/com/vaadin/client/ui/ui/UIConnector.java @@ -814,7 +814,7 @@ public class UIConnector extends AbstractSingleComponentContainerConnector * Sends a request to the server to print a design to the console for the * given component. * - * @since + * @since 7.5 * @param connector * the component connector to output a declarative design for */ diff --git a/client/src/com/vaadin/client/widget/grid/EventCellReference.java b/client/src/com/vaadin/client/widget/grid/EventCellReference.java index 98878339d1..854d91920b 100644 --- a/client/src/com/vaadin/client/widget/grid/EventCellReference.java +++ b/client/src/com/vaadin/client/widget/grid/EventCellReference.java @@ -80,7 +80,7 @@ public class EventCellReference extends CellReference { /** * Is the cell reference for a cell in the header of the Grid. * - * @since + * @since 7.5 * @return true if referenced cell is in the header, * false if not */ @@ -91,7 +91,7 @@ public class EventCellReference extends CellReference { /** * Is the cell reference for a cell in the body of the Grid. * - * @since + * @since 7.5 * @return true if referenced cell is in the body, * false if not */ @@ -102,7 +102,7 @@ public class EventCellReference extends CellReference { /** * Is the cell reference for a cell in the footer of the Grid. * - * @since + * @since 7.5 * @return true if referenced cell is in the footer, * false if not */ @@ -113,7 +113,7 @@ public class EventCellReference extends CellReference { /** * Gets the Grid section where the referenced cell is. * - * @since + * @since 7.5 * @return grid section */ public Section getSection() { diff --git a/client/src/com/vaadin/client/widgets/Grid.java b/client/src/com/vaadin/client/widgets/Grid.java index 1fed0574dd..22a0ae27fb 100644 --- a/client/src/com/vaadin/client/widgets/Grid.java +++ b/client/src/com/vaadin/client/widgets/Grid.java @@ -1287,7 +1287,7 @@ public class Grid extends ResizeComposite implements * @throws IllegalStateException * if this editor is already in edit mode * - * @since + * @since 7.5 */ public void editRow(int rowIndex, int columnIndex) { if (!enabled) { @@ -1496,7 +1496,7 @@ public class Grid extends ResizeComposite implements * Opens the editor overlay over the table row indicated by * {@link #getRow()}. * - * @since + * @since 7.5 */ protected void showOverlay() { @@ -7872,7 +7872,7 @@ public class Grid extends ResizeComposite implements *

* Note: This cell reference will be updated when firing the next event. * - * @since + * @since 7.5 * @return event cell reference */ public EventCellReference getEventCell() { diff --git a/server/src/com/vaadin/ui/Grid.java b/server/src/com/vaadin/ui/Grid.java index 73d3a91176..00ed4a190d 100644 --- a/server/src/com/vaadin/ui/Grid.java +++ b/server/src/com/vaadin/ui/Grid.java @@ -3364,7 +3364,7 @@ public class Grid extends AbstractComponent implements SelectionNotifier, /** * An abstract base class for server-side Grid extensions. * - * @since + * @since 7.5 */ public static abstract class AbstractGridExtension extends AbstractExtension { diff --git a/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java b/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java index 9ca0a0a1bb..b6f17661d0 100644 --- a/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java +++ b/shared/src/com/vaadin/shared/ui/ui/DebugWindowServerRpc.java @@ -51,7 +51,7 @@ public interface DebugWindowServerRpc extends ServerRpc { * Sends a request to the server to print a design to the console for the * given component. * - * @since + * @since 7.5 * @param connector * the component connector to output a declarative design for */ -- cgit v1.2.3 From ed5ad86b114ccb4d6ab08e19a734bdb8b3342399 Mon Sep 17 00:00:00 2001 From: Artur Signell Date: Wed, 27 May 2015 22:03:26 +0300 Subject: Ensure method and property names are capitalized using English locale (#13389) Change-Id: Idde4fc54950f2bb83e0bb8d36a84a5bf075eb8de --- .../client/ui/csslayout/CssLayoutConnector.java | 9 ++--- .../src/com/vaadin/data/util/MethodProperty.java | 11 +++--- .../com/vaadin/data/util/NestedMethodProperty.java | 8 ++--- shared/src/com/vaadin/shared/util/SharedUtil.java | 30 ++++++++++++++-- .../com/vaadin/shared/util/SharedUtilTests.java | 42 ++++++++++++++++++++++ .../vaadin/tests/themes/valo/StringGenerator.java | 6 ++-- 6 files changed, 83 insertions(+), 23 deletions(-) (limited to 'client') diff --git a/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java b/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java index a0ef1fbb3e..bef506b492 100644 --- a/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/csslayout/CssLayoutConnector.java @@ -32,6 +32,7 @@ import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.LayoutClickRpc; import com.vaadin.shared.ui.csslayout.CssLayoutServerRpc; import com.vaadin.shared.ui.csslayout.CssLayoutState; +import com.vaadin.shared.util.SharedUtil; import com.vaadin.ui.CssLayout; /** @@ -160,13 +161,7 @@ public class CssLayoutConnector extends AbstractLayoutConnector { * @return A string converted to camelcase */ private static final String makeCamelCase(String cssProperty) { - // TODO this might be cleaner to implement with regexp - while (cssProperty.contains("-")) { - int indexOf = cssProperty.indexOf("-"); - cssProperty = cssProperty.substring(0, indexOf) - + String.valueOf(cssProperty.charAt(indexOf + 1)) - .toUpperCase() + cssProperty.substring(indexOf + 2); - } + cssProperty = SharedUtil.dashSeparatedToCamelCase(cssProperty); if ("float".equals(cssProperty)) { if (BrowserInfo.get().isIE()) { return "styleFloat"; diff --git a/server/src/com/vaadin/data/util/MethodProperty.java b/server/src/com/vaadin/data/util/MethodProperty.java index 853f68b711..83279afa53 100644 --- a/server/src/com/vaadin/data/util/MethodProperty.java +++ b/server/src/com/vaadin/data/util/MethodProperty.java @@ -26,6 +26,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import com.vaadin.data.Property; +import com.vaadin.shared.util.SharedUtil; import com.vaadin.util.SerializerHelper; /** @@ -189,11 +190,7 @@ public class MethodProperty extends AbstractProperty { // Assure that the first letter is upper cased (it is a common // mistake to write firstName, not FirstName). - if (Character.isLowerCase(beanPropertyName.charAt(0))) { - final char[] buf = beanPropertyName.toCharArray(); - buf[0] = Character.toUpperCase(buf[0]); - beanPropertyName = new String(buf); - } + beanPropertyName = SharedUtil.capitalize(beanPropertyName); // Find the get method getMethod = null; @@ -534,8 +531,7 @@ public class MethodProperty extends AbstractProperty { */ static Method initGetterMethod(String propertyName, final Class beanClass) throws NoSuchMethodException { - propertyName = propertyName.substring(0, 1).toUpperCase() - + propertyName.substring(1); + propertyName = SharedUtil.capitalize(propertyName); Method getMethod = null; try { @@ -772,4 +768,5 @@ public class MethodProperty extends AbstractProperty { private static final Logger getLogger() { return Logger.getLogger(MethodProperty.class.getName()); } + } diff --git a/server/src/com/vaadin/data/util/NestedMethodProperty.java b/server/src/com/vaadin/data/util/NestedMethodProperty.java index 0493812861..29fe62f845 100644 --- a/server/src/com/vaadin/data/util/NestedMethodProperty.java +++ b/server/src/com/vaadin/data/util/NestedMethodProperty.java @@ -26,6 +26,7 @@ import java.util.List; import com.vaadin.data.Property; import com.vaadin.data.util.MethodProperty.MethodException; +import com.vaadin.shared.util.SharedUtil; /** * Nested accessor based property for a bean. @@ -164,11 +165,8 @@ public class NestedMethodProperty extends AbstractProperty { try { // Assure that the first letter is upper cased (it is a common // mistake to write firstName, not FirstName). - if (Character.isLowerCase(lastSimplePropertyName.charAt(0))) { - final char[] buf = lastSimplePropertyName.toCharArray(); - buf[0] = Character.toUpperCase(buf[0]); - lastSimplePropertyName = new String(buf); - } + lastSimplePropertyName = SharedUtil + .capitalize(lastSimplePropertyName); setMethod = lastClass.getMethod("set" + lastSimplePropertyName, new Class[] { type }); diff --git a/shared/src/com/vaadin/shared/util/SharedUtil.java b/shared/src/com/vaadin/shared/util/SharedUtil.java index bc5d87b9f5..d363d767be 100644 --- a/shared/src/com/vaadin/shared/util/SharedUtil.java +++ b/shared/src/com/vaadin/shared/util/SharedUtil.java @@ -149,11 +149,12 @@ public class SharedUtil implements Serializable { sb.append(parts[i]); sb.append(separator); } - return sb.substring(0, sb.length() - 1); + return sb.substring(0, sb.length() - separator.length()); } /** - * Capitalizes the first character in the given string + * Capitalizes the first character in the given string in a way suitable for + * use in code (methods, properties etc) * * @since 7.4 * @param string @@ -239,4 +240,29 @@ public class SharedUtil implements Serializable { return uri; } + /** + * Converts a dash ("-") separated string into camelCase. + *

+ * Examples: + *

+ * {@literal foo} becomes {@literal foo} {@literal foo-bar} becomes + * {@literal fooBar} {@literal foo--bar} becomes {@literal fooBar} + * + * @since + * @param dashSeparated + * The dash separated string to convert + * @return a camelCase version of the input string + */ + public static String dashSeparatedToCamelCase(String dashSeparated) { + if (dashSeparated == null) { + return null; + } + String[] parts = dashSeparated.split("-"); + for (int i = 1; i < parts.length; i++) { + parts[i] = capitalize(parts[i]); + } + + return join(parts, ""); + } + } diff --git a/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java b/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java index 208d4ca7c7..e77501a446 100644 --- a/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java +++ b/shared/tests/src/com/vaadin/shared/util/SharedUtilTests.java @@ -3,6 +3,8 @@ package com.vaadin.shared.util; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; +import java.util.Locale; + import org.junit.Assert; import org.junit.Test; @@ -76,4 +78,44 @@ public class SharedUtilTests { String[] splitParts = SharedUtil.splitCamelCase(camelCaseString); Assert.assertArrayEquals(parts, splitParts); } + + @Test + public void join() { + String s1 = "foo-bar-baz"; + String s2 = "foo--bar"; + + Assert.assertEquals("foobarbaz", SharedUtil.join(s1.split("-"), "")); + Assert.assertEquals("foo!bar!baz", SharedUtil.join(s1.split("-"), "!")); + Assert.assertEquals("foo!!bar!!baz", + SharedUtil.join(s1.split("-"), "!!")); + + Assert.assertEquals("foo##bar", SharedUtil.join(s2.split("-"), "#")); + } + + @Test + public void dashSeparatedToCamelCase() { + Assert.assertEquals(null, SharedUtil.dashSeparatedToCamelCase(null)); + Assert.assertEquals("", SharedUtil.dashSeparatedToCamelCase("")); + Assert.assertEquals("foo", SharedUtil.dashSeparatedToCamelCase("foo")); + Assert.assertEquals("fooBar", + SharedUtil.dashSeparatedToCamelCase("foo-bar")); + Assert.assertEquals("fooBar", + SharedUtil.dashSeparatedToCamelCase("foo--bar")); + Assert.assertEquals("fooBarBaz", + SharedUtil.dashSeparatedToCamelCase("foo-bar-baz")); + Assert.assertEquals("fooBarBaz", + SharedUtil.dashSeparatedToCamelCase("foo-Bar-Baz")); + } + + @Test + public void methodUppercaseWithTurkishLocale() { + Locale defaultLocale = Locale.getDefault(); + try { + Locale.setDefault(new Locale("tr", "TR")); + Assert.assertEquals("Integer", SharedUtil.capitalize("integer")); + } finally { + Locale.setDefault(defaultLocale); + } + } + } diff --git a/uitest/src/com/vaadin/tests/themes/valo/StringGenerator.java b/uitest/src/com/vaadin/tests/themes/valo/StringGenerator.java index 7e5cc0f691..bffd94137c 100644 --- a/uitest/src/com/vaadin/tests/themes/valo/StringGenerator.java +++ b/uitest/src/com/vaadin/tests/themes/valo/StringGenerator.java @@ -15,6 +15,8 @@ */ package com.vaadin.tests.themes.valo; +import com.vaadin.shared.util.SharedUtil; + public class StringGenerator { static String[] strings = new String[] { "lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "quid", "securi", "etiam", "tamquam", "eu", @@ -25,8 +27,8 @@ public class StringGenerator { if (++stringCount >= strings.length) { stringCount = 0; } - return capitalize ? strings[stringCount].substring(0, 1).toUpperCase() - + strings[stringCount].substring(1) : strings[stringCount]; + return capitalize ? SharedUtil.capitalize(strings[stringCount]) + : strings[stringCount]; } } -- cgit v1.2.3