aboutsummaryrefslogtreecommitdiff
path: root/v1/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java
diff options
context:
space:
mode:
Diffstat (limited to 'v1/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java')
-rw-r--r--v1/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java603
1 files changed, 603 insertions, 0 deletions
diff --git a/v1/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java b/v1/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java
new file mode 100644
index 000000000..3027fcc4a
--- /dev/null
+++ b/v1/src/main/java/com/xtremelabs/robolectric/shadows/ShadowTextView.java
@@ -0,0 +1,603 @@
+package com.xtremelabs.robolectric.shadows;
+
+import android.content.Context;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
+import android.text.Layout;
+import android.text.SpannableStringBuilder;
+import android.text.TextPaint;
+import android.text.TextWatcher;
+import android.text.method.MovementMethod;
+import android.text.method.TransformationMethod;
+import android.text.style.URLSpan;
+import android.text.util.Linkify;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.inputmethod.EditorInfo;
+import android.widget.TextView;
+import com.xtremelabs.robolectric.internal.Implementation;
+import com.xtremelabs.robolectric.internal.Implements;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static android.view.View.VISIBLE;
+import static com.xtremelabs.robolectric.Robolectric.shadowOf;
+import static com.xtremelabs.robolectric.Robolectric.shadowOf_;
+
+@SuppressWarnings({"UnusedDeclaration"})
+@Implements(TextView.class)
+public class ShadowTextView extends ShadowView {
+ private CharSequence text = "";
+ private CompoundDrawables compoundDrawablesImpl = new CompoundDrawables(0, 0, 0, 0);
+ private Integer textColorHexValue;
+ private Integer hintColorHexValue;
+ private float textSize = 14.0f;
+ private boolean autoLinkPhoneNumbers;
+ private int autoLinkMask;
+ private CharSequence hintText;
+ private CharSequence errorText;
+ private int compoundDrawablePadding;
+ private MovementMethod movementMethod;
+ private boolean linksClickable;
+ private int gravity;
+ private TextView.OnEditorActionListener onEditorActionListener;
+ private int imeOptions = EditorInfo.IME_NULL;
+ private int textAppearanceId;
+ private TransformationMethod transformationMethod;
+ private int inputType;
+ protected int selectionStart = 0;
+ protected int selectionEnd = 0;
+ private Typeface typeface;
+
+ private List<TextWatcher> watchers = new ArrayList<TextWatcher>();
+ private List<Integer> previousKeyCodes = new ArrayList<Integer>();
+ private List<KeyEvent> previousKeyEvents = new ArrayList<KeyEvent>();
+ private Layout layout;
+
+ @Override
+ public void applyAttributes() {
+ super.applyAttributes();
+ applyTextAttribute();
+ applyTextColorAttribute();
+ applyHintAttribute();
+ applyHintColorAttribute();
+ applyCompoundDrawablesWithIntrinsicBoundsAttributes();
+ }
+
+ @Implementation(i18nSafe = false)
+ public void setText(CharSequence text) {
+ if (text == null) {
+ text = "";
+ }
+
+ sendBeforeTextChanged(text);
+
+ CharSequence oldValue = this.text;
+ this.text = text;
+
+ sendOnTextChanged(oldValue);
+ sendAfterTextChanged();
+ }
+
+ @Implementation
+ public final void append(CharSequence text) {
+ boolean isSelectStartAtEnd = selectionStart == this.text.length();
+ boolean isSelectEndAtEnd = selectionEnd == this.text.length();
+ CharSequence oldValue = this.text;
+ StringBuffer sb = new StringBuffer(this.text);
+ sb.append(text);
+
+ sendBeforeTextChanged(sb.toString());
+ this.text = sb.toString();
+
+ if (isSelectStartAtEnd) {
+ selectionStart = this.text.length();
+ }
+ if (isSelectEndAtEnd) {
+ selectionEnd = this.text.length();
+ }
+
+ sendOnTextChanged(oldValue);
+ sendAfterTextChanged();
+ }
+
+ @Implementation
+ public void setText(int textResourceId) {
+ sendBeforeTextChanged(text);
+
+ CharSequence oldValue = this.text;
+ this.text = getResources().getText(textResourceId);
+
+ sendOnTextChanged(oldValue);
+ sendAfterTextChanged();
+ }
+
+ private void sendAfterTextChanged() {
+ for (TextWatcher watcher : watchers) {
+ watcher.afterTextChanged(new SpannableStringBuilder(getText()));
+ }
+ }
+
+ private void sendOnTextChanged(CharSequence oldValue) {
+ for (TextWatcher watcher : watchers) {
+ watcher.onTextChanged(text, 0, oldValue.length(), text.length());
+ }
+ }
+
+ private void sendBeforeTextChanged(CharSequence newValue) {
+ for (TextWatcher watcher : watchers) {
+ watcher.beforeTextChanged(this.text, 0, this.text.length(), newValue.length());
+ }
+ }
+
+ @Implementation
+ public CharSequence getText() {
+ return text;
+ }
+
+ @Implementation
+ public Typeface getTypeface() {
+ return typeface;
+ }
+
+ @Implementation
+ public void setTypeface(Typeface typeface) {
+ this.typeface = typeface;
+ }
+
+ @Implementation
+ public int length() {
+ return text.length();
+ }
+
+ @Implementation
+ public void setTextColor(int color) {
+ textColorHexValue = color;
+ }
+
+ @Implementation
+ public void setTextSize(float size) {
+ textSize = size;
+ }
+
+ @Implementation
+ public void setTextAppearance(Context context, int resid) {
+ textAppearanceId = resid;
+ }
+
+ @Implementation
+ public void setInputType(int type) {
+ this.inputType = type;
+ }
+
+ @Implementation
+ public int getInputType() {
+ return this.inputType;
+ }
+
+ @Implementation
+ public final void setHint(int resId) {
+ this.hintText = getResources().getText(resId);
+ }
+
+ @Implementation(i18nSafe = false)
+ public final void setHint(CharSequence hintText) {
+ this.hintText = hintText;
+ }
+
+ @Implementation
+ public CharSequence getHint() {
+ return hintText;
+ }
+
+ @Implementation
+ public final void setHintTextColor(int color) {
+ hintColorHexValue = color;
+ }
+
+ @Implementation
+ public final boolean getLinksClickable() {
+ return linksClickable;
+ }
+
+ @Implementation
+ public final void setLinksClickable(boolean whether) {
+ linksClickable = whether;
+ }
+
+ @Implementation
+ public final MovementMethod getMovementMethod() {
+ return movementMethod;
+ }
+
+ @Implementation
+ public final void setMovementMethod(MovementMethod movement) {
+ movementMethod = movement;
+ }
+
+ @Implementation
+ public URLSpan[] getUrls() {
+ String[] words = text.toString().split("\\s+");
+ List<URLSpan> urlSpans = new ArrayList<URLSpan>();
+ for (String word : words) {
+ if (word.startsWith("http://")) {
+ urlSpans.add(new URLSpan(word));
+ }
+ }
+ return urlSpans.toArray(new URLSpan[urlSpans.size()]);
+ }
+
+ @Implementation
+ public final void setAutoLinkMask(int mask) {
+ autoLinkMask = mask;
+
+ autoLinkPhoneNumbers = (mask & Linkify.PHONE_NUMBERS) != 0;
+ }
+
+ @Implementation
+ public void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) {
+ compoundDrawablesImpl = new CompoundDrawables(left, top, right, bottom);
+ }
+
+ @Implementation
+ public void setCompoundDrawablesWithIntrinsicBounds(Drawable left, Drawable top,
+ Drawable right, Drawable bottom) {
+ compoundDrawablesImpl = new CompoundDrawables(left, top, right, bottom);
+ }
+
+ @Implementation
+ public void setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
+ compoundDrawablesImpl = new CompoundDrawables(left, top, right, bottom);
+ }
+
+ @Implementation
+ public Drawable[] getCompoundDrawables() {
+ if (compoundDrawablesImpl == null) {
+ return new Drawable[]{null, null, null, null};
+ }
+ return new Drawable[]{
+ compoundDrawablesImpl.leftDrawable,
+ compoundDrawablesImpl.topDrawable,
+ compoundDrawablesImpl.rightDrawable,
+ compoundDrawablesImpl.bottomDrawable
+ };
+ }
+
+ @Implementation
+ public void setCompoundDrawablePadding(int compoundDrawablePadding) {
+ this.compoundDrawablePadding = compoundDrawablePadding;
+ }
+
+ @Implementation
+ public int getCompoundDrawablePadding() {
+ return compoundDrawablePadding;
+ }
+
+ @Implementation
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ previousKeyCodes.add(keyCode);
+ previousKeyEvents.add(event);
+ if (onKeyListener != null) {
+ return onKeyListener.onKey(realView, keyCode, event);
+ } else {
+ return false;
+ }
+ }
+
+ @Implementation
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ previousKeyCodes.add(keyCode);
+ previousKeyEvents.add(event);
+ if (onKeyListener != null) {
+ return onKeyListener.onKey(realView, keyCode, event);
+ } else {
+ return false;
+ }
+ }
+
+ public int getPreviousKeyCode(int index) {
+ return previousKeyCodes.get(index);
+ }
+
+ public KeyEvent getPreviousKeyEvent(int index) {
+ return previousKeyEvents.get(index);
+ }
+
+ @Implementation
+ public int getGravity() {
+ return gravity;
+ }
+
+ @Implementation
+ public void setGravity(int gravity) {
+ this.gravity = gravity;
+ }
+
+
+ @Implementation
+ public int getImeOptions() {
+ return imeOptions;
+ }
+
+ @Implementation
+ public void setImeOptions(int imeOptions) {
+ this.imeOptions = imeOptions;
+ }
+
+ /**
+ * Returns the text string of this {@code TextView}.
+ * <p/>
+ * Robolectric extension.
+ */
+ @Override
+ public String innerText() {
+ return (text == null || getVisibility() != VISIBLE) ? "" : text.toString();
+ }
+
+ @Implementation
+ public void setError(CharSequence error) {
+ errorText = error;
+ }
+
+ @Implementation
+ public CharSequence getError() {
+ return errorText;
+ }
+
+ @Override
+ @Implementation
+ public boolean equals(Object o) {
+ return super.equals(shadowOf_(o));
+ }
+
+ @Override
+ @Implementation
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ public CompoundDrawables getCompoundDrawablesImpl() {
+ return compoundDrawablesImpl;
+ }
+
+ void setCompoundDrawablesImpl(CompoundDrawables compoundDrawablesImpl) {
+ this.compoundDrawablesImpl = compoundDrawablesImpl;
+ }
+
+ public Integer getTextColorHexValue() {
+ return textColorHexValue;
+ }
+
+ public int getTextAppearanceId() {
+ return textAppearanceId;
+ }
+
+ public Integer getHintColorHexValue() {
+ return hintColorHexValue;
+ }
+
+ @Implementation
+ public float getTextSize() {
+ return textSize;
+ }
+
+ public boolean isAutoLinkPhoneNumbers() {
+ return autoLinkPhoneNumbers;
+ }
+
+ private void applyTextAttribute() {
+ String text = attributeSet.getAttributeValue("android", "text");
+ if (text != null) {
+ if (text.startsWith("@string/")) {
+ int textResId = attributeSet.getAttributeResourceValue("android", "text", 0);
+ text = context.getResources().getString(textResId);
+ }
+ setText(text);
+ }
+ }
+
+ private void applyTextColorAttribute() {
+ String colorValue = attributeSet.getAttributeValue("android", "textColor");
+ if (colorValue != null) {
+ if (colorValue.startsWith("@color/") || colorValue.startsWith("@android:color/")) {
+ int colorResId = attributeSet.getAttributeResourceValue("android", "textColor", 0);
+ setTextColor(context.getResources().getColor(colorResId));
+ } else if (colorValue.startsWith("#")) {
+ int colorFromHex = (int) Long.valueOf(colorValue.replaceAll("#", ""), 16).longValue();
+ setTextColor(colorFromHex);
+ }
+ }
+ }
+
+ private void applyHintAttribute() {
+ String hint = attributeSet.getAttributeValue("android", "hint");
+ if (hint != null) {
+ if (hint.startsWith("@string/")) {
+ int textResId = attributeSet.getAttributeResourceValue("android", "hint", 0);
+ hint = context.getResources().getString(textResId);
+
+ }
+ setHint(hint);
+ }
+ }
+
+ private void applyHintColorAttribute() {
+ String colorValue = attributeSet.getAttributeValue("android", "hintColor");
+ if (colorValue != null) {
+ if (colorValue.startsWith("@color/") || colorValue.startsWith("@android:color/")) {
+ int colorResId = attributeSet.getAttributeResourceValue("android", "hintColor", 0);
+ setHintTextColor(context.getResources().getColor(colorResId));
+ } else if (colorValue.startsWith("#")) {
+ int colorFromHex = (int) Long.valueOf(colorValue.replaceAll("#", ""), 16).longValue();
+ setHintTextColor(colorFromHex);
+ }
+ }
+ }
+
+ private void applyCompoundDrawablesWithIntrinsicBoundsAttributes() {
+ setCompoundDrawablesWithIntrinsicBounds(
+ attributeSet.getAttributeResourceValue("android", "drawableLeft", 0),
+ attributeSet.getAttributeResourceValue("android", "drawableTop", 0),
+ attributeSet.getAttributeResourceValue("android", "drawableRight", 0),
+ attributeSet.getAttributeResourceValue("android", "drawableBottom", 0));
+ }
+
+ @Implementation
+ public void setOnEditorActionListener(android.widget.TextView.OnEditorActionListener onEditorActionListener) {
+ this.onEditorActionListener = onEditorActionListener;
+ }
+
+ public boolean triggerEditorAction(int imeAction) {
+ if (onEditorActionListener != null) {
+ return onEditorActionListener.onEditorAction((TextView) realView, imeAction, null);
+ }
+ return false;
+ }
+
+ @Implementation
+ public void setTransformationMethod(TransformationMethod transformationMethod) {
+ this.transformationMethod = transformationMethod;
+ }
+
+ @Implementation
+ public TransformationMethod getTransformationMethod() {
+ return transformationMethod;
+ }
+
+ @Implementation
+ public void addTextChangedListener(TextWatcher watcher) {
+ this.watchers.add(watcher);
+ }
+
+ @Implementation
+ public void removeTextChangedListener(TextWatcher watcher) {
+ this.watchers.remove(watcher);
+ }
+
+ @Implementation
+ public TextPaint getPaint() {
+ return new TextPaint();
+ }
+
+ @Implementation
+ public Layout getLayout() {
+ return this.layout;
+ }
+
+ public void setSelection(int index) {
+ setSelection(index, index);
+ }
+
+ public void setSelection(int start, int end) {
+ selectionStart = start;
+ selectionEnd = end;
+ }
+
+ @Implementation
+ public int getSelectionStart() {
+ return selectionStart;
+ }
+
+ @Implementation
+ public int getSelectionEnd() {
+ return selectionEnd;
+ }
+
+ @Implementation
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean superResult = super.onTouchEvent(event);
+
+ if (movementMethod != null) {
+ boolean handled = movementMethod.onTouchEvent(null, null, event);
+
+ if (handled) {
+ return true;
+ }
+ }
+
+ return superResult;
+ }
+
+ /**
+ * @return the list of currently registered watchers/listeners
+ */
+ public List<TextWatcher> getWatchers() {
+ return watchers;
+ }
+
+ public void setLayout(Layout layout) {
+ this.layout = layout;
+ }
+
+ public static class CompoundDrawables {
+ public Drawable leftDrawable;
+ public Drawable topDrawable;
+ public Drawable rightDrawable;
+ public Drawable bottomDrawable;
+
+ public CompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom) {
+ leftDrawable = left;
+ topDrawable = top;
+ rightDrawable = right;
+ bottomDrawable = bottom;
+ }
+
+ public CompoundDrawables(int left, int top, int right, int bottom) {
+ leftDrawable = left != 0 ? ShadowDrawable.createFromResourceId(left) : null;
+ topDrawable = top != 0 ? ShadowDrawable.createFromResourceId(top) : null;
+ rightDrawable = right != 0 ? ShadowDrawable.createFromResourceId(right) : null;
+ bottomDrawable = bottom != 0 ? ShadowDrawable.createFromResourceId(bottom) : null;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ CompoundDrawables that = (CompoundDrawables) o;
+
+ if (getBottom() != that.getBottom()) return false;
+ if (getLeft() != that.getLeft()) return false;
+ if (getRight() != that.getRight()) return false;
+ if (getTop() != that.getTop()) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = getLeft();
+ result = 31 * result + getTop();
+ result = 31 * result + getRight();
+ result = 31 * result + getBottom();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "CompoundDrawables{" +
+ "left=" + getLeft() +
+ ", top=" + getTop() +
+ ", right=" + getRight() +
+ ", bottom=" + getBottom() +
+ '}';
+ }
+
+ public int getLeft() {
+ return shadowOf(leftDrawable).getLoadedFromResourceId();
+ }
+
+ public int getTop() {
+ return shadowOf(topDrawable).getLoadedFromResourceId();
+ }
+
+ public int getRight() {
+ return shadowOf(rightDrawable).getLoadedFromResourceId();
+ }
+
+ public int getBottom() {
+ return shadowOf(bottomDrawable).getLoadedFromResourceId();
+ }
+ }
+}