1package com.xtremelabs.robolectric.shadows;
2
3import android.graphics.Bitmap;
4import android.graphics.BitmapFactory;
5import android.graphics.Canvas;
6import android.graphics.Matrix;
7import android.graphics.drawable.AnimationDrawable;
8import android.graphics.drawable.BitmapDrawable;
9import android.graphics.drawable.Drawable;
10import android.graphics.drawable.LayerDrawable;
11import android.widget.ImageView;
12import com.xtremelabs.robolectric.Robolectric;
13import com.xtremelabs.robolectric.internal.Implementation;
14import com.xtremelabs.robolectric.internal.Implements;
15import com.xtremelabs.robolectric.res.ResourceLoader;
16
17import static com.xtremelabs.robolectric.Robolectric.shadowOf;
18
19@Implements(ImageView.class)
20public class ShadowImageView extends ShadowView {
21    private Drawable imageDrawable;
22    private int alpha;
23    private int resourceId;
24    private Bitmap imageBitmap;
25    private ImageView.ScaleType scaleType;
26    private Matrix matrix;
27    private int imageLevel;
28
29    @Override
30    public void applyAttributes() {
31        super.applyAttributes();
32        applyImageAttribute();
33    }
34
35    @Implementation
36    public void setImageBitmap(Bitmap imageBitmap) {
37        setImageDrawable(new BitmapDrawable(imageBitmap));
38        this.imageBitmap = imageBitmap;
39    }
40
41    @Deprecated
42    public Bitmap getImageBitmap() {
43        return imageBitmap;
44    }
45
46    @Implementation
47    public void setImageDrawable(Drawable drawable) {
48        this.imageDrawable = drawable;
49    }
50
51    @Implementation
52    public void setImageResource(int resId) {
53        this.resourceId = resId;
54        setImageDrawable(buildDrawable(resId));
55    }
56
57    /**
58     * Build drawable, either LayerDrawable or BitmapDrawable.
59     *
60     * @param resourceId Resource id
61     * @return Drawable
62     */
63    protected Drawable buildDrawable(int resourceId) {
64        if (isDrawableXml(resourceId)) {
65            ResourceLoader resourceLoader = shadowOf(Robolectric.application).getResourceLoader();
66            int[] resourceIds = resourceLoader.getDrawableIds(resourceId);
67            Drawable[] drawables = new Drawable[resourceIds.length];
68
69            for (int i = 0; i < resourceIds.length; i++) {
70                drawables[i] = buildDrawable(resourceIds[i]);
71            }
72            if (resourceLoader.isAnimatableXml(resourceId)) {
73                AnimationDrawable animationDrawable = new AnimationDrawable();
74                for (Drawable drawable : drawables) {
75                    animationDrawable.addFrame(drawable, -1);
76                }
77                return animationDrawable;
78            } else {
79                LayerDrawable layerDrawable = new LayerDrawable(drawables);
80                shadowOf(layerDrawable).setLoadedFromResourceId(resourceId);
81                return layerDrawable;
82            }
83        } else {
84            return new BitmapDrawable(BitmapFactory.decodeResource(
85                    getResources(), resourceId));
86        }
87    }
88
89    /**
90     * Does the resource id point to xml resource.
91     *
92     * @param resourceId Resource id
93     * @return Boolean
94     */
95    private boolean isDrawableXml(int resourceId) {
96        return shadowOf(Robolectric.application).getResourceLoader()
97                .isDrawableXml(resourceId);
98    }
99
100    @Implementation
101    public void setAlpha(int alpha) {
102        this.alpha = alpha;
103    }
104
105    @Implementation
106    public ImageView.ScaleType getScaleType() {
107        return scaleType;
108    }
109
110    @Implementation
111    public void setScaleType(ImageView.ScaleType scaleType) {
112        this.scaleType = scaleType;
113    }
114
115    @Implementation
116    public Drawable getDrawable() {
117        return imageDrawable;
118    }
119
120    /**
121     * @return the image drawable
122     * @deprecated Use android.widget.ImageView#getDrawable() instead.
123     */
124    @Deprecated
125    public Drawable getImageDrawable() {
126        return imageDrawable;
127    }
128
129    @Implementation
130    public int getAlpha() {
131        return alpha;
132    }
133
134    @Deprecated
135    public int getResourceId() {
136        return resourceId;
137    }
138
139    @Implementation
140    public void setImageMatrix(Matrix matrix) {
141        this.matrix = new Matrix(matrix);
142    }
143
144    @Implementation
145    public void draw(Canvas canvas) {
146        if (matrix != null) {
147            canvas.translate(shadowOf(matrix).getTransX(), shadowOf(matrix)
148                    .getTransY());
149            canvas.scale(shadowOf(matrix).getScaleX(), shadowOf(matrix)
150                    .getScaleY());
151        }
152        imageDrawable.draw(canvas);
153    }
154
155    private void applyImageAttribute() {
156        String source = attributeSet.getAttributeValue("android", "src");
157        if (source != null) {
158            if (source.startsWith("@drawable/")) {
159                setImageResource(attributeSet.getAttributeResourceValue(
160                        "android", "src", 0));
161            }
162        }
163    }
164
165    @Implementation
166    public void setImageLevel(int imageLevel) {
167        this.imageLevel = imageLevel;
168    }
169
170    /**
171     * Non-Android accessor.
172     *
173     * @return the imageLevel set in {@code setImageLevel(int)}
174     */
175    public int getImageLevel() {
176        return imageLevel;
177    }
178}
179