From: Artur Signell Date: Thu, 18 Aug 2016 19:56:01 +0000 (+0300) Subject: Move TextArea to compatibility package X-Git-Tag: 8.0.0.alpha1~116 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=cfe379885275aae74b88c22ec4dd1bd3a8a094bd;p=vaadin-framework.git Move TextArea to compatibility package Change-Id: I16b6566340e3ce32a4f94b7554e2f6f583e20486 --- diff --git a/client/src/main/java/com/vaadin/client/ui/VTextArea.java b/client/src/main/java/com/vaadin/client/ui/VTextArea.java deleted file mode 100644 index 6ad69fb9cb..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/VTextArea.java +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2000-2016 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.client.ui; - -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.dom.client.Element; -import com.google.gwt.dom.client.Style.Overflow; -import com.google.gwt.dom.client.Style.WhiteSpace; -import com.google.gwt.dom.client.TextAreaElement; -import com.google.gwt.event.dom.client.ChangeEvent; -import com.google.gwt.event.dom.client.ChangeHandler; -import com.google.gwt.event.dom.client.KeyCodes; -import com.google.gwt.event.dom.client.KeyDownEvent; -import com.google.gwt.event.dom.client.KeyDownHandler; -import com.google.gwt.event.dom.client.KeyUpEvent; -import com.google.gwt.event.dom.client.KeyUpHandler; -import com.google.gwt.user.client.Command; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; -import com.vaadin.client.BrowserInfo; -import com.vaadin.client.WidgetUtil; -import com.vaadin.client.ui.dd.DragImageModifier; -import com.vaadin.client.v7.ui.VLegacyTextField; - -/** - * This class represents a multiline textfield (textarea). - * - * TODO consider replacing this with a RichTextArea based implementation. IE - * does not support CSS height for textareas in Strict mode :-( - * - * @author Vaadin Ltd. - * - */ -public class VTextArea extends VLegacyTextField implements DragImageModifier { - - public static final String CLASSNAME = "v-textarea"; - private boolean wordwrap = true; - private MaxLengthHandler maxLengthHandler = new MaxLengthHandler(); - private boolean browserSupportsMaxLengthAttribute = browserSupportsMaxLengthAttribute(); - private EnterDownHandler enterDownHandler = new EnterDownHandler(); - - public VTextArea() { - super(DOM.createTextArea()); - setStyleName(CLASSNAME); - - // KeyDownHandler is needed for correct text input on all - // browsers, not just those that don't support a max length attribute - addKeyDownHandler(enterDownHandler); - - if (!browserSupportsMaxLengthAttribute) { - addKeyUpHandler(maxLengthHandler); - addChangeHandler(maxLengthHandler); - sinkEvents(Event.ONPASTE); - } - } - - public TextAreaElement getTextAreaElement() { - return super.getElement().cast(); - } - - public void setRows(int rows) { - getTextAreaElement().setRows(rows); - } - - @Override - public void setSelectionRange(int pos, int length) { - super.setSelectionRange(pos, length); - final String value = getValue(); - /* - * Align position to index inside string value - */ - int index = pos; - if (index < 0) { - index = 0; - } - if (index > value.length()) { - index = value.length(); - } - // Get pixels count required to scroll textarea vertically - int scrollTop = getScrollTop(value, index); - int scrollLeft = -1; - /* - * Check if textarea has wrap attribute set to "off". In the latter case - * horizontal scroll is also required. - */ - if (!isWordwrap()) { - // Get pixels count required to scroll textarea horizontally - scrollLeft = getScrollLeft(value, index); - } - // Set back original text if previous methods calls changed it - if (!isWordwrap() || index < value.length()) { - setValue(value, false); - } - /* - * Call original method to set cursor position. In most browsers it - * doesn't lead to scrolling. - */ - super.setSelectionRange(pos, length); - /* - * Align vertical scroll to middle of textarea view (height) if - * scrolling is reqiured at all. - */ - if (scrollTop > 0) { - scrollTop += getElement().getClientHeight() / 2; - } - /* - * Align horizontal scroll to middle of textarea view (widht) if - * scrolling is reqiured at all. - */ - if (scrollLeft > 0) { - scrollLeft += getElement().getClientWidth() / 2; - } - /* - * Scroll if computed scrollTop is greater than scroll after cursor - * setting - */ - if (getElement().getScrollTop() < scrollTop) { - getElement().setScrollTop(scrollTop); - } - /* - * Scroll if computed scrollLeft is greater than scroll after cursor - * setting - */ - if (getElement().getScrollLeft() < scrollLeft) { - getElement().setScrollLeft(scrollLeft); - } - } - - /* - * Get horizontal scroll value required to get position visible. Method is - * called only when text wrapping is off. There is need to scroll - * horizontally in case words are wrapped. - */ - private int getScrollLeft(String value, int index) { - String beginning = value.substring(0, index); - // Compute beginning of the current line - int begin = beginning.lastIndexOf('\n'); - String line = value.substring(begin + 1); - index = index - begin - 1; - if (index < line.length()) { - index++; - } - line = line.substring(0, index); - /* - * Now line contains current line up to index position - */ - setValue(line.trim(), false); // Set this line to the textarea. - /* - * Scroll textarea up to the end of the line (maximum possible - * horizontal scrolling value). Now the end line becomes visible. - */ - getElement().setScrollLeft(getElement().getScrollWidth()); - // Return resulting horizontal scrolling value. - return getElement().getScrollLeft(); - } - - /* - * Get vertical scroll value required to get position visible - */ - private int getScrollTop(String value, int index) { - /* - * Trim text after position and set this trimmed text if index is not - * very end. - */ - if (index < value.length()) { - String beginning = value.substring(0, index); - setValue(beginning, false); - } - /* - * Now textarea contains trimmed text and could be scrolled up to the - * top. Scroll it to maximum possible value to get end of the text - * visible. - */ - getElement().setScrollTop(getElement().getScrollHeight()); - // Return resulting vertical scrolling value. - return getElement().getScrollTop(); - } - - private class MaxLengthHandler implements KeyUpHandler, ChangeHandler { - - @Override - public void onKeyUp(KeyUpEvent event) { - enforceMaxLength(); - } - - public void onPaste(Event event) { - enforceMaxLength(); - } - - @Override - public void onChange(ChangeEvent event) { - // Opera does not support paste events so this enforces max length - // for Opera. - enforceMaxLength(); - } - - } - - protected void enforceMaxLength() { - if (getMaxLength() >= 0) { - Scheduler.get().scheduleDeferred(new Command() { - @Override - public void execute() { - if (getText().length() > getMaxLength()) { - setText(getText().substring(0, getMaxLength())); - } - } - }); - } - } - - protected boolean browserSupportsMaxLengthAttribute() { - BrowserInfo info = BrowserInfo.get(); - if (info.isFirefox()) { - return true; - } - if (info.isSafari()) { - return true; - } - if (info.isIE11() || info.isEdge()) { - return true; - } - if (info.isAndroid()) { - return true; - } - return false; - } - - @Override - protected void updateMaxLength(int maxLength) { - if (browserSupportsMaxLengthAttribute) { - super.updateMaxLength(maxLength); - } else { - // Events handled by MaxLengthHandler. This call enforces max length - // when the max length value has changed - enforceMaxLength(); - } - } - - @Override - public void onBrowserEvent(Event event) { - super.onBrowserEvent(event); - if (event.getTypeInt() == Event.ONPASTE) { - maxLengthHandler.onPaste(event); - } - } - - private class EnterDownHandler implements KeyDownHandler { - - @Override - public void onKeyDown(KeyDownEvent event) { - // Fix for #12424/13811 - if the key being pressed is enter, we stop - // propagation of the KeyDownEvents if there were no modifier keys - // also pressed. This prevents shortcuts that are bound to only the - // enter key from being processed but allows usage of e.g. - // shift-enter or ctrl-enter. - if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER - && !event.isAnyModifierKeyDown()) { - event.stopPropagation(); - } - } - - } - - @Override - public int getCursorPos() { - // This is needed so that TextBoxImplIE6 is used to return the correct - // position for old Internet Explorer versions where it has to be - // detected in a different way. - return getImpl().getTextAreaCursorPos(getElement()); - } - - @Override - protected void setMaxLengthToElement(int newMaxLength) { - // There is no maxlength property for textarea. The maximum length is - // enforced by the KEYUP handler - - } - - public void setWordwrap(boolean wordwrap) { - if (wordwrap == this.wordwrap) { - return; // No change - } - - if (wordwrap) { - getElement().removeAttribute("wrap"); - getElement().getStyle().clearOverflow(); - getElement().getStyle().clearWhiteSpace(); - } else { - getElement().setAttribute("wrap", "off"); - getElement().getStyle().setOverflow(Overflow.AUTO); - getElement().getStyle().setWhiteSpace(WhiteSpace.PRE); - } - if (BrowserInfo.get().isOpera() - || (BrowserInfo.get().isWebkit() && wordwrap)) { - // Opera fails to dynamically update the wrap attribute so we detach - // and reattach the whole TextArea. - // Webkit fails to properly reflow the text when enabling wrapping, - // same workaround - WidgetUtil.detachAttach(getElement()); - } - this.wordwrap = wordwrap; - } - - @Override - public void onKeyDown(KeyDownEvent event) { - // Overridden to avoid submitting TextArea value on enter in IE. This is - // another reason why widgets should inherit a common abstract - // class instead of directly each other. - // This method is overridden only for IE and Firefox. - } - - @Override - public void modifyDragImage(Element element) { - // Fix for #13557 - drag image doesn't show original text area text. - // It happens because "value" property is not copied into the cloned - // element - String value = getElement().getPropertyString("value"); - if (value != null) { - element.setPropertyString("value", value); - } - } -} - diff --git a/client/src/main/java/com/vaadin/client/ui/textarea/TextAreaConnector.java b/client/src/main/java/com/vaadin/client/ui/textarea/TextAreaConnector.java deleted file mode 100644 index e081a0e0a4..0000000000 --- a/client/src/main/java/com/vaadin/client/ui/textarea/TextAreaConnector.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2000-2016 Vaadin Ltd. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.vaadin.client.ui.textarea; - -import com.google.gwt.dom.client.Element; -import com.google.gwt.event.dom.client.MouseUpEvent; -import com.google.gwt.event.dom.client.MouseUpHandler; -import com.vaadin.client.WidgetUtil.CssSize; -import com.vaadin.client.ui.VTextArea; -import com.vaadin.client.v7.ui.textfield.LegacyTextFieldConnector; -import com.vaadin.shared.ui.Connect; -import com.vaadin.shared.ui.textarea.TextAreaState; -import com.vaadin.ui.TextArea; - -@Connect(TextArea.class) -public class TextAreaConnector extends LegacyTextFieldConnector { - - @Override - public TextAreaState getState() { - return (TextAreaState) super.getState(); - } - - @Override - public VTextArea getWidget() { - return (VTextArea) super.getWidget(); - } - - @Override - protected void init() { - super.init(); - - getWidget().addMouseUpHandler(new ResizeMouseUpHandler()); - } - - /* - * Workaround to handle the resize on the mouse up. - */ - private class ResizeMouseUpHandler implements MouseUpHandler { - - @Override - public void onMouseUp(MouseUpEvent event) { - Element element = getWidget().getElement(); - - updateSize(element.getStyle().getHeight(), getState().height, - "height"); - updateSize(element.getStyle().getWidth(), getState().width, - "width"); - } - - /* - * Update the specified size on the server. - */ - private void updateSize(String sizeText, String stateSizeText, - String sizeType) { - - CssSize stateSize = CssSize.fromString(stateSizeText); - CssSize newSize = CssSize.fromString(sizeText); - - if (stateSize == null && newSize == null) { - return; - - } else if (newSize == null) { - sizeText = ""; - - // Else, if the current stateSize is null, just go ahead and set - // the newSize, so no check on stateSize is needed. - - } else if (stateSize != null && stateSize.equals(newSize)) { - return; - } - - getConnection().updateVariable(getConnectorId(), sizeType, sizeText, - false); - } - - } - -} diff --git a/compatibility-client/src/main/java/com/vaadin/client/ui/VTextArea.java b/compatibility-client/src/main/java/com/vaadin/client/ui/VTextArea.java new file mode 100644 index 0000000000..6ad69fb9cb --- /dev/null +++ b/compatibility-client/src/main/java/com/vaadin/client/ui/VTextArea.java @@ -0,0 +1,338 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.client.ui; + +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.Style.Overflow; +import com.google.gwt.dom.client.Style.WhiteSpace; +import com.google.gwt.dom.client.TextAreaElement; +import com.google.gwt.event.dom.client.ChangeEvent; +import com.google.gwt.event.dom.client.ChangeHandler; +import com.google.gwt.event.dom.client.KeyCodes; +import com.google.gwt.event.dom.client.KeyDownEvent; +import com.google.gwt.event.dom.client.KeyDownHandler; +import com.google.gwt.event.dom.client.KeyUpEvent; +import com.google.gwt.event.dom.client.KeyUpHandler; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.vaadin.client.BrowserInfo; +import com.vaadin.client.WidgetUtil; +import com.vaadin.client.ui.dd.DragImageModifier; +import com.vaadin.client.v7.ui.VLegacyTextField; + +/** + * This class represents a multiline textfield (textarea). + * + * TODO consider replacing this with a RichTextArea based implementation. IE + * does not support CSS height for textareas in Strict mode :-( + * + * @author Vaadin Ltd. + * + */ +public class VTextArea extends VLegacyTextField implements DragImageModifier { + + public static final String CLASSNAME = "v-textarea"; + private boolean wordwrap = true; + private MaxLengthHandler maxLengthHandler = new MaxLengthHandler(); + private boolean browserSupportsMaxLengthAttribute = browserSupportsMaxLengthAttribute(); + private EnterDownHandler enterDownHandler = new EnterDownHandler(); + + public VTextArea() { + super(DOM.createTextArea()); + setStyleName(CLASSNAME); + + // KeyDownHandler is needed for correct text input on all + // browsers, not just those that don't support a max length attribute + addKeyDownHandler(enterDownHandler); + + if (!browserSupportsMaxLengthAttribute) { + addKeyUpHandler(maxLengthHandler); + addChangeHandler(maxLengthHandler); + sinkEvents(Event.ONPASTE); + } + } + + public TextAreaElement getTextAreaElement() { + return super.getElement().cast(); + } + + public void setRows(int rows) { + getTextAreaElement().setRows(rows); + } + + @Override + public void setSelectionRange(int pos, int length) { + super.setSelectionRange(pos, length); + final String value = getValue(); + /* + * Align position to index inside string value + */ + int index = pos; + if (index < 0) { + index = 0; + } + if (index > value.length()) { + index = value.length(); + } + // Get pixels count required to scroll textarea vertically + int scrollTop = getScrollTop(value, index); + int scrollLeft = -1; + /* + * Check if textarea has wrap attribute set to "off". In the latter case + * horizontal scroll is also required. + */ + if (!isWordwrap()) { + // Get pixels count required to scroll textarea horizontally + scrollLeft = getScrollLeft(value, index); + } + // Set back original text if previous methods calls changed it + if (!isWordwrap() || index < value.length()) { + setValue(value, false); + } + /* + * Call original method to set cursor position. In most browsers it + * doesn't lead to scrolling. + */ + super.setSelectionRange(pos, length); + /* + * Align vertical scroll to middle of textarea view (height) if + * scrolling is reqiured at all. + */ + if (scrollTop > 0) { + scrollTop += getElement().getClientHeight() / 2; + } + /* + * Align horizontal scroll to middle of textarea view (widht) if + * scrolling is reqiured at all. + */ + if (scrollLeft > 0) { + scrollLeft += getElement().getClientWidth() / 2; + } + /* + * Scroll if computed scrollTop is greater than scroll after cursor + * setting + */ + if (getElement().getScrollTop() < scrollTop) { + getElement().setScrollTop(scrollTop); + } + /* + * Scroll if computed scrollLeft is greater than scroll after cursor + * setting + */ + if (getElement().getScrollLeft() < scrollLeft) { + getElement().setScrollLeft(scrollLeft); + } + } + + /* + * Get horizontal scroll value required to get position visible. Method is + * called only when text wrapping is off. There is need to scroll + * horizontally in case words are wrapped. + */ + private int getScrollLeft(String value, int index) { + String beginning = value.substring(0, index); + // Compute beginning of the current line + int begin = beginning.lastIndexOf('\n'); + String line = value.substring(begin + 1); + index = index - begin - 1; + if (index < line.length()) { + index++; + } + line = line.substring(0, index); + /* + * Now line contains current line up to index position + */ + setValue(line.trim(), false); // Set this line to the textarea. + /* + * Scroll textarea up to the end of the line (maximum possible + * horizontal scrolling value). Now the end line becomes visible. + */ + getElement().setScrollLeft(getElement().getScrollWidth()); + // Return resulting horizontal scrolling value. + return getElement().getScrollLeft(); + } + + /* + * Get vertical scroll value required to get position visible + */ + private int getScrollTop(String value, int index) { + /* + * Trim text after position and set this trimmed text if index is not + * very end. + */ + if (index < value.length()) { + String beginning = value.substring(0, index); + setValue(beginning, false); + } + /* + * Now textarea contains trimmed text and could be scrolled up to the + * top. Scroll it to maximum possible value to get end of the text + * visible. + */ + getElement().setScrollTop(getElement().getScrollHeight()); + // Return resulting vertical scrolling value. + return getElement().getScrollTop(); + } + + private class MaxLengthHandler implements KeyUpHandler, ChangeHandler { + + @Override + public void onKeyUp(KeyUpEvent event) { + enforceMaxLength(); + } + + public void onPaste(Event event) { + enforceMaxLength(); + } + + @Override + public void onChange(ChangeEvent event) { + // Opera does not support paste events so this enforces max length + // for Opera. + enforceMaxLength(); + } + + } + + protected void enforceMaxLength() { + if (getMaxLength() >= 0) { + Scheduler.get().scheduleDeferred(new Command() { + @Override + public void execute() { + if (getText().length() > getMaxLength()) { + setText(getText().substring(0, getMaxLength())); + } + } + }); + } + } + + protected boolean browserSupportsMaxLengthAttribute() { + BrowserInfo info = BrowserInfo.get(); + if (info.isFirefox()) { + return true; + } + if (info.isSafari()) { + return true; + } + if (info.isIE11() || info.isEdge()) { + return true; + } + if (info.isAndroid()) { + return true; + } + return false; + } + + @Override + protected void updateMaxLength(int maxLength) { + if (browserSupportsMaxLengthAttribute) { + super.updateMaxLength(maxLength); + } else { + // Events handled by MaxLengthHandler. This call enforces max length + // when the max length value has changed + enforceMaxLength(); + } + } + + @Override + public void onBrowserEvent(Event event) { + super.onBrowserEvent(event); + if (event.getTypeInt() == Event.ONPASTE) { + maxLengthHandler.onPaste(event); + } + } + + private class EnterDownHandler implements KeyDownHandler { + + @Override + public void onKeyDown(KeyDownEvent event) { + // Fix for #12424/13811 - if the key being pressed is enter, we stop + // propagation of the KeyDownEvents if there were no modifier keys + // also pressed. This prevents shortcuts that are bound to only the + // enter key from being processed but allows usage of e.g. + // shift-enter or ctrl-enter. + if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER + && !event.isAnyModifierKeyDown()) { + event.stopPropagation(); + } + } + + } + + @Override + public int getCursorPos() { + // This is needed so that TextBoxImplIE6 is used to return the correct + // position for old Internet Explorer versions where it has to be + // detected in a different way. + return getImpl().getTextAreaCursorPos(getElement()); + } + + @Override + protected void setMaxLengthToElement(int newMaxLength) { + // There is no maxlength property for textarea. The maximum length is + // enforced by the KEYUP handler + + } + + public void setWordwrap(boolean wordwrap) { + if (wordwrap == this.wordwrap) { + return; // No change + } + + if (wordwrap) { + getElement().removeAttribute("wrap"); + getElement().getStyle().clearOverflow(); + getElement().getStyle().clearWhiteSpace(); + } else { + getElement().setAttribute("wrap", "off"); + getElement().getStyle().setOverflow(Overflow.AUTO); + getElement().getStyle().setWhiteSpace(WhiteSpace.PRE); + } + if (BrowserInfo.get().isOpera() + || (BrowserInfo.get().isWebkit() && wordwrap)) { + // Opera fails to dynamically update the wrap attribute so we detach + // and reattach the whole TextArea. + // Webkit fails to properly reflow the text when enabling wrapping, + // same workaround + WidgetUtil.detachAttach(getElement()); + } + this.wordwrap = wordwrap; + } + + @Override + public void onKeyDown(KeyDownEvent event) { + // Overridden to avoid submitting TextArea value on enter in IE. This is + // another reason why widgets should inherit a common abstract + // class instead of directly each other. + // This method is overridden only for IE and Firefox. + } + + @Override + public void modifyDragImage(Element element) { + // Fix for #13557 - drag image doesn't show original text area text. + // It happens because "value" property is not copied into the cloned + // element + String value = getElement().getPropertyString("value"); + if (value != null) { + element.setPropertyString("value", value); + } + } +} + diff --git a/compatibility-client/src/main/java/com/vaadin/client/ui/textarea/TextAreaConnector.java b/compatibility-client/src/main/java/com/vaadin/client/ui/textarea/TextAreaConnector.java new file mode 100644 index 0000000000..e081a0e0a4 --- /dev/null +++ b/compatibility-client/src/main/java/com/vaadin/client/ui/textarea/TextAreaConnector.java @@ -0,0 +1,92 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.client.ui.textarea; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.event.dom.client.MouseUpEvent; +import com.google.gwt.event.dom.client.MouseUpHandler; +import com.vaadin.client.WidgetUtil.CssSize; +import com.vaadin.client.ui.VTextArea; +import com.vaadin.client.v7.ui.textfield.LegacyTextFieldConnector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.textarea.TextAreaState; +import com.vaadin.ui.TextArea; + +@Connect(TextArea.class) +public class TextAreaConnector extends LegacyTextFieldConnector { + + @Override + public TextAreaState getState() { + return (TextAreaState) super.getState(); + } + + @Override + public VTextArea getWidget() { + return (VTextArea) super.getWidget(); + } + + @Override + protected void init() { + super.init(); + + getWidget().addMouseUpHandler(new ResizeMouseUpHandler()); + } + + /* + * Workaround to handle the resize on the mouse up. + */ + private class ResizeMouseUpHandler implements MouseUpHandler { + + @Override + public void onMouseUp(MouseUpEvent event) { + Element element = getWidget().getElement(); + + updateSize(element.getStyle().getHeight(), getState().height, + "height"); + updateSize(element.getStyle().getWidth(), getState().width, + "width"); + } + + /* + * Update the specified size on the server. + */ + private void updateSize(String sizeText, String stateSizeText, + String sizeType) { + + CssSize stateSize = CssSize.fromString(stateSizeText); + CssSize newSize = CssSize.fromString(sizeText); + + if (stateSize == null && newSize == null) { + return; + + } else if (newSize == null) { + sizeText = ""; + + // Else, if the current stateSize is null, just go ahead and set + // the newSize, so no check on stateSize is needed. + + } else if (stateSize != null && stateSize.equals(newSize)) { + return; + } + + getConnection().updateVariable(getConnectorId(), sizeType, sizeText, + false); + } + + } + +} diff --git a/compatibility-server/src/main/java/com/vaadin/ui/TextArea.java b/compatibility-server/src/main/java/com/vaadin/ui/TextArea.java new file mode 100644 index 0000000000..056667a696 --- /dev/null +++ b/compatibility-server/src/main/java/com/vaadin/ui/TextArea.java @@ -0,0 +1,171 @@ +/* + * Copyright 2000-2016 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.ui; + +import org.jsoup.nodes.Element; + +import com.vaadin.data.Property; +import com.vaadin.shared.ui.textarea.TextAreaState; +import com.vaadin.ui.declarative.DesignContext; +import com.vaadin.ui.declarative.DesignFormatter; +import com.vaadin.v7.ui.LegacyAbstractTextField; + +/** + * A text field that supports multi line editing. + */ +public class TextArea extends LegacyAbstractTextField { + + /** + * Constructs an empty TextArea. + */ + public TextArea() { + setValue(""); + } + + /** + * Constructs an empty TextArea with given caption. + * + * @param caption + * the caption for the field. + */ + public TextArea(String caption) { + this(); + setCaption(caption); + } + + /** + * Constructs a TextArea with given property data source. + * + * @param dataSource + * the data source for the field + */ + public TextArea(Property dataSource) { + this(); + setPropertyDataSource(dataSource); + } + + /** + * Constructs a TextArea with given caption and property data source. + * + * @param caption + * the caption for the field + * @param dataSource + * the data source for the field + */ + public TextArea(String caption, Property dataSource) { + this(dataSource); + setCaption(caption); + } + + /** + * Constructs a TextArea with given caption and value. + * + * @param caption + * the caption for the field + * @param value + * the value for the field + */ + public TextArea(String caption, String value) { + this(caption); + setValue(value); + + } + + @Override + protected TextAreaState getState() { + return (TextAreaState) super.getState(); + } + + @Override + protected TextAreaState getState(boolean markAsDirty) { + return (TextAreaState) super.getState(markAsDirty); + } + + /** + * Sets the number of rows in the text area. + * + * @param rows + * the number of rows for this text area. + */ + public void setRows(int rows) { + if (rows < 0) { + rows = 0; + } + getState().rows = rows; + } + + /** + * Gets the number of rows in the text area. + * + * @return number of explicitly set rows. + */ + public int getRows() { + return getState(false).rows; + } + + /** + * Sets the text area's word-wrap mode on or off. + * + * @param wordwrap + * the boolean value specifying if the text area should be in + * word-wrap mode. + */ + public void setWordwrap(boolean wordwrap) { + getState().wordwrap = wordwrap; + } + + /** + * Tests if the text area is in word-wrap mode. + * + * @return true if the component is in word-wrap mode, + * false if not. + */ + public boolean isWordwrap() { + return getState(false).wordwrap; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.AbstractField#readDesign(org.jsoup.nodes.Element , + * com.vaadin.ui.declarative.DesignContext) + */ + @Override + public void readDesign(Element design, DesignContext designContext) { + super.readDesign(design, designContext); + setValue(DesignFormatter.decodeFromTextNode(design.html()), false, + true); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.AbstractTextField#writeDesign(org.jsoup.nodes.Element + * , com.vaadin.ui.declarative.DesignContext) + */ + @Override + public void writeDesign(Element design, DesignContext designContext) { + super.writeDesign(design, designContext); + design.html(DesignFormatter.encodeForTextNode(getValue())); + } + + @Override + public void clear() { + setValue(""); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/design/WriteLegacyDesignTest.java b/compatibility-server/src/test/java/com/vaadin/tests/design/WriteLegacyDesignTest.java new file mode 100644 index 0000000000..eb3841b094 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/design/WriteLegacyDesignTest.java @@ -0,0 +1,99 @@ +/* + * Copyright 2000-2016 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.design; + +import static org.junit.Assert.assertTrue; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Properties; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.server.Constants; +import com.vaadin.server.DefaultDeploymentConfiguration; +import com.vaadin.server.DeploymentConfiguration; +import com.vaadin.server.VaadinService; +import com.vaadin.server.VaadinServletService; +import com.vaadin.ui.declarative.Design; +import com.vaadin.ui.declarative.DesignContext; +import com.vaadin.util.CurrentInstance; + +/** + * Parse and write a legacy design (using the "v-" prefix). + */ +public class WriteLegacyDesignTest { + + // The context is used for accessing the created component hierarchy. + private DesignContext ctx; + + @Before + public void setUp() throws Exception { + Properties properties = new Properties(); + properties.put(Constants.SERVLET_PARAMETER_LEGACY_DESIGN_PREFIX, + "true"); + final DeploymentConfiguration configuration = new DefaultDeploymentConfiguration( + WriteLegacyDesignTest.class, properties); + + VaadinService service = new VaadinServletService(null, configuration); + + CurrentInstance.set(VaadinService.class, service); + + ctx = Design.read( + getClass().getResourceAsStream("testFile-legacy.html"), null); + } + + @After + public void tearDown() { + CurrentInstance.set(VaadinService.class, null); + } + + private ByteArrayOutputStream serializeDesign(DesignContext context) + throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Design.write(context, out); + + return out; + } + + @Test + public void designIsSerializedWithCorrectPrefixesAndPackageNames() + throws IOException { + ByteArrayOutputStream out = serializeDesign(ctx); + + Document doc = Jsoup.parse(out.toString("UTF-8")); + for (Node child : doc.body().childNodes()) { + checkNode(child); + } + } + + private void checkNode(Node node) { + if (node instanceof Element) { + assertTrue("Wrong design element prefix", + node.nodeName().startsWith("v-")); + for (Node child : node.childNodes()) { + checkNode(child); + } + } + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/textarea/TextAreaDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/textarea/TextAreaDeclarativeTest.java new file mode 100644 index 0000000000..cbfa33320f --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/textarea/TextAreaDeclarativeTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2000-2016 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.server.component.textarea; + +import java.io.IOException; + +import org.jsoup.nodes.Element; +import org.jsoup.parser.Tag; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.tests.design.DeclarativeTestBase; +import com.vaadin.ui.TextArea; +import com.vaadin.ui.declarative.DesignContext; + +/** + * Tests declarative support for implementations of {@link TextArea}. + * + * @since 7.4 + * @author Vaadin Ltd + */ +public class TextAreaDeclarativeTest extends DeclarativeTestBase