diff options
5 files changed, 509 insertions, 0 deletions
diff --git a/client/src/main/java/com/vaadin/client/connectors/fields/TextFieldConnector.java b/client/src/main/java/com/vaadin/client/connectors/fields/TextFieldConnector.java new file mode 100644 index 0000000000..006e6ebe90 --- /dev/null +++ b/client/src/main/java/com/vaadin/client/connectors/fields/TextFieldConnector.java @@ -0,0 +1,92 @@ +/* + * 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.client.connectors.fields; + +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.event.dom.client.ChangeEvent; +import com.google.gwt.event.dom.client.ChangeHandler; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.TextBox; +import com.vaadin.client.communication.StateChangeEvent; +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.Connect.LoadStyle; +import com.vaadin.shared.ui.components.fields.TextFieldServerRpc; +import com.vaadin.shared.ui.components.fields.TextFieldState; + +@Connect(value = com.vaadin.ui.components.fields.TextField.class, loadStyle = LoadStyle.EAGER) +public class TextFieldConnector extends AbstractComponentConnector { + + @Override + protected void init() { + getWidget().addChangeHandler(new ChangeHandler() { + + @Override + public void onChange(ChangeEvent event) { + getRpcProxy(TextFieldServerRpc.class) + .setText(getWidget().getValue()); + } + }); + } + + @Override + public TextFieldState getState() { + return (TextFieldState) super.getState(); + } + + @Override + public TextBox getWidget() { + return (TextBox) super.getWidget(); + } + + @Override + public void onStateChanged(StateChangeEvent stateChangeEvent) { + // TODO Split into separate @OnStateChanged methods + super.onStateChanged(stateChangeEvent); + + final TextBox w = getWidget(); + final TextFieldState state = getState(); + + w.setReadOnly(state.readOnly); + + if (state.placeholder != null) { + w.getElement().setAttribute("placeholder", state.placeholder); + } else { + w.getElement().removeAttribute("placeholder"); + } + if (state.maxLength >= 0) { + w.setMaxLength(state.maxLength); + } else { + w.getElement().removeAttribute("maxlength"); + } + + w.setValue(state.text); + + if (state.selectionStart != -1) { + /* + * Gecko defers setting the text so we need to defer the selection. + */ + Scheduler.get().scheduleDeferred(new Command() { + @Override + public void execute() { + w.setSelectionRange(state.selectionStart, + state.selectionLength); + } + }); + } + } +} diff --git a/server/src/main/java/com/vaadin/ui/components/fields/AbstractTextField.java b/server/src/main/java/com/vaadin/ui/components/fields/AbstractTextField.java new file mode 100644 index 0000000000..81c72a69ce --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/components/fields/AbstractTextField.java @@ -0,0 +1,244 @@ +/* + * 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.ui.components.fields; + +import java.util.Collection; + +import org.jsoup.nodes.Attributes; +import org.jsoup.nodes.Element; + +import com.vaadin.event.FieldEvents.BlurEvent; +import com.vaadin.event.FieldEvents.BlurListener; +import com.vaadin.event.FieldEvents.FocusEvent; +import com.vaadin.event.FieldEvents.FocusListener; +import com.vaadin.event.FieldEvents.TextChangeEvent; +import com.vaadin.event.FieldEvents.TextChangeListener; +import com.vaadin.event.handler.Handler; +import com.vaadin.event.handler.Registration; +import com.vaadin.shared.ui.components.fields.TextFieldServerRpc; +import com.vaadin.shared.ui.components.fields.TextFieldState; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.components.HasValue; +import com.vaadin.ui.declarative.DesignAttributeHandler; +import com.vaadin.ui.declarative.DesignContext; + +/** + * Abstract base class for text input components. + * + * @author Vaadin Ltd. + */ +public abstract class AbstractTextField extends AbstractComponent + implements HasValue<String> { + + protected AbstractTextField() { + registerRpc(new TextFieldServerRpc() { + + @Override + public void blur() { + fireEvent(new BlurEvent(AbstractTextField.this)); + } + + @Override + public void focus() { + fireEvent(new FocusEvent(AbstractTextField.this)); + } + + @Override + public void setText(String text) { + if (!isReadOnly()) { + setValue(text); + fireEvent(new TextChangeEvent(AbstractTextField.this) { + + @Override + public String getText() { + return text; + } + + @Override + public int getCursorPosition() { + return 0; // TODO + } + }); + } + } + }); + } + + @Override + protected TextFieldState getState() { + return (TextFieldState) super.getState(); + } + + @Override + protected TextFieldState getState(boolean markAsDirty) { + return (TextFieldState) super.getState(markAsDirty); + } + + /** + * Returns the maximum number of characters in the field. Value -1 is + * considered unlimited. Terminal may however have some technical limits. + * + * @return the maxLength + */ + public int getMaxLength() { + return getState(false).maxLength; + } + + /** + * Sets the maximum number of characters in the field. Value -1 is + * considered unlimited. Terminal may however have some technical limits. + * + * @param maxLength + * the maxLength to set + */ + public void setMaxLength(int maxLength) { + getState().maxLength = maxLength; + } + + /** + * Returns the current placeholder text. + * + * @see #setPlaceholder(String) + * @return the placeholder text + */ + public String getPlaceholder() { + return getState(false).placeholder; + } + + /** + * Sets the placeholder text. The placeholder is text that is displayed when + * the field would otherwise be empty, to prompt the user for input. + * + * @param placeholder + * the placeholder text to set + */ + public void setPlaceholder(String placeholder) { + getState().placeholder = placeholder; + } + + @Override + public void setValue(String text) { + // TODO Accept nulls or not? + getState().text = text; + } + + @Override + public String getValue() { + return getState(false).text; + } + + @Override + public Registration onChange(Handler<String> handler) { + TextChangeListener l = e -> handler + .handleEvent(new com.vaadin.event.handler.Event<String>(this, + e.getText(), true)); + + addListener(TextChangeListener.EVENT_ID, TextChangeEvent.class, l, + TextChangeListener.EVENT_METHOD); + + return () -> removeListener(TextChangeEvent.class, l); + } + + /** + * Selects all text in the field. + * + */ + public void selectAll() { + // TODO Do we need this API? Or provide as extension? + setSelection(0, getValue().length()); + } + + /** + * Sets the range of text to be selected. + * + * As a side effect the field will become focused. + * + * @param pos + * the position of the first character to be selected + * @param length + * the number of characters to be selected + */ + public void setSelection(int start, int length) { + // TODO Do we need this API? Or provide as extension? + getState().selectionStart = start; + getState().selectionLength = length; + focus(); + } + + /** + * Sets the cursor position in the field. As a side effect the field will + * become focused. + * + * @param pos + * the position for the cursor + */ + public void setCursorPosition(int pos) { + setSelection(pos, 0); + } + + @Deprecated + public void addFocusListener(FocusListener listener) { + addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener, + FocusListener.focusMethod); + } + + @Deprecated + public void removeFocusListener(FocusListener listener) { + removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener); + } + + @Deprecated + public void addBlurListener(BlurListener listener) { + addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener, + BlurListener.blurMethod); + } + + @Deprecated + public void removeBlurListener(BlurListener listener) { + removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener); + } + + @Override + public void readDesign(Element design, DesignContext designContext) { + super.readDesign(design, designContext); + Attributes attr = design.attributes(); + if (attr.hasKey("maxlength")) { + setMaxLength(DesignAttributeHandler.readAttribute("maxlength", attr, + Integer.class)); + } + } + + @Override + protected Collection<String> getCustomAttributes() { + Collection<String> customAttributes = super.getCustomAttributes(); + customAttributes.add("maxlength"); + customAttributes.add("max-length"); // to prevent this appearing in + // output + customAttributes.add("cursor-position"); + return customAttributes; + } + + @Override + public void writeDesign(Element design, DesignContext designContext) { + super.writeDesign(design, designContext); + AbstractTextField def = (AbstractTextField) designContext + .getDefaultInstance(this); + Attributes attr = design.attributes(); + DesignAttributeHandler.writeAttribute("maxlength", attr, getMaxLength(), + def.getMaxLength(), Integer.class); + } +} diff --git a/server/src/main/java/com/vaadin/ui/components/fields/TextField.java b/server/src/main/java/com/vaadin/ui/components/fields/TextField.java new file mode 100644 index 0000000000..c691a92184 --- /dev/null +++ b/server/src/main/java/com/vaadin/ui/components/fields/TextField.java @@ -0,0 +1,98 @@ +/* + * 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.ui.components.fields; + +import org.jsoup.nodes.Attributes; +import org.jsoup.nodes.Element; + +import com.vaadin.data.Property; +import com.vaadin.ui.TextArea; +import com.vaadin.ui.declarative.DesignAttributeHandler; +import com.vaadin.ui.declarative.DesignContext; + +/** + * A component for editing textual data that fits on a single line. For a + * multi-line textarea, see the {@link TextArea} component. + * + * @author Vaadin Ltd. + */ +@SuppressWarnings("serial") +public class TextField extends AbstractTextField { + + /** + * Constructs an empty <code>TextField</code> with no caption. + */ + public TextField() { + clear(); + } + + /** + * Constructs an empty <code>TextField</code> with given caption. + * + * @param caption + * the caption <code>String</code> for the editor. + */ + public TextField(String caption) { + this(); + setCaption(caption); + } + + /** + * Constructs a new <code>TextField</code> with the given caption and + * initial text contents. The editor constructed this way will not be bound + * to a Property unless + * {@link com.vaadin.data.Property.Viewer#setPropertyDataSource(Property)} + * is called to bind it. + * + * @param caption + * the caption <code>String</code> for the editor. + * @param value + * the initial text content of the editor. + */ + public TextField(String caption, String value) { + setValue(value); + setCaption(caption); + } + + /** + * Clears the value of this TextField. + */ + public void clear() { + setValue(""); + } + + @Override + public void readDesign(Element design, DesignContext designContext) { + super.readDesign(design, designContext); + Attributes attr = design.attributes(); + if (attr.hasKey("value")) { + String text = DesignAttributeHandler.readAttribute("value", attr, + String.class); + getState(false).text = text; + } + } + + @Override + public void writeDesign(Element design, DesignContext designContext) { + super.writeDesign(design, designContext); + AbstractTextField def = (AbstractTextField) designContext + .getDefaultInstance(this); + Attributes attr = design.attributes(); + DesignAttributeHandler.writeAttribute("value", attr, getValue(), + def.getValue(), String.class); + } +} diff --git a/shared/src/main/java/com/vaadin/shared/ui/components/fields/TextFieldServerRpc.java b/shared/src/main/java/com/vaadin/shared/ui/components/fields/TextFieldServerRpc.java new file mode 100644 index 0000000000..679aba3430 --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/ui/components/fields/TextFieldServerRpc.java @@ -0,0 +1,24 @@ +/* + * 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.shared.ui.components.fields; + +import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc; + +public interface TextFieldServerRpc extends FocusAndBlurServerRpc { + + public void setText(String text); +} diff --git a/shared/src/main/java/com/vaadin/shared/ui/components/fields/TextFieldState.java b/shared/src/main/java/com/vaadin/shared/ui/components/fields/TextFieldState.java new file mode 100644 index 0000000000..07848388c8 --- /dev/null +++ b/shared/src/main/java/com/vaadin/shared/ui/components/fields/TextFieldState.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2014 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.shared.ui.components.fields; + +import com.vaadin.shared.AbstractFieldState; +import com.vaadin.shared.annotations.NoLayout; + +public class TextFieldState extends AbstractFieldState { + { + primaryStyleName = "v-textfield"; + } + + /** + * Maximum character count in text field. + */ + @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. + */ + @NoLayout + public String placeholder = null; + + /** + * The text in the field + */ + @NoLayout + public String text = ""; + + public int selectionStart = -1; + public int selectionLength = 0; +} |