From: Artur Signell Date: Tue, 6 Sep 2016 18:56:19 +0000 (+0300) Subject: Add AbstractTextField client side to make mapping 1:1 X-Git-Tag: 8.0.0.alpha1~14 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a18552fb252e452ce93642a946db67af6708a91d;p=vaadin-framework.git Add AbstractTextField client side to make mapping 1:1 Change-Id: I4439b995a769d22e0eded7132e2fb09123c25a49 --- diff --git a/client/src/main/java/com/vaadin/client/ui/AbstractTextFieldWidget.java b/client/src/main/java/com/vaadin/client/ui/AbstractTextFieldWidget.java new file mode 100644 index 0000000000..256428c83a --- /dev/null +++ b/client/src/main/java/com/vaadin/client/ui/AbstractTextFieldWidget.java @@ -0,0 +1,64 @@ +/* + * 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.vaadin.client.ui.textfield.AbstractTextFieldConnector; + +/** + * Implemented by all widgets used by a connector extending + * {@link AbstractTextFieldConnector}. + */ +public interface AbstractTextFieldWidget { + + /** + * Sets the selection range for the field. + * + * @param start + * the start of the selection + * @param length + * the length of the selection + */ + public void setSelectionRange(int start, int length); + + /** + * Gets the current value of the field. + * + * @return the current text in the field + */ + public String getValue(); + + /** + * Selects all text in the field. + */ + public void selectAll(); + + /** + * Sets the read-only mode of the field. + * + * @param readOnly + * true to set the field to read-only, + * false otherwise + */ + public void setReadOnly(boolean readOnly); + + /** + * Gets the current cursor position inside the field. + * + * @return the current cursor position + */ + public int getCursorPos(); + +} 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 c63fbda38c..18727361fe 100644 --- a/client/src/main/java/com/vaadin/client/ui/VTextArea.java +++ b/client/src/main/java/com/vaadin/client/ui/VTextArea.java @@ -34,7 +34,8 @@ import com.vaadin.client.ui.dd.DragImageModifier; * @author Vaadin Ltd. * */ -public class VTextArea extends VTextField implements DragImageModifier { +public class VTextArea extends VTextField + implements DragImageModifier, AbstractTextFieldWidget { public static final String CLASSNAME = "v-textarea"; diff --git a/client/src/main/java/com/vaadin/client/ui/VTextField.java b/client/src/main/java/com/vaadin/client/ui/VTextField.java index a1ef816d1d..1eb499505a 100644 --- a/client/src/main/java/com/vaadin/client/ui/VTextField.java +++ b/client/src/main/java/com/vaadin/client/ui/VTextField.java @@ -31,7 +31,7 @@ import com.google.gwt.user.client.ui.TextBoxBase; * */ public class VTextField extends TextBoxBase - implements Field, FocusHandler, BlurHandler { + implements Field, FocusHandler, BlurHandler, AbstractTextFieldWidget { public static final String CLASSNAME = "v-textfield"; public static final String CLASSNAME_FOCUS = "focus"; 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 index 9ad4c8b277..1f98b04310 100644 --- a/client/src/main/java/com/vaadin/client/ui/textarea/TextAreaConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/textarea/TextAreaConnector.java @@ -19,15 +19,17 @@ package com.vaadin.client.ui.textarea; import com.google.gwt.dom.client.Style; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; +import com.vaadin.client.event.InputEvent; import com.vaadin.client.ui.VTextArea; -import com.vaadin.client.ui.textfield.TextFieldConnector; +import com.vaadin.client.ui.textfield.AbstractTextFieldConnector; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.textarea.TextAreaServerRpc; import com.vaadin.shared.ui.textarea.TextAreaState; +import com.vaadin.shared.ui.textfield.ValueChangeMode; import com.vaadin.ui.TextArea; @Connect(TextArea.class) -public class TextAreaConnector extends TextFieldConnector { +public class TextAreaConnector extends AbstractTextFieldConnector { @Override public TextAreaState getState() { @@ -42,6 +44,12 @@ public class TextAreaConnector extends TextFieldConnector { @Override protected void init() { super.init(); + getWidget().addChangeHandler(event -> sendValueChange()); + getWidget().addDomHandler(event -> { + if (getState().valueChangeMode != ValueChangeMode.BLUR) { + scheduleValueChange(); + } + }, InputEvent.getType()); getWidget().addMouseUpHandler(new ResizeMouseUpHandler()); } diff --git a/client/src/main/java/com/vaadin/client/ui/textfield/AbstractTextFieldConnector.java b/client/src/main/java/com/vaadin/client/ui/textfield/AbstractTextFieldConnector.java new file mode 100644 index 0000000000..3ee9958140 --- /dev/null +++ b/client/src/main/java/com/vaadin/client/ui/textfield/AbstractTextFieldConnector.java @@ -0,0 +1,164 @@ +/* + * 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.textfield; + +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.ui.Widget; +import com.vaadin.client.annotations.OnStateChange; +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.client.ui.AbstractTextFieldWidget; +import com.vaadin.client.ui.ConnectorFocusAndBlurHandler; +import com.vaadin.shared.ui.textfield.AbstractTextFieldClientRpc; +import com.vaadin.shared.ui.textfield.AbstractTextFieldServerRpc; +import com.vaadin.shared.ui.textfield.AbstractTextFieldState; +import com.vaadin.shared.ui.textfield.ValueChangeMode; +import com.vaadin.ui.AbstractTextField; + +/** + * Connector class for AbstractTextField. + */ +public abstract class AbstractTextFieldConnector + extends AbstractComponentConnector { + + private class AbstractTextFieldClientRpcImpl + implements AbstractTextFieldClientRpc { + @Override + public void selectRange(int start, int length) { + int textLength = getAbstractTextField().getValue().length(); + start = restrictTo(start, 0, textLength - 1); + length = restrictTo(length, 0, textLength - start); + getAbstractTextField().setSelectionRange(start, length); + } + + private int restrictTo(int value, int min, int max) { + if (value < min) { + value = min; + } + if (value > max) { + value = max; + } + + return value; + } + + @Override + public void selectAll() { + getAbstractTextField().selectAll(); + } + } + + private int lastSentCursorPosition = -1; + + private Timer valueChangeTrigger = new Timer() { + @Override + public void run() { + Scheduler.get().scheduleDeferred(() -> sendValueChange()); + } + }; + + @Override + protected void init() { + registerRpc(AbstractTextFieldClientRpc.class, + new AbstractTextFieldClientRpcImpl()); + ConnectorFocusAndBlurHandler.addHandlers(this); + } + + /** + * Helper to cast {@link #getWidget()} to {@link AbstractTextField}. The + * method exists only because getWidget() must return a {@link Widget} and + * not an interface. + * + * @return the widget as an AbstractTextFieldWidget + */ + private AbstractTextFieldWidget getAbstractTextField() { + return (AbstractTextFieldWidget) getWidget(); + } + + /** + * Called whenever a change in the value has been detected. Schedules a + * value change to be sent to the server, depending on the current value + * change mode. + *

+ * Note that this method does not consider the {@link ValueChangeMode#BLUR} + * mode but assumes that {@link #sendValueChange()} is called directly for + * this mode. + */ + protected void scheduleValueChange() { + switch (getState().valueChangeMode) { + case LAZY: + lazyTextChange(); + break; + case TIMEOUT: + timeoutTextChange(); + break; + case EAGER: + eagerTextChange(); + break; + case BLUR: + // Nothing to schedule for this mode + break; + } + } + + private void lazyTextChange() { + valueChangeTrigger.schedule(getState().valueChangeTimeout); + } + + private void timeoutTextChange() { + if (valueChangeTrigger.isRunning()) { + return; + } + valueChangeTrigger.schedule(getState().valueChangeTimeout); + } + + private void eagerTextChange() { + valueChangeTrigger.run(); + } + + @Override + public AbstractTextFieldState getState() { + return (AbstractTextFieldState) super.getState(); + } + + @OnStateChange("readOnly") + private void updateReadOnly() { + getAbstractTextField().setReadOnly(getState().readOnly); + } + + private boolean hasStateChanged() { + boolean textChanged = !getAbstractTextField().getValue() + .equals(getState().text); + boolean cursorPosChanged = getAbstractTextField() + .getCursorPos() != lastSentCursorPosition; + return textChanged || cursorPosChanged; + } + + /** + * Sends the updated value and cursor position to the server, if either one + * has changed. + */ + protected void sendValueChange() { + if (!hasStateChanged()) { + return; + } + lastSentCursorPosition = getAbstractTextField().getCursorPos(); + getRpcProxy(AbstractTextFieldServerRpc.class).setText( + getAbstractTextField().getValue(), lastSentCursorPosition); + getState().text = getAbstractTextField().getValue(); + } + +} diff --git a/client/src/main/java/com/vaadin/client/ui/textfield/TextFieldConnector.java b/client/src/main/java/com/vaadin/client/ui/textfield/TextFieldConnector.java index 46e02c18ee..0a937de349 100644 --- a/client/src/main/java/com/vaadin/client/ui/textfield/TextFieldConnector.java +++ b/client/src/main/java/com/vaadin/client/ui/textfield/TextFieldConnector.java @@ -15,17 +15,10 @@ */ package com.vaadin.client.ui.textfield; -import com.google.gwt.core.client.Scheduler; -import com.google.gwt.user.client.Timer; -import com.vaadin.client.annotations.OnStateChange; import com.vaadin.client.event.InputEvent; -import com.vaadin.client.ui.AbstractComponentConnector; -import com.vaadin.client.ui.ConnectorFocusAndBlurHandler; import com.vaadin.client.ui.VTextField; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.Connect.LoadStyle; -import com.vaadin.shared.ui.textfield.AbstractTextFieldClientRpc; -import com.vaadin.shared.ui.textfield.AbstractTextFieldServerRpc; import com.vaadin.shared.ui.textfield.TextFieldState; import com.vaadin.shared.ui.textfield.ValueChangeMode; import com.vaadin.ui.TextField; @@ -34,49 +27,11 @@ import com.vaadin.ui.TextField; * Connector class for TextField. */ @Connect(value = TextField.class, loadStyle = LoadStyle.EAGER) -public class TextFieldConnector extends AbstractComponentConnector { - - private class AbstractTextFieldClientRpcImpl - implements AbstractTextFieldClientRpc { - @Override - public void selectRange(int start, int length) { - int textLength = getWidget().getText().length(); - start = restrictTo(start, 0, textLength - 1); - length = restrictTo(length, 0, textLength - start); - getWidget().setSelectionRange(start, length); - } - - private int restrictTo(int value, int min, int max) { - if (value < min) { - value = min; - } - if (value > max) { - value = max; - } - - return value; - } - - @Override - public void selectAll() { - getWidget().selectAll(); - } - } - - private int lastSentCursorPosition = -1; - - private Timer valueChangeTrigger = new Timer() { - @Override - public void run() { - Scheduler.get().scheduleDeferred(() -> sendValueChange()); - } - }; +public class TextFieldConnector extends AbstractTextFieldConnector { @Override protected void init() { - registerRpc(AbstractTextFieldClientRpc.class, - new AbstractTextFieldClientRpcImpl()); - ConnectorFocusAndBlurHandler.addHandlers(this); + super.init(); getWidget().addChangeHandler(event -> sendValueChange()); getWidget().addDomHandler(event -> { if (getState().valueChangeMode != ValueChangeMode.BLUR) { @@ -85,38 +40,6 @@ public class TextFieldConnector extends AbstractComponentConnector { }, InputEvent.getType()); } - private void scheduleValueChange() { - switch (getState().valueChangeMode) { - case LAZY: - lazyTextChange(); - break; - case TIMEOUT: - timeoutTextChange(); - break; - case EAGER: - eagerTextChange(); - break; - case BLUR: - // Nothing to schedule for this mode - break; - } - } - - private void lazyTextChange() { - valueChangeTrigger.schedule(getState().valueChangeTimeout); - } - - private void timeoutTextChange() { - if (valueChangeTrigger.isRunning()) { - return; - } - valueChangeTrigger.schedule(getState().valueChangeTimeout); - } - - private void eagerTextChange() { - valueChangeTrigger.run(); - } - @Override public TextFieldState getState() { return (TextFieldState) super.getState(); @@ -127,25 +50,4 @@ public class TextFieldConnector extends AbstractComponentConnector { return (VTextField) super.getWidget(); } - @OnStateChange("readOnly") - private void updateReadOnly() { - getWidget().setReadOnly(getState().readOnly); - } - - private boolean hasStateChanged() { - boolean textChanged = !getWidget().getValue().equals(getState().text); - boolean cursorPosChanged = getWidget() - .getCursorPos() != lastSentCursorPosition; - return textChanged || cursorPosChanged; - } - - private void sendValueChange() { - if (!hasStateChanged()) { - return; - } - lastSentCursorPosition = getWidget().getCursorPos(); - getRpcProxy(AbstractTextFieldServerRpc.class) - .setText(getWidget().getValue(), lastSentCursorPosition); - getState().text = getWidget().getValue(); - } } diff --git a/server/src/main/java/com/vaadin/ui/AbstractTextField.java b/server/src/main/java/com/vaadin/ui/AbstractTextField.java index 75c2067759..e447fd6724 100644 --- a/server/src/main/java/com/vaadin/ui/AbstractTextField.java +++ b/server/src/main/java/com/vaadin/ui/AbstractTextField.java @@ -29,7 +29,7 @@ import com.vaadin.shared.Registration; import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc; import com.vaadin.shared.ui.textfield.AbstractTextFieldClientRpc; import com.vaadin.shared.ui.textfield.AbstractTextFieldServerRpc; -import com.vaadin.shared.ui.textfield.TextFieldState; +import com.vaadin.shared.ui.textfield.AbstractTextFieldState; import com.vaadin.shared.ui.textfield.ValueChangeMode; import com.vaadin.ui.declarative.DesignAttributeHandler; import com.vaadin.ui.declarative.DesignContext; @@ -42,7 +42,7 @@ import com.vaadin.ui.declarative.DesignContext; */ public abstract class AbstractTextField extends AbstractField { - private final class TextFieldServerRpcImpl + private final class AbstractTextFieldServerRpcImpl implements AbstractTextFieldServerRpc { @Override @@ -54,7 +54,7 @@ public abstract class AbstractTextField extends AbstractField { } } - private final class TextFieldFocusAndBlurRpcImpl + private final class AbstractTextFieldFocusAndBlurRpcImpl implements FocusAndBlurServerRpc { @Override public void blur() { @@ -73,8 +73,8 @@ public abstract class AbstractTextField extends AbstractField { * Creates a new instance. */ protected AbstractTextField() { - registerRpc(new TextFieldServerRpcImpl()); - registerRpc(new TextFieldFocusAndBlurRpcImpl()); + registerRpc(new AbstractTextFieldServerRpcImpl()); + registerRpc(new AbstractTextFieldFocusAndBlurRpcImpl()); } @Override @@ -305,13 +305,13 @@ public abstract class AbstractTextField extends AbstractField { } @Override - protected TextFieldState getState() { - return (TextFieldState) super.getState(); + protected AbstractTextFieldState getState() { + return (AbstractTextFieldState) super.getState(); } @Override - protected TextFieldState getState(boolean markAsDirty) { - return (TextFieldState) super.getState(markAsDirty); + protected AbstractTextFieldState getState(boolean markAsDirty) { + return (AbstractTextFieldState) super.getState(markAsDirty); } @Override diff --git a/server/src/main/java/com/vaadin/ui/PasswordField.java b/server/src/main/java/com/vaadin/ui/PasswordField.java index 9d07d2718a..a3fb4d265a 100644 --- a/server/src/main/java/com/vaadin/ui/PasswordField.java +++ b/server/src/main/java/com/vaadin/ui/PasswordField.java @@ -26,7 +26,7 @@ import com.vaadin.ui.declarative.DesignContext; * A field that is used to enter secret text information like passwords. The * entered text is not displayed on the screen. */ -public class PasswordField extends AbstractTextField { +public class PasswordField extends TextField { /** * Constructs an empty PasswordField. diff --git a/server/src/main/java/com/vaadin/ui/TextField.java b/server/src/main/java/com/vaadin/ui/TextField.java index 2f66b6edee..c01650fb60 100644 --- a/server/src/main/java/com/vaadin/ui/TextField.java +++ b/server/src/main/java/com/vaadin/ui/TextField.java @@ -19,6 +19,7 @@ package com.vaadin.ui; import org.jsoup.nodes.Attributes; import org.jsoup.nodes.Element; +import com.vaadin.shared.ui.textfield.TextFieldState; import com.vaadin.ui.declarative.DesignAttributeHandler; import com.vaadin.ui.declarative.DesignContext; @@ -63,6 +64,11 @@ public class TextField extends AbstractTextField { setCaption(caption); } + @Override + protected TextFieldState getState() { + return (TextFieldState) super.getState(); + } + @Override public void readDesign(Element design, DesignContext designContext) { super.readDesign(design, designContext); diff --git a/shared/src/main/java/com/vaadin/shared/ui/textarea/TextAreaState.java b/shared/src/main/java/com/vaadin/shared/ui/textarea/TextAreaState.java index a56b45ea7e..a5f3205d6d 100644 --- a/shared/src/main/java/com/vaadin/shared/ui/textarea/TextAreaState.java +++ b/shared/src/main/java/com/vaadin/shared/ui/textarea/TextAreaState.java @@ -17,9 +17,9 @@ package com.vaadin.shared.ui.textarea; import com.vaadin.shared.annotations.DelegateToWidget; import com.vaadin.shared.annotations.NoLayout; -import com.vaadin.shared.ui.textfield.TextFieldState; +import com.vaadin.shared.ui.textfield.AbstractTextFieldState; -public class TextAreaState extends TextFieldState { +public class TextAreaState extends AbstractTextFieldState { { primaryStyleName = "v-textarea"; } diff --git a/shared/src/main/java/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java b/shared/src/main/java/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java new file mode 100644 index 0000000000..b35fd89a27 --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/ui/textfield/AbstractTextFieldState.java @@ -0,0 +1,59 @@ +/* + * 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.shared.ui.textfield; + +import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.annotations.DelegateToWidget; +import com.vaadin.shared.annotations.NoLayout; + +/** + * State class for AbstractTextField. + */ +public abstract class AbstractTextFieldState extends AbstractFieldState { + + /** + * Maximum character count in text field. + */ + @DelegateToWidget + @NoLayout + public int maxLength = -1; + + /** + * Number of visible columns in the TextField. + */ + public int columns = 0; + + /** + * The prompt to display in an empty field. Null when disabled. + */ + @DelegateToWidget + @NoLayout + public String placeholder = null; + + /** + * The text in the field. + */ + @DelegateToWidget + @NoLayout + public String text = ""; + + @NoLayout + public ValueChangeMode valueChangeMode = ValueChangeMode.LAZY; + + @NoLayout + public int valueChangeTimeout = 400; + +} diff --git a/shared/src/main/java/com/vaadin/shared/ui/textfield/TextFieldState.java b/shared/src/main/java/com/vaadin/shared/ui/textfield/TextFieldState.java index f30af9ec78..02fe1c7f30 100644 --- a/shared/src/main/java/com/vaadin/shared/ui/textfield/TextFieldState.java +++ b/shared/src/main/java/com/vaadin/shared/ui/textfield/TextFieldState.java @@ -15,44 +15,11 @@ */ package com.vaadin.shared.ui.textfield; -import com.vaadin.shared.AbstractFieldState; -import com.vaadin.shared.annotations.DelegateToWidget; -import com.vaadin.shared.annotations.NoLayout; - -public class TextFieldState extends AbstractFieldState { +/** + * State class for TextField. + */ +public class TextFieldState extends AbstractTextFieldState { { primaryStyleName = "v-textfield"; } - - /** - * Maximum character count in text field. - */ - @DelegateToWidget - @NoLayout - public int maxLength = -1; - - /** - * Number of visible columns in the TextField. - */ - public int columns = 0; - - /** - * The prompt to display in an empty field. Null when disabled. - */ - @DelegateToWidget - @NoLayout - public String placeholder = null; - - /** - * The text in the field - */ - @DelegateToWidget - @NoLayout - public String text = ""; - - @NoLayout - public ValueChangeMode valueChangeMode = ValueChangeMode.LAZY; - - @NoLayout - public int valueChangeTimeout = 400; }