]> source.dussan.org Git - vaadin-framework.git/commitdiff
#5865: Extracted AbstractTextField from TextField, RichTextEditor extends now that...
authorMatti Tahvonen <matti.tahvonen@itmill.com>
Tue, 26 Oct 2010 15:13:30 +0000 (15:13 +0000)
committerMatti Tahvonen <matti.tahvonen@itmill.com>
Tue, 26 Oct 2010 15:13:30 +0000 (15:13 +0000)
Also fixes focus and selectAll in RichTextArea. More complicated selections methods removed from RichTextArea, at least until it is possible to implement them with GWT RichTextArea.

svn changeset:15725/svn branch:6.5

src/com/vaadin/terminal/gwt/client/ui/richtextarea/VRichTextArea.java
src/com/vaadin/ui/AbstractTextField.java [new file with mode: 0644]
src/com/vaadin/ui/RichTextArea.java
src/com/vaadin/ui/TextArea.java
src/com/vaadin/ui/TextField.java

index 8dcae8e735444928390c165eb7767e07a8620309..5ababb6c24f7c8ea060469d9ad78c572948fe30f 100644 (file)
@@ -18,8 +18,10 @@ import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Timer;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Focusable;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.RichTextArea;
 import com.google.gwt.user.client.ui.Widget;
@@ -41,7 +43,7 @@ import com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler.ShortcutActionHan
  */
 public class VRichTextArea extends Composite implements Paintable, Field,
         ChangeHandler, BlurHandler, KeyPressHandler, KeyDownHandler,
-        BeforeShortcutActionListener {
+        BeforeShortcutActionListener, Focusable {
 
     /**
      * The input node CSS classname.
@@ -159,6 +161,33 @@ public class VRichTextArea extends Composite implements Paintable, Field,
             maxLength = -1;
             keyPressHandler.removeHandler();
         }
+
+        if (uidl.hasAttribute("selectAll")) {
+            selectAll();
+        }
+
+    }
+
+    private void selectAll() {
+        /*
+         * There is a timing issue if trying to select all immediately on first
+         * render. Simple deferred command is not enough. Using Timer with
+         * moderated timeout. If this appears to fail on many (most likely slow)
+         * environments, consider increasing the timeout.
+         * 
+         * FF seems to require the most time to stabilize its RTA. On Vaadin
+         * tiergarden test machines, 200ms was not enough always (about 50%
+         * success rate) - 300 ms was 100% successful. This however was not
+         * enough on a sluggish old non-virtualized XP test machine. A bullet
+         * proof solution would be nice, GWT 2.1 might however solve these. At
+         * least setFocus has a workaround for this kind of issue.
+         */
+        new Timer() {
+            @Override
+            public void run() {
+                rta.getFormatter().selectAll();
+            }
+        }.schedule(320);
     }
 
     private void setReadOnly(boolean b) {
@@ -195,6 +224,7 @@ public class VRichTextArea extends Composite implements Paintable, Field,
 
     public void onBlur(BlurEvent event) {
         synchronizeContentToServer();
+        // TODO notify possible server side blur/focus listeners
     }
 
     /**
@@ -338,4 +368,30 @@ public class VRichTextArea extends Composite implements Paintable, Field,
         synchronizeContentToServer();
     }
 
+    public int getTabIndex() {
+        return rta.getTabIndex();
+    }
+
+    public void setAccessKey(char key) {
+        rta.setAccessKey(key);
+    }
+
+    public void setFocus(boolean focused) {
+        /*
+         * Similar issue as with selectAll. Focusing must happen before possible
+         * selectall, so keep the timeout here lower.
+         */
+        new Timer() {
+
+            @Override
+            public void run() {
+                rta.setFocus(true);
+            }
+        }.schedule(300);
+    }
+
+    public void setTabIndex(int index) {
+        rta.setTabIndex(index);
+    }
+
 }
