1 package com.xtremelabs.robolectric.shadows;
2 
3 import android.content.res.Resources;
4 import android.graphics.Bitmap;
5 import android.graphics.BitmapFactory;
6 import android.graphics.Rect;
7 import android.graphics.drawable.BitmapDrawable;
8 import android.graphics.drawable.Drawable;
9 import android.util.TypedValue;
10 
11 import com.xtremelabs.robolectric.Robolectric;
12 import com.xtremelabs.robolectric.internal.Implementation;
13 import com.xtremelabs.robolectric.internal.Implements;
14 import com.xtremelabs.robolectric.internal.RealObject;
15 
16 import java.io.InputStream;
17 import java.util.ArrayList;
18 
19 import static com.xtremelabs.robolectric.Robolectric.shadowOf;
20 
21 @SuppressWarnings({"UnusedDeclaration"})
22 @Implements(Drawable.class)
23 public class ShadowDrawable {
24     private static int defaultIntrinsicWidth = -1;
25     private static int defaultIntrinsicHeight = -1;
26     static ArrayList<String> corruptStreamSources = new ArrayList<String>();
27 
28     @RealObject Drawable realObject;
29 
30     private Rect bounds = new Rect(0, 0, 0, 0);
31     private int intrinsicWidth = defaultIntrinsicWidth;
32     private int intrinsicHeight = defaultIntrinsicHeight;
33     private int alpha;
34     private InputStream inputStream;
35     private int level;
36     private int loadedFromResourceId = -1;
37     private boolean wasInvalidated;
38 
39     @Implementation
createFromStream(InputStream is, String srcName)40     public static Drawable createFromStream(InputStream is, String srcName) {
41         if (corruptStreamSources.contains(srcName)) {
42             return null;
43         }
44         BitmapDrawable drawable = new BitmapDrawable(Robolectric.newInstanceOf(Bitmap.class));
45         shadowOf(drawable).setSource(srcName);
46         shadowOf(drawable).setInputStream(is);
47         return drawable;
48     }
49 
50     @Implementation
createFromResourceStream(Resources res, TypedValue value, InputStream is, String srcName)51     public static Drawable createFromResourceStream(Resources res, TypedValue value, InputStream is, String srcName) {
52         return createFromStream(is, srcName);
53     }
54 
55     @Implementation
createFromResourceStream(Resources res, TypedValue value, InputStream is, String srcName, BitmapFactory.Options opts)56     public static Drawable createFromResourceStream(Resources res, TypedValue value, InputStream is, String srcName, BitmapFactory.Options opts) {
57         return createFromStream(is, srcName);
58     }
59 
60     @Implementation
createFromPath(String pathName)61     public static Drawable createFromPath(String pathName) {
62         BitmapDrawable drawable = new BitmapDrawable(Robolectric.newInstanceOf(Bitmap.class));
63         shadowOf(drawable).setPath(pathName);
64         return drawable;
65     }
66 
createFromResourceId(int resourceId)67     public static Drawable createFromResourceId(int resourceId) {
68         Bitmap bitmap = Robolectric.newInstanceOf(Bitmap.class);
69         shadowOf(bitmap).setLoadedFromResourceId(resourceId);
70         BitmapDrawable drawable = new BitmapDrawable(bitmap);
71         return drawable;
72     }
73 
74     @Implementation
getBounds()75     public final Rect getBounds() {
76         return bounds;
77     }
78 
79     @Implementation
setBounds(Rect rect)80     public void setBounds(Rect rect) {
81         this.bounds = rect;
82     }
83 
84     @Implementation
setBounds(int left, int top, int right, int bottom)85     public void setBounds(int left, int top, int right, int bottom) {
86         bounds = new Rect(left, top, right, bottom);
87     }
88 
89     @Implementation
copyBounds()90     public Rect copyBounds() {
91         Rect bounds = new Rect();
92         copyBounds(bounds);
93         return bounds;
94     }
95 
96     @Implementation
copyBounds(Rect bounds)97     public void copyBounds(Rect bounds) {
98         bounds.set(getBounds());
99     }
100 
101     @Implementation
getIntrinsicWidth()102     public int getIntrinsicWidth() {
103         return intrinsicWidth;
104     }
105 
106     @Implementation
getIntrinsicHeight()107     public int getIntrinsicHeight() {
108         return intrinsicHeight;
109     }
110 
addCorruptStreamSource(String src)111     public static void addCorruptStreamSource(String src) {
112         corruptStreamSources.add(src);
113     }
114 
setDefaultIntrinsicWidth(int defaultIntrinsicWidth)115     public static void setDefaultIntrinsicWidth(int defaultIntrinsicWidth) {
116         ShadowDrawable.defaultIntrinsicWidth = defaultIntrinsicWidth;
117     }
118 
setDefaultIntrinsicHeight(int defaultIntrinsicHeight)119     public static void setDefaultIntrinsicHeight(int defaultIntrinsicHeight) {
120         ShadowDrawable.defaultIntrinsicHeight = defaultIntrinsicHeight;
121     }
122 
setIntrinsicWidth(int intrinsicWidth)123     public void setIntrinsicWidth(int intrinsicWidth) {
124         this.intrinsicWidth = intrinsicWidth;
125     }
126 
setIntrinsicHeight(int intrinsicHeight)127     public void setIntrinsicHeight(int intrinsicHeight) {
128         this.intrinsicHeight = intrinsicHeight;
129     }
130 
getInputStream()131     public InputStream getInputStream() {
132         return inputStream;
133     }
134 
setInputStream(InputStream inputStream)135     public void setInputStream(InputStream inputStream) {
136         this.inputStream = inputStream;
137     }
138 
139     @Implementation
getLevel()140     public int getLevel() {
141         return level;
142     }
143 
144     @Implementation
setLevel(int level)145     public boolean setLevel(int level) {
146         this.level = level;
147         // This should return true if the new level causes a layout change.
148         // Doing this in robolectric would require parsing level sets which
149         // is not currently supported.
150         return false;
151     }
152 
153     @Override @Implementation
equals(Object o)154     public boolean equals(Object o) {
155         if (realObject == o) return true;
156         if (o == null || realObject.getClass() != o.getClass()) return false;
157 
158         ShadowDrawable that = shadowOf((Drawable) o);
159 
160         if (intrinsicHeight != that.intrinsicHeight) return false;
161         if (intrinsicWidth != that.intrinsicWidth) return false;
162         if (bounds != null ? !bounds.equals(that.bounds) : that.bounds != null) return false;
163 
164         return true;
165     }
166 
167     @Override @Implementation
hashCode()168     public int hashCode() {
169         int result = bounds != null ? bounds.hashCode() : 0;
170         result = 31 * result + intrinsicWidth;
171         result = 31 * result + intrinsicHeight;
172         return result;
173     }
174 
175     @Implementation
setAlpha(int alpha)176     public void setAlpha(int alpha) {
177         this.alpha = alpha;
178     }
179 
180     @Implementation
invalidateSelf()181     public void invalidateSelf() {
182         wasInvalidated = true;
183     }
184 
getAlpha()185     public int getAlpha() {
186         return alpha;
187     }
188 
reset()189     public static void reset() {
190         corruptStreamSources.clear();
191     }
192 
getLoadedFromResourceId()193     public int getLoadedFromResourceId() {
194         return loadedFromResourceId;
195     }
196 
setLoadedFromResourceId(int resourceId)197     public void setLoadedFromResourceId(int resourceId) {
198         loadedFromResourceId = resourceId;
199     }
200 
wasInvalidated()201     public boolean wasInvalidated() {
202         return wasInvalidated;
203     }
204 }
205