ShadowResources.java revision 9daa83d905eccca3b027ce27e4a77b3f57441a1e
1package com.xtremelabs.robolectric.shadows;
2
3import android.content.res.AssetManager;
4import android.content.res.Configuration;
5import android.content.res.Resources;
6import android.content.res.TypedArray;
7import android.graphics.BitmapFactory;
8import android.graphics.drawable.BitmapDrawable;
9import android.graphics.drawable.Drawable;
10import android.util.AttributeSet;
11import android.util.DisplayMetrics;
12import com.xtremelabs.robolectric.Robolectric;
13import com.xtremelabs.robolectric.internal.Implementation;
14import com.xtremelabs.robolectric.internal.Implements;
15import com.xtremelabs.robolectric.internal.RealObject;
16import com.xtremelabs.robolectric.res.ResourceExtractor;
17import com.xtremelabs.robolectric.res.ResourceLoader;
18
19import java.io.InputStream;
20import java.util.Locale;
21
22import static com.xtremelabs.robolectric.Robolectric.newInstanceOf;
23import static com.xtremelabs.robolectric.Robolectric.shadowOf;
24
25/**
26 * Shadow of {@code Resources} that simulates the loading of resources
27 *
28 * @see com.xtremelabs.robolectric.RobolectricTestRunner#RobolectricTestRunner(Class, String, String)
29 */
30@SuppressWarnings({"UnusedDeclaration"})
31@Implements(Resources.class)
32public class ShadowResources {
33    private float density = 1.0f;
34
35    static Resources bind(Resources resources, ResourceLoader resourceLoader) {
36        ShadowResources shadowResources = shadowOf(resources);
37        if (shadowResources.resourceLoader != null) throw new RuntimeException("ResourceLoader already set!");
38        shadowResources.resourceLoader = resourceLoader;
39        return resources;
40    }
41
42    @RealObject Resources realResources;
43    private ResourceLoader resourceLoader;
44
45    @Implementation
46    public  int getIdentifier(String name, String defType, String defPackage) {
47        Integer index = 0;
48
49        ResourceExtractor resourceExtractor = resourceLoader.getResourceExtractor();
50
51        index = resourceExtractor.getResourceId(defType + "/" + name);
52        if (index == null) {
53            return 0;
54        }
55        return index;
56    }
57
58    @Implementation
59    public int getColor(int id) throws Resources.NotFoundException {
60        return resourceLoader.getColorValue(id);
61    }
62
63    @Implementation
64    public Configuration getConfiguration() {
65        Configuration configuration = new Configuration();
66        configuration.setToDefaults();
67        if (configuration.locale == null) {
68            configuration.locale = Locale.getDefault();
69        }
70        return configuration;
71    }
72
73    @Implementation
74    public String getString(int id) throws Resources.NotFoundException {
75        return resourceLoader.getStringValue(id);
76    }
77
78    @Implementation
79    public String getString(int id, Object... formatArgs) throws Resources.NotFoundException {
80        String raw = getString(id);
81        return String.format(Locale.ENGLISH, raw, formatArgs);
82    }
83
84    @Implementation
85    public String getQuantityString(int id, int quantity, Object... formatArgs) throws Resources.NotFoundException {
86        String raw = getQuantityString(id, quantity);
87        return String.format(Locale.ENGLISH, raw, formatArgs);
88    }
89
90    @Implementation
91    public String getQuantityString(int id, int quantity) throws Resources.NotFoundException {
92        return resourceLoader.getPluralStringValue(id, quantity);
93    }
94
95    @Implementation
96    public InputStream openRawResource(int id) throws Resources.NotFoundException {
97        return resourceLoader.getRawValue(id);
98    }
99
100    @Implementation
101    public String[] getStringArray(int id) throws Resources.NotFoundException {
102        String[] arrayValue = resourceLoader.getStringArrayValue(id);
103        if (arrayValue == null) {
104            throw new Resources.NotFoundException();
105        }
106        return arrayValue;
107    }
108
109    @Implementation
110    public CharSequence[] getTextArray(int id) throws Resources.NotFoundException {
111        return getStringArray(id);
112    }
113
114    @Implementation
115    public CharSequence getText(int id) throws Resources.NotFoundException {
116        return getString(id);
117    }
118
119    public void setDensity(float density) {
120        this.density = density;
121    }
122
123    @Implementation
124    public DisplayMetrics getDisplayMetrics() {
125        DisplayMetrics displayMetrics = new DisplayMetrics();
126        displayMetrics.density = this.density;
127        return displayMetrics;
128    }
129
130    @Implementation
131    public Drawable getDrawable(int drawableResourceId) throws Resources.NotFoundException {
132        return new BitmapDrawable(BitmapFactory.decodeResource(realResources, drawableResourceId));
133    }
134
135    @Implementation
136    public float getDimension(int id) throws Resources.NotFoundException {
137        // todo: get this value from the xml resources and scale it by display metrics [xw 20101011]
138        if (resourceLoader.dimensions.containsKey(id)) {
139            return resourceLoader.dimensions.get(id);
140        }
141        return id - 0x7f000000;
142    }
143
144    @Implementation
145    public int getDimensionPixelSize(int id) throws Resources.NotFoundException {
146        // The int value returned from here is probably going to be handed to TextView.setTextSize(),
147        // which takes a float. Avoid int-to-float conversion errors by returning a value generated from this
148        // resource ID but which isn't too big (resource values in R.java are all greater than 0x7f000000).
149
150        return (int) getDimension(id);
151    }
152
153    @Implementation
154    public int getDimensionPixelOffset(int id) throws Resources.NotFoundException {
155        return (int) getDimension(id);
156    }
157
158    @Implementation
159    public AssetManager getAssets() {
160        return ShadowAssetManager.bind(Robolectric.newInstanceOf(AssetManager.class), resourceLoader);
161    }
162
163    @Implementation
164    public final android.content.res.Resources.Theme newTheme() {
165        return newInstanceOf(Resources.Theme.class);
166    }
167
168    /**
169     * Non-Android accessor that sets the value to be returned by {@link #getDimension(int)}
170     *
171     * @param id    ID to set the dimension for
172     * @param value value to be returned
173     */
174    public void setDimension(int id, int value) {
175        resourceLoader.dimensions.put(id, value);
176    }
177
178    @Implements(Resources.Theme.class)
179    public static class ShadowTheme {
180        @Implementation
181        public TypedArray obtainStyledAttributes(int[] attrs) {
182            return obtainStyledAttributes(0, attrs);
183        }
184
185        @Implementation
186        public TypedArray obtainStyledAttributes(int resid, int[] attrs) throws android.content.res.Resources.NotFoundException {
187            return obtainStyledAttributes(null, attrs, 0, 0);
188        }
189
190        @Implementation
191        public TypedArray obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
192            return newInstanceOf(TypedArray.class);
193        }
194    }
195}
196