1package com.xtremelabs.robolectric.shadows;
2
3import android.content.res.Resources;
4import android.graphics.Bitmap;
5import android.graphics.BitmapFactory;
6import android.graphics.Rect;
7import android.graphics.drawable.BitmapDrawable;
8import android.graphics.drawable.Drawable;
9import android.util.TypedValue;
10
11import com.xtremelabs.robolectric.Robolectric;
12import com.xtremelabs.robolectric.internal.Implementation;
13import com.xtremelabs.robolectric.internal.Implements;
14import com.xtremelabs.robolectric.internal.RealObject;
15
16import java.io.InputStream;
17import java.util.ArrayList;
18
19import static com.xtremelabs.robolectric.Robolectric.shadowOf;
20
21@SuppressWarnings({"UnusedDeclaration"})
22@Implements(Drawable.class)
23public 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
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
51    public static Drawable createFromResourceStream(Resources res, TypedValue value, InputStream is, String srcName) {
52        return createFromStream(is, srcName);
53    }
54
55    @Implementation
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
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
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
75    public final Rect getBounds() {
76        return bounds;
77    }
78
79    @Implementation
80    public void setBounds(Rect rect) {
81        this.bounds = rect;
82    }
83
84    @Implementation
85    public void setBounds(int left, int top, int right, int bottom) {
86        bounds = new Rect(left, top, right, bottom);
87    }
88
89    @Implementation
90    public Rect copyBounds() {
91        Rect bounds = new Rect();
92        copyBounds(bounds);
93        return bounds;
94    }
95
96    @Implementation
97    public void copyBounds(Rect bounds) {
98        bounds.set(getBounds());
99    }
100
101    @Implementation
102    public int getIntrinsicWidth() {
103        return intrinsicWidth;
104    }
105
106    @Implementation
107    public int getIntrinsicHeight() {
108        return intrinsicHeight;
109    }
110
111    public static void addCorruptStreamSource(String src) {
112        corruptStreamSources.add(src);
113    }
114
115    public static void setDefaultIntrinsicWidth(int defaultIntrinsicWidth) {
116        ShadowDrawable.defaultIntrinsicWidth = defaultIntrinsicWidth;
117    }
118
119    public static void setDefaultIntrinsicHeight(int defaultIntrinsicHeight) {
120        ShadowDrawable.defaultIntrinsicHeight = defaultIntrinsicHeight;
121    }
122
123    public void setIntrinsicWidth(int intrinsicWidth) {
124        this.intrinsicWidth = intrinsicWidth;
125    }
126
127    public void setIntrinsicHeight(int intrinsicHeight) {
128        this.intrinsicHeight = intrinsicHeight;
129    }
130
131    public InputStream getInputStream() {
132        return inputStream;
133    }
134
135    public void setInputStream(InputStream inputStream) {
136        this.inputStream = inputStream;
137    }
138
139    @Implementation
140    public int getLevel() {
141        return level;
142    }
143
144    @Implementation
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
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
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
176    public void setAlpha(int alpha) {
177        this.alpha = alpha;
178    }
179
180    @Implementation
181    public void invalidateSelf() {
182        wasInvalidated = true;
183    }
184
185    public int getAlpha() {
186        return alpha;
187    }
188
189    public static void reset() {
190        corruptStreamSources.clear();
191    }
192
193    public int getLoadedFromResourceId() {
194        return loadedFromResourceId;
195    }
196
197    public void setLoadedFromResourceId(int resourceId) {
198        loadedFromResourceId = resourceId;
199    }
200
201    public boolean wasInvalidated() {
202        return wasInvalidated;
203    }
204}
205