diff --git a/src/com/vaadin/ui/AbstractTextField.java b/src/com/vaadin/ui/AbstractTextField.java
new file mode 100644 (file)
index 0000000..7fe1306
--- /dev/null
@@ -0,0 +1,349 @@
+package com.vaadin.ui;
+
+import java.text.Format;
+import java.util.Map;
+
+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.terminal.PaintException;
+import com.vaadin.terminal.PaintTarget;
+
+public abstract class AbstractTextField extends AbstractField {
+
+    /**
+     * Value formatter used to format the string contents.
+     */
+    private Format format;
+
+    /**
+     * Null representation.
+     */
+    private String nullRepresentation = "null";
+    /**
+     * Is setting to null from non-null value allowed by setting with null
+     * representation .
+     */
+    private boolean nullSettingAllowed = false;
+    /**
+     * Maximum character count in text field.
+     */
+    private int maxLength = -1;
+
+    public AbstractTextField() {
+        super();
+    }
+
+    @Override
+    public void paintContent(PaintTarget target) throws PaintException {
+        super.paintContent(target);
+
+        if (getMaxLength() >= 0) {
+            target.addAttribute("maxLength", getMaxLength());
+        }
+
+        // Adds the content as variable
+        String value = getFormattedValue();
+        if (value == null) {
+            value = getNullRepresentation();
+        }
+        if (value == null) {
+            throw new IllegalStateException(
+                    "Null values are not allowed if the null-representation is null");
+        }
+        target.addVariable(this, "text", value);
+    }
+
+    /**
+     * Gets the formatted string value. Sets the field value by using the
+     * assigned Format.
+     * 
+     * @return the Formatted value.
+     * @see #setFormat(Format)
+     * @see Format
+     * @deprecated
+     */
+    @Deprecated
+    protected String getFormattedValue() {
+        Object v = getValue();
+        if (v == null) {
+            return null;
+        }
+        return v.toString();
+    }
+
+    @Override
+    public Object getValue() {
+        Object v = super.getValue();
+        if (format == null || v == null) {
+            return v;
+        }
+        try {
+            return format.format(v);
+        } catch (final IllegalArgumentException e) {
+            return v;
+        }
+    }
+
+    @Override
+    public void changeVariables(Object source, Map<String, Object> variables) {
+
+        super.changeVariables(source, variables);
+
+        // Sets the text
+        if (variables.containsKey("text") && !isReadOnly()) {
+
+            // Only do the setting if the string representation of the value
+            // has been updated
+            String newValue = (String) variables.get("text");
+
+            // server side check for max length
+            if (getMaxLength() != -1 && newValue.length() > getMaxLength()) {
+                newValue = newValue.substring(0, getMaxLength());
+            }
+            final String oldValue = getFormattedValue();
+            if (newValue != null
+                    && (oldValue == null || isNullSettingAllowed())
+                    && newValue.equals(getNullRepresentation())) {
+                newValue = null;
+            }
+            if (newValue != oldValue
+                    && (newValue == null || !newValue.equals(oldValue))) {
+                boolean wasModified = isModified();
+                setValue(newValue, true);
+
+                // If the modified status changes, or if we have a formatter,
+                // repaint is needed after all.
+                if (format != null || wasModified != isModified()) {
+                    requestRepaint();
+                }
+            }
+        }
+
+        if (variables.containsKey(FocusEvent.EVENT_ID)) {
+            fireEvent(new FocusEvent(this));
+        }
+        if (variables.containsKey(BlurEvent.EVENT_ID)) {
+            fireEvent(new BlurEvent(this));
+        }
+
+    }
+
+    /**
+     * Sets the height of the {@link TextField} instance.
+     * 
+     * <p>
+     * Setting height for {@link TextField} also has a side-effect that puts
+     * {@link TextField} into multiline mode (aka "textarea"). Multiline mode
+     * can also be achieved by calling {@link #setRows(int)}. The height value
+     * overrides the number of rows set by {@link #setRows(int)}.
+     * <p>
+     * If you want to set height of single line {@link TextField}, call
+     * {@link #setRows(int)} with value 0 after setting the height. Setting rows
+     * to 0 resets the side-effect.
+     * 
+     * @see com.vaadin.ui.AbstractComponent#setHeight(float, int)
+     */
+    @Override
+    public void setHeight(float height, int unit) {
+        super.setHeight(height, unit);
+        if (height > 1 && this instanceof TextField) {
+            /*
+             * In html based terminals we most commonly want to make component
+             * to be textarea if height is defined. Setting row field above 0
+             * will render component as textarea.
+             */
+
+            ((TextField) this).setRows(2);
+        }
+    }
+
+    /**
+     * Sets the height of the {@link TextField} instance.
+     * 
+     * <p>
+     * Setting height for {@link TextField} also has a side-effect that puts
+     * {@link TextField} into multiline mode (aka "textarea"). Multiline mode
+     * can also be achieved by calling {@link #setRows(int)}. The height value
+     * overrides the number of rows set by {@link #setRows(int)}.
+     * <p>
+     * If you want to set height of single line {@link TextField}, call
+     * {@link #setRows(int)} with value 0 after setting the height. Setting rows
+     * to 0 resets the side-effect.
+     * 
+     * @see com.vaadin.ui.AbstractComponent#setHeight(java.lang.String)
+     */
+    @Override
+    public void setHeight(String height) {
+        // will call setHeight(float, int) the actually does the magic. Method
+        // is overridden just to document side-effects.
+        super.setHeight(height);
+    }
+
+    @Override
+    public Class getType() {
+        return String.class;
+    }
+
+    /**
+     * Gets the null-string representation.
+     * 
+     * <p>
+     * The null-valued strings are represented on the user interface by
+     * replacing the null value with this string. If the null representation is
+     * set null (not 'null' string), painting null value throws exception.
+     * </p>
+     * 
+     * <p>
+     * The default value is string 'null'.
+     * </p>
+     * 
+     * @return the String Textual representation for null strings.
+     * @see TextField#isNullSettingAllowed()
+     */
+    public String getNullRepresentation() {
+        return nullRepresentation;
+    }
+
+    /**
+     * Is setting nulls with null-string representation allowed.
+     * 
+     * <p>
+     * If this property is true, writing null-representation string to text
+     * field always sets the field value to real null. If this property is
+     * false, null setting is not made, but the null values are maintained.
+     * Maintenance of null-values is made by only converting the textfield
+     * contents to real null, if the text field matches the null-string
+     * representation and the current value of the field is null.
+     * </p>
+     * 
+     * <p>
+     * By default this setting is false
+     * </p>
+     * 
+     * @return boolean Should the null-string represenation be always converted
+     *         to null-values.
+     * @see TextField#getNullRepresentation()
+     */
+    public boolean isNullSettingAllowed() {
+        return nullSettingAllowed;
+    }
+
+    /**
+     * Sets the null-string representation.
+     * 
+     * <p>
+     * The null-valued strings are represented on the user interface by
+     * replacing the null value with this string. If the null representation is
+     * set null (not 'null' string), painting null value throws exception.
+     * </p>
+     * 
+     * <p>
+     * The default value is string 'null'
+     * </p>
+     * 
+     * @param nullRepresentation
+     *            Textual representation for null strings.
+     * @see TextField#setNullSettingAllowed(boolean)
+     */
+    public void setNullRepresentation(String nullRepresentation) {
+        this.nullRepresentation = nullRepresentation;
+    }
+
+    /**
+     * Sets the null conversion mode.
+     * 
+     * <p>
+     * If this property is true, writing null-representation string to text
+     * field always sets the field value to real null. If this property is
+     * false, null setting is not made, but the null values are maintained.
+     * Maintenance of null-values is made by only converting the textfield
+     * contents to real null, if the text field matches the null-string
+     * representation and the current value of the field is null.
+     * </p>
+     * 
+     * <p>
+     * By default this setting is false.
+     * </p>
+     * 
+     * @param nullSettingAllowed
+     *            Should the null-string represenation be always converted to
+     *            null-values.
+     * @see TextField#getNullRepresentation()
+     */
+    public void setNullSettingAllowed(boolean nullSettingAllowed) {
+        this.nullSettingAllowed = nullSettingAllowed;
+    }
+
+    /**
+     * Gets the value formatter of TextField.
+     * 
+     * @return the Format used to format the value.
+     * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter}
+     */
+    @Deprecated
+    public Format getFormat() {
+        return format;
+    }
+
+    /**
+     * Gets the value formatter of TextField.
+     * 
+     * @param format
+     *            the Format used to format the value. Null disables the
+     *            formatting.
+     * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter}
+     */
+    @Deprecated
+    public void setFormat(Format format) {
+        this.format = format;
+        requestRepaint();
+    }
+
+    @Override
+    protected boolean isEmpty() {
+        return super.isEmpty() || toString().length() == 0;
+    }
+
+    /**
+     * 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 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) {
+        this.maxLength = maxLength;
+        requestRepaint();
+    }
+
+    public void addListener(FocusListener listener) {
+        addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
+                FocusListener.focusMethod);
+    }
+
+    public void removeListener(FocusListener listener) {
+        removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener);
+    }
+
+    public void addListener(BlurListener listener) {
+        addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
+                BlurListener.blurMethod);
+    }
+
+    public void removeListener(BlurListener listener) {
+        removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener);
+    }
+
+}
\ No newline at end of file
index bb7b6e58c14f959ff35407c58fa43f34bdc74f99..8b640dc3600d0b0b73b8db6faf7ff49793e1fb6d 100644 (file)
@@ -19,7 +19,9 @@ import com.vaadin.ui.ClientWidget.LoadStyle;
  */
 @SuppressWarnings("serial")
 @ClientWidget(value = VRichTextArea.class, loadStyle = LoadStyle.LAZY)
-public class RichTextArea extends TextField {
+public class RichTextArea extends AbstractTextField {
+
+    private boolean selectAll;
 
     /**
      * Constructs an empty <code>RichTextArea</code> with no caption.
@@ -36,7 +38,7 @@ public class RichTextArea extends TextField {
      *            the caption for the editor.
      */
     public RichTextArea(String caption) {
-        super(caption);
+        setCaption(caption);
     }
 
     /**
@@ -47,7 +49,7 @@ public class RichTextArea extends TextField {
      *            the data source for the editor value
      */
     public RichTextArea(Property dataSource) {
-        super(dataSource);
+        setPropertyDataSource(dataSource);
     }
 
     /**
@@ -60,7 +62,8 @@ public class RichTextArea extends TextField {
      *            the data source for the editor value
      */
     public RichTextArea(String caption, Property dataSource) {
-        super(caption, dataSource);
+        this(dataSource);
+        setCaption(caption);
     }
 
     /**
@@ -73,24 +76,19 @@ public class RichTextArea extends TextField {
      *            the initial text content of the editor.
      */
     public RichTextArea(String caption, String value) {
-        super(caption, value);
+        this(caption);
+        setValue(value);
     }
 
     @Override
     public void paintContent(PaintTarget target) throws PaintException {
-        target.addAttribute("richtext", true);
+        if (selectAll) {
+            target.addAttribute("selectAll", true);
+            selectAll = false;
+        }
         super.paintContent(target);
     }
 
-    /**
-     * RichTextArea does not support input prompt.
-     */
-    @Override
-    public void setInputPrompt(String inputPrompt) {
-        throw new UnsupportedOperationException(
-                "RichTextArea does not support inputPrompt");
-    }
-
     @Override
     public void setReadOnly(boolean readOnly) {
         super.setReadOnly(readOnly);
@@ -102,4 +100,24 @@ public class RichTextArea extends TextField {
         }
     }
 
+    /**
+     * Selects all text in the rich text area. As a side effect, focuses the
+     * rich text area.
+     * 
+     * @since 6.5
+     */
+    public void selectAll() {
+        /*
+         * Set selection range functionality is currently being
+         * planned/developed for GWT RTA. Only selecting all is currently
+         * supported. Consider moving selectAll and other selection related
+         * functions to AbstractTextField at that point to share the
+         * implementation. Some third party components extending
+         * AbstractTextField might however not want to support them.
+         */
+        selectAll = true;
+        focus();
+        requestRepaint();
+    }
+
 }
index 1b8d6dc687a3ace3eee64eca6dcc5fd0a6504a93..edc8d3ecaee9c5e8995879306379fb64380484fd 100644 (file)
@@ -41,7 +41,7 @@ public class TextArea extends TextField {
     @Override
     public void setRows(int rows) {
         // TODO implement here once AbstractTextField (or something similar is
-        // created).
+        // created) and incompatible API can be introduced.
         super.setRows(rows);
     }
 
@@ -55,7 +55,7 @@ public class TextArea extends TextField {
     @Override
     public int getRows() {
         // TODO implement here once AbstractTextField (or something similar is
-        // created).
+        // created) and incompatible API can be introduced.
         return super.getRows();
     }
 
index c2d0aee29f677fe7bda1c42f2edec864befc97f2..81e586a5058b38630dc89823834f88ee1827e9fc 100644 (file)
@@ -4,15 +4,8 @@
 
 package com.vaadin.ui;
 
-import java.text.Format;
-import java.util.Map;
-
 import com.vaadin.data.Property;
 import com.vaadin.event.FieldEvents;
-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.terminal.PaintException;
 import com.vaadin.terminal.PaintTarget;
 import com.vaadin.terminal.gwt.client.ui.VTextField;
@@ -40,20 +33,14 @@ import com.vaadin.ui.ClientWidget.LoadStyle;
  */
 @SuppressWarnings("serial")
 @ClientWidget(value = VTextField.class, loadStyle = LoadStyle.EAGER)
-public class TextField extends AbstractField implements
+public class TextField extends AbstractTextField implements
         FieldEvents.BlurNotifier, FieldEvents.FocusNotifier {
 
-    /* Private members */
-
-    /**
-     * Value formatter used to format the string contents.
-     */
-    private Format format;
-
     /**
-     * Number of visible columns in the TextField.
+     * Tells if input is used to enter sensitive information that is not echoed
+     * to display. Typically passwords.
      */
-    private int columns = 0;
+    private boolean secret = false;
 
     /**
      * Number of visible rows in a multiline TextField. Value 0 implies a
@@ -67,35 +54,15 @@ public class TextField extends AbstractField implements
     private boolean wordwrap = true;
 
     /**
-     * Tells if input is used to enter sensitive information that is not echoed
-     * to display. Typically passwords.
-     */
-    private boolean secret = false;
-
-    /**
-     * Null representation.
-     */
-    private String nullRepresentation = "null";
-
-    /**
-     * Is setting to null from non-null value allowed by setting with null
-     * representation .
+     * Number of visible columns in the TextField.
      */
-    private boolean nullSettingAllowed = false;
+    private int columns = 0;
 
     private String inputPrompt = null;
 
-    /**
-     * Maximum character count in text field.
-     */
-    private int maxLength = -1;
-
     private int selectionPosition = -1;
-
     private int selectionLength;
 
-    /* Constructors */
-
     /**
      * Constructs an empty <code>TextField</code> with no caption.
      */
@@ -156,173 +123,67 @@ public class TextField extends AbstractField implements
         setCaption(caption);
     }
 
-    /* Component basic features */
+    /**
+     * Gets the secret property on and off. If a field is used to enter
+     * secretinformation the information is not echoed to display.
+     * 
+     * @return <code>true</code> if the field is used to enter secret
+     *         information, <code>false</code> otherwise.
+     * 
+     * @deprecated use {@link PasswordField} instead
+     */
+    @Deprecated
+    public boolean isSecret() {
+        return secret;
+    }
 
-    /*
-     * Paints this component. Don't add a JavaDoc comment here, we use the
-     * default documentation from implemented interface.
+    /**
+     * Sets the secret property on and off. If a field is used to enter
+     * secretinformation the information is not echoed to display.
+     * 
+     * @param secret
+     *            the value specifying if the field is used to enter secret
+     *            information.
+     * @deprecated use {@link PasswordField} instead
      */
+    @Deprecated
+    public void setSecret(boolean secret) {
+        if (this.secret != secret) {
+            this.secret = secret;
+            requestRepaint();
+        }
+    }
+
     @Override
     public void paintContent(PaintTarget target) throws PaintException {
-        super.paintContent(target);
-
-        // Sets the secret attribute
         if (isSecret()) {
             target.addAttribute("secret", true);
         }
-
-        if (getMaxLength() >= 0) {
-            target.addAttribute("maxLength", getMaxLength());
-        }
-
-        if (inputPrompt != null) {
-            target.addAttribute("prompt", inputPrompt);
-        }
-        if (selectionPosition != -1) {
-            target.addAttribute("selpos", selectionPosition);
-            target.addAttribute("sellen", selectionLength);
-            selectionPosition = -1;
-        }
-
         // Adds the number of column and rows
         final int columns = getColumns();
-        final int rows = getRows();
         if (columns != 0) {
             target.addAttribute("cols", String.valueOf(columns));
         }
+        final int rows = getRows();
         if (rows != 0) {
             target.addAttribute("rows", String.valueOf(rows));
             target.addAttribute("multiline", true);
-            if (!wordwrap) {
+            if (!isWordwrap()) {
                 target.addAttribute("wordwrap", false);
             }
         }
 
-        // Adds the content as variable
-        String value = getFormattedValue();
-        if (value == null) {
-            value = getNullRepresentation();
-        }
-        if (value == null) {
-            throw new IllegalStateException(
-                    "Null values are not allowed if the null-representation is null");
-        }
-        target.addVariable(this, "text", value);
-    }
-
-    /**
-     * Gets the formatted string value. Sets the field value by using the
-     * assigned Format.
-     * 
-     * @return the Formatted value.
-     * @see #setFormat(Format)
-     * @see Format
-     * @deprecated
-     */
-    @Deprecated
-    protected String getFormattedValue() {
-        Object v = getValue();
-        if (v == null) {
-            return null;
-        }
-        return v.toString();
-    }
-
-    /*
-     * Gets the value of the field, but uses formatter is given. Don't add a
-     * JavaDoc comment here, we use the default documentation from implemented
-     * interface.
-     */
-    @Override
-    public Object getValue() {
-        Object v = super.getValue();
-        if (format == null || v == null) {
-            return v;
-        }
-        try {
-            return format.format(v);
-        } catch (final IllegalArgumentException e) {
-            return v;
-        }
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see com.vaadin.ui.AbstractField#changeVariables(java.lang.Object,
-     * java.util.Map)
-     */
-    @Override
-    public void changeVariables(Object source, Map<String, Object> variables) {
-
-        super.changeVariables(source, variables);
-
-        // Sets the text
-        if (variables.containsKey("text") && !isReadOnly()) {
-
-            // Only do the setting if the string representation of the value
-            // has been updated
-            String newValue = (String) variables.get("text");
-
-            // server side check for max length
-            if (getMaxLength() != -1 && newValue.length() > getMaxLength()) {
-                newValue = newValue.substring(0, getMaxLength());
-            }
-            final String oldValue = getFormattedValue();
-            if (newValue != null
-                    && (oldValue == null || isNullSettingAllowed())
-                    && newValue.equals(getNullRepresentation())) {
-                newValue = null;
-            }
-            if (newValue != oldValue
-                    && (newValue == null || !newValue.equals(oldValue))) {
-                boolean wasModified = isModified();
-                setValue(newValue, true);
-
-                // If the modified status changes, or if we have a formatter,
-                // repaint is needed after all.
-                if (format != null || wasModified != isModified()) {
-                    requestRepaint();
-                }
-            }
+        if (getInputPrompt() != null) {
+            target.addAttribute("prompt", getInputPrompt());
         }
 
-        if (variables.containsKey(FocusEvent.EVENT_ID)) {
-            fireEvent(new FocusEvent(this));
-        }
-        if (variables.containsKey(BlurEvent.EVENT_ID)) {
-            fireEvent(new BlurEvent(this));
+        if (selectionPosition != -1) {
+            target.addAttribute("selpos", selectionPosition);
+            target.addAttribute("sellen", selectionLength);
+            selectionPosition = -1;
         }
 
-    }
-
-    /* Text field configuration */
-
-    /**
-     * Gets the number of columns in the editor. If the number of columns is set
-     * 0, the actual number of displayed columns is determined implicitly by the
-     * adapter.
-     * 
-     * @return the number of columns in the editor.
-     */
-    public int getColumns() {
-        return columns;
-    }
-
-    /**
-     * Sets the number of columns in the editor. If the number of columns is set
-     * 0, the actual number of displayed columns is determined implicitly by the
-     * adapter.
-     * 
-     * @param columns
-     *            the number of columns to set.
-     */
-    public void setColumns(int columns) {
-        if (columns < 0) {
-            columns = 0;
-        }
-        this.columns = columns;
-        requestRepaint();
+        super.paintContent(target);
     }
 
     /**
@@ -362,56 +223,6 @@ public class TextField extends AbstractField implements
         }
     }
 
-    /**
-     * Sets the height of the {@link TextField} instance.
-     * 
-     * <p>
-     * Setting height for {@link TextField} also has a side-effect that puts
-     * {@link TextField} into multiline mode (aka "textarea"). Multiline mode
-     * can also be achieved by calling {@link #setRows(int)}. The height value
-     * overrides the number of rows set by {@link #setRows(int)}.
-     * <p>
-     * If you want to set height of single line {@link TextField}, call
-     * {@link #setRows(int)} with value 0 after setting the height. Setting rows
-     * to 0 resets the side-effect.
-     * 
-     * @see com.vaadin.ui.AbstractComponent#setHeight(float, int)
-     */
-    @Override
-    public void setHeight(float height, int unit) {
-        super.setHeight(height, unit);
-        if (height > 1) {
-            /*
-             * In html based terminals we most commonly want to make component
-             * to be textarea if height is defined. Setting row field above 0
-             * will render component as textarea.
-             */
-            rows = 2;
-        }
-    }
-
-    /**
-     * Sets the height of the {@link TextField} instance.
-     * 
-     * <p>
-     * Setting height for {@link TextField} also has a side-effect that puts
-     * {@link TextField} into multiline mode (aka "textarea"). Multiline mode
-     * can also be achieved by calling {@link #setRows(int)}. The height value
-     * overrides the number of rows set by {@link #setRows(int)}.
-     * <p>
-     * If you want to set height of single line {@link TextField}, call
-     * {@link #setRows(int)} with value 0 after setting the height. Setting rows
-     * to 0 resets the side-effect.
-     * 
-     * @see com.vaadin.ui.AbstractComponent#setHeight(java.lang.String)
-     */
-    @Override
-    public void setHeight(String height) {
-        // will call setHeight(float, int) the actually does the magic. Method
-        // is overridden just to document side-effects.
-        super.setHeight(height);
-    }
-
     /**
      * Tests if the editor is in word-wrap mode.
      * 
@@ -445,131 +256,31 @@ public class TextField extends AbstractField implements
         }
     }
 
-    /* Property features */
-
-    /*
-     * Gets the edited property's type. Don't add a JavaDoc comment here, we use
-     * the default documentation from implemented interface.
-     */
-    @Override
-    public Class getType() {
-        return String.class;
-    }
-
     /**
-     * Gets the secret property on and off. If a field is used to enter
-     * secretinformation the information is not echoed to display.
+     * Gets the number of columns in the editor. If the number of columns is set
+     * 0, the actual number of displayed columns is determined implicitly by the
+     * adapter.
      * 
-     * @return <code>true</code> if the field is used to enter secret
-     *         information, <code>false</code> otherwise.
+     * @return the number of columns in the editor.
      */
-    public boolean isSecret() {
-        return secret;
+    public int getColumns() {
+        return columns;
     }
 
     /**
-     * Sets the secret property on and off. If a field is used to enter
-     * secretinformation the information is not echoed to display.
+     * Sets the number of columns in the editor. If the number of columns is set
+     * 0, the actual number of displayed columns is determined implicitly by the
+     * adapter.
      * 
-     * @param secret
-     *            the value specifying if the field is used to enter secret
-     *            information.
+     * @param columns
+     *            the number of columns to set.
      */
-    public void setSecret(boolean secret) {
-        if (this.secret != secret) {
-            this.secret = secret;
-            requestRepaint();
+    public void setColumns(int columns) {
+        if (columns < 0) {
+            columns = 0;
         }
-    }
-
-    /**
-     * Gets the null-string representation.
-     * 
-     * <p>
-     * The null-valued strings are represented on the user interface by
-     * replacing the null value with this string. If the null representation is
-     * set null (not 'null' string), painting null value throws exception.
-     * </p>
-     * 
-     * <p>
-     * The default value is string 'null'.
-     * </p>
-     * 
-     * @return the String Textual representation for null strings.
-     * @see TextField#isNullSettingAllowed()
-     */
-    public String getNullRepresentation() {
-        return nullRepresentation;
-    }
-
-    /**
-     * Is setting nulls with null-string representation allowed.
-     * 
-     * <p>
-     * If this property is true, writing null-representation string to text
-     * field always sets the field value to real null. If this property is
-     * false, null setting is not made, but the null values are maintained.
-     * Maintenance of null-values is made by only converting the textfield
-     * contents to real null, if the text field matches the null-string
-     * representation and the current value of the field is null.
-     * </p>
-     * 
-     * <p>
-     * By default this setting is false
-     * </p>
-     * 
-     * @return boolean Should the null-string represenation be always converted
-     *         to null-values.
-     * @see TextField#getNullRepresentation()
-     */
-    public boolean isNullSettingAllowed() {
-        return nullSettingAllowed;
-    }
-
-    /**
-     * Sets the null-string representation.
-     * 
-     * <p>
-     * The null-valued strings are represented on the user interface by
-     * replacing the null value with this string. If the null representation is
-     * set null (not 'null' string), painting null value throws exception.
-     * </p>
-     * 
-     * <p>
-     * The default value is string 'null'
-     * </p>
-     * 
-     * @param nullRepresentation
-     *            Textual representation for null strings.
-     * @see TextField#setNullSettingAllowed(boolean)
-     */
-    public void setNullRepresentation(String nullRepresentation) {
-        this.nullRepresentation = nullRepresentation;
-    }
-
-    /**
-     * Sets the null conversion mode.
-     * 
-     * <p>
-     * If this property is true, writing null-representation string to text
-     * field always sets the field value to real null. If this property is
-     * false, null setting is not made, but the null values are maintained.
-     * Maintenance of null-values is made by only converting the textfield
-     * contents to real null, if the text field matches the null-string
-     * representation and the current value of the field is null.
-     * </p>
-     * 
-     * <p>
-     * By default this setting is false.
-     * </p>
-     * 
-     * @param nullSettingAllowed
-     *            Should the null-string represenation be always converted to
-     *            null-values.
-     * @see TextField#getNullRepresentation()
-     */
-    public void setNullSettingAllowed(boolean nullSettingAllowed) {
-        this.nullSettingAllowed = nullSettingAllowed;
+        this.columns = columns;
+        requestRepaint();
     }
 
     /**
@@ -593,76 +304,6 @@ public class TextField extends AbstractField implements
         requestRepaint();
     }
 
-    /**
-     * Gets the value formatter of TextField.
-     * 
-     * @return the Format used to format the value.
-     * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter}
-     */
-    @Deprecated
-    public Format getFormat() {
-        return format;
-    }
-
-    /**
-     * Gets the value formatter of TextField.
-     * 
-     * @param format
-     *            the Format used to format the value. Null disables the
-     *            formatting.
-     * @deprecated replaced by {@link com.vaadin.data.util.PropertyFormatter}
-     */
-    @Deprecated
-    public void setFormat(Format format) {
-        this.format = format;
-        requestRepaint();
-    }
-
-    @Override
-    protected boolean isEmpty() {
-        return super.isEmpty() || toString().length() == 0;
-    }
-
-    /**
-     * 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 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) {
-        this.maxLength = maxLength;
-        requestRepaint();
-    }
-
-    public void addListener(FocusListener listener) {
-        addListener(FocusEvent.EVENT_ID, FocusEvent.class, listener,
-                FocusListener.focusMethod);
-    }
-
-    public void removeListener(FocusListener listener) {
-        removeListener(FocusEvent.EVENT_ID, FocusEvent.class, listener);
-    }
-
-    public void addListener(BlurListener listener) {
-        addListener(BlurEvent.EVENT_ID, BlurEvent.class, listener,
-                BlurListener.blurMethod);
-    }
-
-    public void removeListener(BlurListener listener) {
-        removeListener(BlurEvent.EVENT_ID, BlurEvent.class, listener);
-    }
-
     /**
      * Selects all text in the field.
      *