All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xtremelabs.robolectric.res.DrawableResourceLoader Maven / Gradle / Ivy

There is a newer version: 1.2
Show newest version
package com.xtremelabs.robolectric.res;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import android.R;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.StateListDrawable;

import com.xtremelabs.robolectric.Robolectric;
import com.xtremelabs.robolectric.shadows.ShadowStateListDrawable;

/**
 * DrawableResourceLoader
 */
public class DrawableResourceLoader extends XmlLoader {
	
   	// Put all the states for a StateListDrawable in the into a Map for looking up
	// http://developer.android.com/guide/topics/resources/drawable-resource.html#StateList
	private static final Map stateMap = new HashMap();
	static {
		stateMap.put( "android:state_selected", R.attr.state_selected );
		stateMap.put( "android:state_pressed", R.attr.state_pressed );
		stateMap.put( "android:state_focused", R.attr.state_focused );
		stateMap.put( "android:state_checkable", R.attr.state_checkable );
		stateMap.put( "android:state_checked", R.attr.state_checked );
		stateMap.put( "android:state_enabled", R.attr.state_enabled );
		stateMap.put( "android:state_window_focused", R.attr.state_window_focused );
	}
	
    /** document */
    protected Map documents = new HashMap();

    /** resource directory */
    protected File resourceDirectory;

    /**
     * DrawableResourceLoader constructor.
     * 
     * @param extractor
     *            Extractor
     * @param resourceDirectory
     *            Resource directory
     */
    public DrawableResourceLoader(ResourceExtractor extractor, File resourceDirectory) {
        super(extractor);
        this.resourceDirectory = resourceDirectory;
    }

    /**
     * Check if resource is xml.
     * 
     * @param resourceId
     *            Resource id
     * @return Boolean
     */
    public boolean isXml(int resourceId) {
        return documents.containsKey(resourceExtractor.getResourceName(resourceId));
    }

    public Drawable getXmlDrawable( int resId ) {
    	
    	if( !isXml( resId ) ) { return null; }
    	
    	Document xmlDoc = documents.get( resourceExtractor.getResourceName( resId ) );
    	NodeList nodes = xmlDoc.getElementsByTagName("selector");
    	if( nodes != null && nodes.getLength() > 0 ) { return buildStateListDrawable( xmlDoc ); } 

    	nodes = xmlDoc.getElementsByTagName("layer-list");
    	if( nodes != null && nodes.getLength() > 0 ) { return new LayerDrawable( null ); }    	

    	return null;
    }
    
    /**
     * Store document locally keyed by resource name.
     * 
     * @param xmlFile
     *            Xml file
     * @param document
     *            Document
     * @param isSystem
     *            System resource
     * @throws Exception
     * @see com.xtremelabs.robolectric.res.XmlLoader#processResourceXml(java.io.File,
     *      org.w3c.dom.Document, boolean)
     */
    @Override
    protected void processResourceXml(File xmlFile, Document document, boolean isSystem) throws Exception {
        String name = toResourceName(xmlFile);
        if (!documents.containsKey(name)) {
            if (isSystem) {
                name = "android:" + name;
            }
            documents.put(name, document);
        }
    }

    /**
     * Convert file name to resource name.
     * 
     * @param xmlFile
     *            Xml File
     * @return Resource name
     */
    private String toResourceName(File xmlFile) {
        try {
            return xmlFile.getCanonicalPath().replaceAll("[/\\\\\\\\]", "/")
                    .replaceAll("^.*?/res/", "").replaceAll("\\..+$", "");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    
    /**
     * Get drawables by resource id.
     * 
     * @param resourceId
     *            Resource id
     * @return Drawables
     */
    protected int[] getDrawableIds(int resourceId) {
        String resourceName = resourceExtractor.getResourceName(resourceId);
        Document document = documents.get(resourceName);

        NodeList items = document.getElementsByTagName("item");
        int[] drawableIds = new int[items.getLength()];

        for (int i = 0; i < items.getLength(); i++) {
            if (resourceName.startsWith("android:")) {
                drawableIds[i] = -1;
            } else {
                Node item = items.item(i);
                Node drawableName = item.getAttributes().getNamedItem("android:drawable");
                if (drawableName != null) {
                    drawableIds[i] = resourceExtractor.getResourceId(drawableName.getNodeValue());
                }
            }
        }

        return drawableIds;
    }
    
    private StateListDrawable buildStateListDrawable( Document d ) {
    	
    	StateListDrawable drawable = new StateListDrawable();
    	ShadowStateListDrawable shDrawable = Robolectric.shadowOf( drawable );
    	
    	NodeList items = d.getElementsByTagName( "item" );
    	for (int i = 0; i < items.getLength(); i++) {
    		Node node = items.item( i );
    		Node drawableName = node.getAttributes().getNamedItem("android:drawable");
    		if( drawableName != null ) {
    			int resId = resourceExtractor.getResourceId(drawableName.getNodeValue());
    			int stateId = getStateId( node );
    			shDrawable.addState(stateId, resId);
    		}
    	}
    	return drawable;
    }
    
    private int getStateId( Node node ) {
    	
    	NamedNodeMap attrs = node.getAttributes();
    	for( String state : stateMap.keySet() ) {
        	Node attr = attrs.getNamedItem( state ); 
        	if( attr != null ) { return stateMap.get( state ); }    		
    	}
    	
    	// if a state wasn't specified, return the default state
    	return R.attr.state_active;
    }    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy