Change-Id: Ia2d357b77842bef188ae1f2a25e4a6a1c0a86dd0feature/vaadin8-book
@@ -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); | |||
} | |||
}); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} |
@@ -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; | |||
} |