package org.vaadin.viritin.fields;
import com.vaadin.event.FieldEvents.BlurListener;
import com.vaadin.event.FieldEvents.FocusListener;
import com.vaadin.server.ErrorMessage;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.Page;
import com.vaadin.server.Resource;
import com.vaadin.shared.Registration;
import com.vaadin.shared.ui.ValueChangeMode;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomField;
import com.vaadin.ui.Layout;
import com.vaadin.ui.TextField;
import com.vaadin.ui.themes.ValoTheme;
import org.vaadin.viritin.button.MButton;
import org.vaadin.viritin.layouts.MHorizontalLayout;
/**
* A textfield with an attached button, that clears the textfield. Most methods
* in this class delegate to the textfield, some to the button.
* ClearableTextField should work as a drop-in replacement for TextFiled /
* MTextField.
*
* @author Niki
*/
public class ClearableTextField extends CustomField {
private final TextField textfield = new TextField();
private final MButton clearButton = new MButton(FontAwesome.TIMES).withStyleName(ValoTheme.BUTTON_ICON_ONLY);
private final MHorizontalLayout root = new MHorizontalLayout()
.expand(textfield).add(clearButton)
.withSpacing(false)
.withFullWidth()
.withStyleName("clearable-textfield");
@SuppressWarnings("OverridableMethodCallInConstructor")
public ClearableTextField() {
clearButton.addClickListener(new Button.ClickListener() {
@Override
public void buttonClick(Button.ClickEvent event) {
textfield.clear();
textfield.focus();
}
});
textfield.addValueChangeListener(new ValueChangeListener<String>() {
@Override
public void valueChange(ValueChangeEvent<String> event) {
setValue(event.getValue());
}
});
textfield.setValueChangeMode(ValueChangeMode.LAZY);
setWidth("300px");
}
@SuppressWarnings("OverridableMethodCallInConstructor")
public ClearableTextField(String caption) {
this();
this.setCaption(caption);
}
@SuppressWarnings("OverridableMethodCallInConstructor")
public ClearableTextField(String caption, String value) {
this();
this.setCaption(caption);
textfield.setValue(value);
}
/**
*
* @return The TextField from the composition
*/
public TextField getTextfield() {
return textfield;
}
/**
*
* @return The root CssLayout
*/
public Layout getRoot() {
return root;
}
/**
*
* @return The Button
*/
public MButton getClearButton() {
return clearButton;
}
@Override
public void setReadOnly(boolean readOnly) {
super.setReadOnly(readOnly);
textfield.setReadOnly(readOnly);
clearButton.setEnabled(!readOnly);
}
/**
* A method to add custom click listener to the clear button.
*
* @return the listener registration
* @see Button#addClickListener(Button.ClickListener listener)
* @param listener the listener to be added to the clear button
*/
public Registration addClickListener(Button.ClickListener listener) {
return clearButton.addClickListener(listener);
}
public void click() {
clearButton.click();
}
public void setClickShortcut(int keyCode, int... modifiers) {
clearButton.setClickShortcut(keyCode, modifiers);
}
public void removeClickShortcut() {
clearButton.removeClickShortcut();
}
public void setIcon(Resource icon, String iconAltText) {
clearButton.setIcon(icon, iconAltText);
}
public String getIconAlternateText() {
return clearButton.getIconAlternateText();
}
public void setIconAlternateText(String iconAltText) {
clearButton.setIconAlternateText(iconAltText);
}
public void setHtmlContentAllowed(boolean htmlContentAllowed) {
clearButton.setHtmlContentAllowed(htmlContentAllowed);
}
public boolean isHtmlContentAllowed() {
return clearButton.isHtmlContentAllowed();
}
@Override
public void clear() {
super.clear();
textfield.clear();
}
@Override
public boolean isEmpty() {
return super.isEmpty();
}
public int getMaxLength() {
return textfield.getMaxLength();
}
public void setMaxLength(int maxLength) {
textfield.setMaxLength(maxLength);
}
public String getPlaceholder() {
return textfield.getPlaceholder();
}
public void setPlaceholder(String inputPrompt) {
textfield.setPlaceholder(inputPrompt);
}
public void selectAll() {
textfield.selectAll();
}
public void setSelection(int pos, int length) {
textfield.setSelection(pos, length);
}
public void setCursorPosition(int pos) {
textfield.setCursorPosition(pos);
}
public int getCursorPosition() {
return textfield.getCursorPosition();
}
public Registration addFocusListener(FocusListener listener) {
return textfield.addFocusListener(listener);
}
public Registration addBlurListener(BlurListener listener) {
return textfield.addBlurListener(listener);
}
public ClearableTextField withCaption(String caption) {
super.setCaption(caption);
return this;
}
public ClearableTextField withFullWidth() {
this.setWidth("100%");
return this;
}
public ClearableTextField withValue(String value) {
setValue(value);
return this;
}
@Override
public ErrorMessage getErrorMessage() {
final ErrorMessage errorMessage = super.getErrorMessage();
if (errorMessage == null) {
textfield.removeStyleName("error");
} else {
textfield.addStyleName("error");
}
return errorMessage;
}
@Override
public void setComponentError(ErrorMessage componentError) {
super.setComponentError(componentError);
if (componentError == null) {
textfield.removeStyleName("error");
} else {
textfield.addStyleName("error");
}
}
@Override
public void focus() {
textfield.focus();
}
@Override
protected Component initContent() {
return root;
}
@Override
public void attach() {
super.attach();
// TODO optimize this so that it is added only once
Page.getCurrent().getStyles().add(
".clearable-textfield .v-widget {\n"
+ " border-radius: 4px 4px 4px 4px;\n"
+ "}\n"
+ ".clearable-textfield .v-slot:last-child>.v-widget {\n"
+ " border-top-left-radius: 0;\n"
+ " border-bottom-left-radius: 0; margin-left:-1px\n"
+ "}\n"
+ "\n"
+ ".clearable-textfield .v-slot:first-child>.v-widget {\n"
+ " border-top-right-radius: 0;\n"
+ " border-bottom-right-radius: 0;\n"
+ "}\n");
}
@Override
protected void doSetValue(Object newValue) {
textfield.setValue(newValue.toString());
}
@Override
public Object getValue() {
return textfield.getValue();
}
}