@Test public void testConfigure() throws Exception { HashMap<String, String> params = new HashMap<String, String>(); String param1 = "this is a test."; String param2 = Plot.RenderMode.USE_BACKGROUND_THREAD.toString(); String param3 = "#FF0000"; params.put("title", param1); params.put("renderMode", param2); params.put("backgroundPaint.color", param3); params.put("graphWidget.domainTickLabelPaint.color", param3); Configurator.configure(RuntimeEnvironment.application, plot, params); assertEquals(param1, plot.getTitle()); assertEquals(Plot.RenderMode.USE_BACKGROUND_THREAD, plot.getRenderMode()); assertEquals(Color.parseColor(param3), plot.getBackgroundPaint().getColor()); assertEquals( Color.parseColor(param3), plot.getGraphWidget().getDomainTickLabelPaint().getColor()); }
/** * Parse XML Attributes. Should only be called once and at the end of the base class constructor. * The first-pass attempts to locate styleable attributes and apply those first. After that, * configurator-style attributes are applied, overriding any styleable attrs that may have been * previously applied. * * @param attrs */ private void loadAttrs(AttributeSet attrs, int defStyle) { if (attrs != null) { Field styleableFieldInR = null; TypedArray typedAttrs = null; final String appPkg = getContext().getPackageName(); Class styleableClass = null; try { /** * Need to retrieve R$styleable.class dynamically to avoid exceptions in environments where * this class does not exist, such as .jar users that have not merged the library's * attrs.xml with their own. */ styleableClass = Class.forName(appPkg + ".R$styleable"); } catch (ClassNotFoundException e) { // when running as a preview in IntelliJ or AndroidStudio it seems that the package of R is // something else; this fixes that issue: if (isInEditMode()) { styleableClass = R.styleable.class; } } if (styleableClass != null) { String styleableName = getClass().getName().substring(BASE_PACKAGE.length()); styleableName = styleableName.replace('.', '_'); try { /** * Use reflection to safely check for the existence of styleable defs for Plot and it's * derivatives. This safety check is necessary to avoid runtime exceptions in apps that * don't include Androidplot as a .aar and won't have access to the resources defined in * the core library. */ styleableFieldInR = styleableClass.getField(styleableName); } catch (NoSuchFieldException e) { Log.d(TAG, "Styleable definition not found for: " + styleableName); } if (styleableFieldInR != null) { try { int[] resIds = (int[]) styleableFieldInR.get(null); typedAttrs = getContext().obtainStyledAttributes(attrs, resIds, defStyle, 0); } catch (IllegalAccessException e) { // nothing to do } finally { if (typedAttrs != null) { // apply derived class' attrs: processAttrs(typedAttrs); typedAttrs.recycle(); } } } try { styleableFieldInR = styleableClass.getField(Plot.class.getSimpleName()); if (styleableFieldInR != null) { int[] resIds = (int[]) styleableFieldInR.get(null); typedAttrs = getContext().obtainStyledAttributes(attrs, resIds, defStyle, 0); } } catch (IllegalAccessException e) { // nothing to do } catch (NoSuchFieldException e) { Log.d(TAG, "Styleable definition not found for: " + Plot.class.getSimpleName()); } finally { if (typedAttrs != null) { // apply base attrs: processBaseAttrs(typedAttrs); typedAttrs.recycle(); } } } // apply "configurator" attrs: (overrides any previously applied styleable attrs) // filter out androidplot prefixed attrs: HashMap<String, String> attrHash = new HashMap<String, String>(); for (int i = 0; i < attrs.getAttributeCount(); i++) { String attrName = attrs.getAttributeName(i); // case insensitive check to see if this attr begins with our prefix: if (attrName != null && attrName.toUpperCase().startsWith(XML_ATTR_PREFIX.toUpperCase())) { attrHash.put( attrName.substring(XML_ATTR_PREFIX.length() + 1), attrs.getAttributeValue(i)); } } Configurator.configure(getContext(), this, attrHash); } }