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 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