1 package org.robolectric.shadows;
2 
3 import static org.robolectric.shadow.api.Shadow.directlyOn;
4 
5 import android.content.Context;
6 import android.graphics.Typeface;
7 import android.text.InputFilter;
8 import android.text.TextPaint;
9 import android.text.TextWatcher;
10 import android.text.method.MovementMethod;
11 import android.text.method.TransformationMethod;
12 import android.view.KeyEvent;
13 import android.view.View;
14 import android.view.inputmethod.EditorInfo;
15 import android.widget.TextView;
16 import java.io.PrintStream;
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.Locale;
20 import org.robolectric.annotation.HiddenApi;
21 import org.robolectric.annotation.Implementation;
22 import org.robolectric.annotation.Implements;
23 import org.robolectric.annotation.RealObject;
24 
25 @SuppressWarnings({"UnusedDeclaration"})
26 @Implements(TextView.class)
27 public class ShadowTextView extends ShadowView {
28   @RealObject TextView realTextView;
29 
30   private CharSequence text = "";
31   private TextView.BufferType bufferType = TextView.BufferType.NORMAL;
32   private Integer textColorHexValue;
33   private Integer hintColorHexValue;
34   private float textSize = 14.0f;
35   private boolean autoLinkPhoneNumbers;
36   private int autoLinkMask;
37   private CharSequence hintText;
38   private CharSequence errorText;
39   private int compoundDrawablePadding;
40   private MovementMethod movementMethod;
41   private boolean linksClickable;
42   private int gravity;
43   private int imeOptions = EditorInfo.IME_NULL;
44   private TextView.OnEditorActionListener onEditorActionListener;
45   private int textAppearanceId;
46   private TransformationMethod transformationMethod;
47   private int inputType;
48   private int lines;
49   protected int selectionStart = -1;
50   protected int selectionEnd = -1;
51   private Typeface typeface;
52   private InputFilter[] inputFilters;
53   private TextPaint textPaint = new TextPaint();
54 
55   private List<TextWatcher> watchers = new ArrayList<>();
56   private List<Integer> previousKeyCodes = new ArrayList<>();
57   private List<KeyEvent> previousKeyEvents = new ArrayList<>();
58   private int paintFlags;
59   private int compoundDrawablesWithIntrinsicBoundsLeft;
60   private int compoundDrawablesWithIntrinsicBoundsTop;
61   private int compoundDrawablesWithIntrinsicBoundsRight;
62   private int compoundDrawablesWithIntrinsicBoundsBottom;
63 
64   @Implementation
setTextAppearance(Context context, int resid)65   protected void setTextAppearance(Context context, int resid) {
66     textAppearanceId = resid;
67     directlyOn(realTextView, TextView.class).setTextAppearance(context, resid);
68   }
69 
70   @Implementation
onKeyDown(int keyCode, KeyEvent event)71   protected boolean onKeyDown(int keyCode, KeyEvent event) {
72     previousKeyCodes.add(keyCode);
73     previousKeyEvents.add(event);
74     return directlyOn(realTextView, TextView.class).onKeyDown(keyCode, event);
75   }
76 
77   @Implementation
onKeyUp(int keyCode, KeyEvent event)78   protected boolean onKeyUp(int keyCode, KeyEvent event) {
79     previousKeyCodes.add(keyCode);
80     previousKeyEvents.add(event);
81     return directlyOn(realTextView, TextView.class).onKeyUp(keyCode, event);
82   }
83 
getPreviousKeyCode(int index)84   public int getPreviousKeyCode(int index) {
85     return previousKeyCodes.get(index);
86   }
87 
getPreviousKeyEvent(int index)88   public KeyEvent getPreviousKeyEvent(int index) {
89     return previousKeyEvents.get(index);
90   }
91 
92   /**
93    * Returns the text string of this {@code TextView}.
94    *
95    * Robolectric extension.
96    */
97   @Override
innerText()98   public String innerText() {
99     CharSequence text = realTextView.getText();
100     return (text == null || realTextView.getVisibility() != View.VISIBLE) ? "" : text.toString();
101   }
102 
getTextAppearanceId()103   public int getTextAppearanceId() {
104     return textAppearanceId;
105   }
106 
107   @Implementation
addTextChangedListener(TextWatcher watcher)108   protected void addTextChangedListener(TextWatcher watcher) {
109     this.watchers.add(watcher);
110     directlyOn(realTextView, TextView.class).addTextChangedListener(watcher);
111   }
112 
113   @Implementation
removeTextChangedListener(TextWatcher watcher)114   protected void removeTextChangedListener(TextWatcher watcher) {
115     this.watchers.remove(watcher);
116     directlyOn(realTextView, TextView.class).removeTextChangedListener(watcher);
117   }
118 
119   /**
120    * @return the list of currently registered watchers/listeners
121    */
getWatchers()122   public List<TextWatcher> getWatchers() {
123     return watchers;
124   }
125 
126   @HiddenApi @Implementation
getTextServicesLocale()127   public Locale getTextServicesLocale() {
128     return Locale.getDefault();
129   }
130 
131   @Override
dumpAttributes(PrintStream out)132   protected void dumpAttributes(PrintStream out) {
133     super.dumpAttributes(out);
134     CharSequence text = realTextView.getText();
135     if (text != null && text.length() > 0) {
136       dumpAttribute(out, "text", text.toString());
137     }
138   }
139 
140   @Implementation
getPaintFlags()141   protected int getPaintFlags() {
142     return paintFlags;
143   }
144 
145   @Implementation
setPaintFlags(int paintFlags)146   protected void setPaintFlags(int paintFlags) {
147     this.paintFlags = paintFlags;
148   }
149 
150   @Implementation
setOnEditorActionListener(TextView.OnEditorActionListener l)151   protected void setOnEditorActionListener(TextView.OnEditorActionListener l) {
152     this.onEditorActionListener = l;
153     directlyOn(realTextView, TextView.class).setOnEditorActionListener(l);
154   }
155 
getOnEditorActionListener()156   public TextView.OnEditorActionListener getOnEditorActionListener() {
157     return onEditorActionListener;
158   }
159 
160   @Implementation
setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom)161   protected void setCompoundDrawablesWithIntrinsicBounds(int left, int top, int right, int bottom) {
162     this.compoundDrawablesWithIntrinsicBoundsLeft = left;
163     this.compoundDrawablesWithIntrinsicBoundsTop = top;
164     this.compoundDrawablesWithIntrinsicBoundsRight = right;
165     this.compoundDrawablesWithIntrinsicBoundsBottom = bottom;
166     directlyOn(realTextView, TextView.class).setCompoundDrawablesWithIntrinsicBounds(left, top, right, bottom);
167   }
168 
getCompoundDrawablesWithIntrinsicBoundsLeft()169   public int getCompoundDrawablesWithIntrinsicBoundsLeft() {
170     return compoundDrawablesWithIntrinsicBoundsLeft;
171   }
172 
getCompoundDrawablesWithIntrinsicBoundsTop()173   public int getCompoundDrawablesWithIntrinsicBoundsTop() {
174     return compoundDrawablesWithIntrinsicBoundsTop;
175   }
176 
getCompoundDrawablesWithIntrinsicBoundsRight()177   public int getCompoundDrawablesWithIntrinsicBoundsRight() {
178     return compoundDrawablesWithIntrinsicBoundsRight;
179   }
180 
getCompoundDrawablesWithIntrinsicBoundsBottom()181   public int getCompoundDrawablesWithIntrinsicBoundsBottom() {
182     return compoundDrawablesWithIntrinsicBoundsBottom;
183   }
184 }
185