@@ -0,0 +1,146 @@
+package com.andreabaccega.widget;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.widget.AutoCompleteTextView;
+import android.widget.EditText;
+
+/**
+ * AutoCompleteTextView Extension to be used in order to create forms in android.
+ *
+ * @author Said Tahsin Dane <tasomaniac@gmail.com>
+ */
+public class FormAutoCompleteTextView extends AutoCompleteTextView {
+    public FormAutoCompleteTextView(Context context) {
+        super(context);
+        // FIXME how should this constructor be handled
+        throw new RuntimeException("Not supported");
+    }
+
+    public FormAutoCompleteTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        editTextValidator = new DefaultEditTextValidator(this, attrs, context);
+    }
+
+    public FormAutoCompleteTextView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        editTextValidator = new DefaultEditTextValidator(this, attrs, context);
+
+    }
+
+    /**
+     * Add a validator to this AutoCompleteTextView. The validator will be added in the
+     * queue of the current validators.
+     *
+     * @param theValidator
+     * @throws IllegalArgumentException
+     *             if the validator is null
+     */
+    public void addValidator(com.andreabaccega.formedittextvalidator.Validator theValidator) throws IllegalArgumentException {
+        editTextValidator.addValidator(theValidator);
+    }
+
+    public EditTextValidator getEditTextValidator() {
+        return editTextValidator;
+    }
+
+    public void setEditTextValidator(EditTextValidator editTextValidator) {
+        this.editTextValidator = editTextValidator;
+    }
+
+    /**
+     * Calling *testValidity()* will cause the AutoCompleteTextView to go through
+     * customValidators and call {@link com.andreabaccega.formedittextvalidator.Validator#isValid(EditText)}
+     *
+     * @return true if the validity passes false otherwise.
+     */
+    public boolean testValidity() {
+        return editTextValidator.testValidity();
+    }
+
+    private EditTextValidator editTextValidator;
+
+
+    /**
+     * Keep track of which icon we used last
+     */
+    private Drawable lastErrorIcon = null;
+
+    /**
+     * Don't send delete key so edit text doesn't capture it and close error
+     */
+    @Override
+    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+        if (TextUtils.isEmpty(getText().toString())
+                && keyCode == KeyEvent.KEYCODE_DEL)
+            return true;
+        else
+            return super.onKeyPreIme(keyCode, event);
+    }
+
+    /**
+     * Resolve an issue where the error icon is hidden under some cases in JB
+     * due to a bug http://code.google.com/p/android/issues/detail?id=40417
+     */
+    @Override
+    public void setError(CharSequence error, Drawable icon) {
+        super.setError(error, icon);
+        lastErrorIcon = icon;
+
+        // if the error is not null, and we are in JB, force
+        // the error to show
+        if (error != null /* !isFocused() && */) {
+            showErrorIconHax(icon);
+        }
+    }
+
+
+    /**
+     * In onFocusChanged() we also have to reshow the error icon as the Editor
+     * hides it. Because Editor is a hidden class we need to cache the last used
+     * icon and use that
+     */
+    @Override
+    protected void onFocusChanged(boolean focused, int direction,
+                                  Rect previouslyFocusedRect) {
+        super.onFocusChanged(focused, direction, previouslyFocusedRect);
+        showErrorIconHax(lastErrorIcon);
+    }
+
+    /**
+     * Use reflection to force the error icon to show. Dirty but resolves the
+     * issue in 4.2
+     */
+    private void showErrorIconHax(Drawable icon) {
+        if (icon == null)
+            return;
+
+        // only for JB 4.2 and 4.2.1
+        if (android.os.Build.VERSION.SDK_INT != Build.VERSION_CODES.JELLY_BEAN
+                && android.os.Build.VERSION.SDK_INT != Build.VERSION_CODES.JELLY_BEAN_MR1)
+            return;
+
+        try {
+            Class<?> textview = Class.forName("android.widget.TextView");
+            Field tEditor = textview.getDeclaredField("mEditor");
+            tEditor.setAccessible(true);
+            Class<?> editor = Class.forName("android.widget.Editor");
+            Method privateShowError = editor.getDeclaredMethod("setErrorIcon",
+                    Drawable.class);
+            privateShowError.setAccessible(true);
+            privateShowError.invoke(tEditor.get(this), icon);
+        } catch (Exception e) {
+            // e.printStackTrace(); // oh well, we tried
+        }
+    }
+
+
+}