From 506e515d481b476e27b0c1e89cdd787fe3d0ce82 Mon Sep 17 00:00:00 2001 From: Anna Koskinen Date: Mon, 26 Apr 2021 13:39:14 +0300 Subject: [PATCH] Add browser specific handling in setRows (#12141) (#12275) Also enforced minimum height to 1 rows for consistency. Fixes: https://github.com/vaadin/framework/issues/10138 Fixes: https://github.com/vaadin/framework/issues/7878 Co-authored-by: Tatu Lund --- .../java/com/vaadin/client/ui/VTextArea.java | 4 +- .../src/main/java/com/vaadin/ui/TextArea.java | 7 +- .../components/textarea/TextAreaSetRows.java | 67 +++++++++ .../textarea/TextAreaSetRowsTest.java | 127 ++++++++++++++++++ 4 files changed, 202 insertions(+), 3 deletions(-) create mode 100644 uitest/src/main/java/com/vaadin/tests/components/textarea/TextAreaSetRows.java create mode 100644 uitest/src/test/java/com/vaadin/tests/components/textarea/TextAreaSetRowsTest.java diff --git a/client/src/main/java/com/vaadin/client/ui/VTextArea.java b/client/src/main/java/com/vaadin/client/ui/VTextArea.java index 769b1ed817..b50bd88a04 100644 --- a/client/src/main/java/com/vaadin/client/ui/VTextArea.java +++ b/client/src/main/java/com/vaadin/client/ui/VTextArea.java @@ -60,6 +60,7 @@ public class VTextArea extends VTextField implements DragImageModifier { super(DOM.createTextArea()); setStyleName(CLASSNAME); addKeyDownHandler(enterDownHandler); + getElement().getStyle().setOverflowX(Overflow.HIDDEN); } public TextAreaElement getTextAreaElement() { @@ -76,7 +77,8 @@ public class VTextArea extends VTextField implements DragImageModifier { } if (wordWrap) { getElement().removeAttribute("wrap"); - getElement().getStyle().clearOverflow(); + getElement().getStyle().clearOverflowY(); + getElement().getStyle().setOverflowX(Overflow.HIDDEN); getElement().getStyle().clearWhiteSpace(); } else { getElement().setAttribute("wrap", "off"); diff --git a/server/src/main/java/com/vaadin/ui/TextArea.java b/server/src/main/java/com/vaadin/ui/TextArea.java index 7d19948bb3..211cc44a29 100644 --- a/server/src/main/java/com/vaadin/ui/TextArea.java +++ b/server/src/main/java/com/vaadin/ui/TextArea.java @@ -136,13 +136,16 @@ public class TextArea extends AbstractTextField { /** * Sets the number of rows in the text area. + *

+ * Note: it's not possible to display less than one row via this height + * setting method, so minimum number of rows has been set to 1. * * @param rows * the number of rows for this text area. */ public void setRows(int rows) { - if (rows < 0) { - rows = 0; + if (rows < 1) { + rows = 1; } getState().rows = rows; } diff --git a/uitest/src/main/java/com/vaadin/tests/components/textarea/TextAreaSetRows.java b/uitest/src/main/java/com/vaadin/tests/components/textarea/TextAreaSetRows.java new file mode 100644 index 0000000000..393c91496e --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/textarea/TextAreaSetRows.java @@ -0,0 +1,67 @@ +package com.vaadin.tests.components.textarea; + +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.util.LoremIpsum; +import com.vaadin.ui.Button; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.Panel; +import com.vaadin.ui.TextArea; + +public class TextAreaSetRows extends AbstractTestUI { + + protected static final String ROWS_0 = "Set rows to 0"; + protected static final String ROWS_1 = "Set rows to 1"; + protected static final String ROWS_2 = "Set rows to 2"; + protected static final String ROWS_3 = "Set rows to 3"; + protected static final String ROWS_4 = "Set rows to 4"; + protected static final String HEIGHT0 = "Set height to 0px"; + protected static final String HEIGHTR = "Reset height setting"; + protected static final String WWRAP = "Toggle word wrap"; + protected static final String LONGS = "Use longer contents (separate)"; + protected static final String LONGN = "Use longer contents (no breaks)"; + protected static final String SCROLLB = "Add scrollbar to panel"; + + @Override + protected void setup(VaadinRequest request) { + TextArea ta = new TextArea(); + String value = "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n"; + ta.setValue(value); + addComponent(ta); + + addComponent(new Button(ROWS_0, e -> ta.setRows(0))); + addComponent(new Button(ROWS_1, e -> ta.setRows(1))); + addComponent(new Button(ROWS_2, e -> ta.setRows(2))); + addComponent(new Button(ROWS_3, e -> ta.setRows(3))); + addComponent(new Button(ROWS_4, e -> ta.setRows(4))); + addComponent(new Button(HEIGHT0, e -> ta.setHeight("0px"))); + addComponent(new Button(HEIGHTR, e -> ta.setHeight("-1px"))); + addComponent(new Button(WWRAP, e -> ta.setWordWrap(!ta.isWordWrap()))); + addComponent(new Button(LONGS, + e -> ta.setValue(value + LoremIpsum.get(50)))); + addComponent(new Button(LONGN, + e -> ta.setValue(value + getClass().getName()))); + + Panel p = new Panel(); + CssLayout content = new CssLayout(); + p.setContent(content); + content.setHeight("0px"); + p.setHeightUndefined(); + p.setWidth("100px"); + addComponent(p); + addComponent(new Button(SCROLLB, e -> content.setWidth("200px"))); + } + + @Override + protected Integer getTicketNumber() { + return 10138; + } + + @Override + protected String getTestDescription() { + return "Default height: 5 rows. Minimum height: 1 rows. " + + "Height should update as expected. Disabling word wrap " + + "adds space for a scrollbar whether one is needed or not. " + + "Firefox always behaves like word wrap was disabled."; + } +} diff --git a/uitest/src/test/java/com/vaadin/tests/components/textarea/TextAreaSetRowsTest.java b/uitest/src/test/java/com/vaadin/tests/components/textarea/TextAreaSetRowsTest.java new file mode 100644 index 0000000000..d2f4f139b5 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/textarea/TextAreaSetRowsTest.java @@ -0,0 +1,127 @@ +package com.vaadin.tests.components.textarea; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.PanelElement; +import com.vaadin.testbench.elements.TextAreaElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class TextAreaSetRowsTest extends MultiBrowserTest { + private double rowHeight; + private int scrollbarHeight; + private int bordersAndPadding = 14; // fixed by Valo theme + + @Test + public void testSetRows() { + openTestURL(); + waitUntilLoadingIndicatorNotVisible(); + + // calculate scrollbar height for comparison + PanelElement panel = $(PanelElement.class).first(); + int panelHeight = panel.getSize().getHeight(); + // add scrollbar + $(ButtonElement.class).caption(TextAreaSetRows.SCROLLB).first().click(); + waitUntilLoadingIndicatorNotVisible(); + scrollbarHeight = panel.getSize().getHeight() - panelHeight; + assertGreater("Unexpected comparison scrollbar height", scrollbarHeight, + 0); + + TextAreaElement textArea = $(TextAreaElement.class).first(); + int height5 = textArea.getSize().getHeight(); + // calculate height of a single row + rowHeight = (height5 - bordersAndPadding) / 5d; + assertEquals("Unexpected initial height,", getExpected(5), height5, 1); + + $(ButtonElement.class).caption(TextAreaSetRows.ROWS_0).first().click(); + waitUntilLoadingIndicatorNotVisible(); + int height0 = textArea.getSize().getHeight(); + assertEquals("Unexpected 0 rows height,", getExpected(0), height0, 1); + + $(ButtonElement.class).caption(TextAreaSetRows.ROWS_4).first().click(); + waitUntilLoadingIndicatorNotVisible(); + int height4 = textArea.getSize().getHeight(); + assertEquals("Unexpected 4 rows height,", getExpected(4), height4, 1); + + $(ButtonElement.class).caption(TextAreaSetRows.ROWS_2).first().click(); + waitUntilLoadingIndicatorNotVisible(); + int height2 = textArea.getSize().getHeight(); + assertEquals("Unexpected 2 rows height,", getExpected(2), height2, 1); + + $(ButtonElement.class).caption(TextAreaSetRows.ROWS_1).first().click(); + waitUntilLoadingIndicatorNotVisible(); + int height1 = textArea.getSize().getHeight(); + assertEquals("Unexpected 1 rows height,", getExpected(1), height1, 1); + + assertEquals("Height mismatch for 0 and 1 rows", height0, height1, 1); + + // set fixed height to 0 (does not affect borders and padding) + $(ButtonElement.class).caption(TextAreaSetRows.HEIGHT0).first().click(); + waitUntilLoadingIndicatorNotVisible(); + int heightFixed = textArea.getSize().getHeight(); + assertEquals("Unexpected fixed height,", bordersAndPadding, heightFixed, + 1); + + // remove fixed height, should return to height by rows + $(ButtonElement.class).caption(TextAreaSetRows.HEIGHTR).first().click(); + waitUntilLoadingIndicatorNotVisible(); + int heightReset = textArea.getSize().getHeight(); + assertEquals("Unexpected 1 rows height,", height1, heightReset, 1); + + $(ButtonElement.class).caption(TextAreaSetRows.ROWS_3).first().click(); + waitUntilLoadingIndicatorNotVisible(); + int height3 = textArea.getSize().getHeight(); + assertEquals("Unexpected 3 rows height,", getExpected(3), height3, 1); + + // toggle off word wrap + $(ButtonElement.class).caption(TextAreaSetRows.WWRAP).first().click(); + waitUntilLoadingIndicatorNotVisible(); + int newHeight3 = textArea.getSize().getHeight(); + // expected height to increase even without a scrollbar + assertGreater("Unexpected 3 rows height without word wrap (short),", + newHeight3, height3); + + // trigger horizontal scroll bar + $(ButtonElement.class).caption(TextAreaSetRows.LONGS).first().click(); + waitUntilLoadingIndicatorNotVisible(); + // height should not have changed + assertEquals("Unexpected 3 rows height without word wrap (long),", + newHeight3, textArea.getSize().getHeight(), 1); + + // switch to longer contents with no breaks + $(ButtonElement.class).caption(TextAreaSetRows.LONGN).first().click(); + waitUntilLoadingIndicatorNotVisible(); + // height should not have changed + assertEquals( + "Unexpected 3 rows height without word wrap (long without breaks),", + newHeight3, textArea.getSize().getHeight(), 1); + + // ensure that the height difference to original matches a scrollbar + // height, use a Panel's scrollbar as a comparison + assertEquals("Unexpected textarea scrollbar height,", scrollbarHeight, + newHeight3 - height3, 1); + + // toggle word wrap back on + $(ButtonElement.class).caption(TextAreaSetRows.WWRAP).first().click(); + waitUntilLoadingIndicatorNotVisible(); + // height should have reverted to what it was before removing wrap + assertEquals( + "Unexpected 3 rows height with word wrap (long without breaks),", + height3, textArea.getSize().getHeight(), 1); + } + + /** + * Calculates the expected height when horizontal scrollbar isn't possible. + * + * @param rows + * how many rows are displayed + * @return expected text area height + */ + private double getExpected(int rows) { + // minimum row count is one + return bordersAndPadding + (Math.max(1, rows) * rowHeight); + } + +} -- 2.39.5