diff options
Diffstat (limited to 'src/net/hoopajoo/android/SoftKeys/Theme.java')
-rw-r--r-- | src/net/hoopajoo/android/SoftKeys/Theme.java | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/net/hoopajoo/android/SoftKeys/Theme.java b/src/net/hoopajoo/android/SoftKeys/Theme.java new file mode 100644 index 0000000..920fd42 --- /dev/null +++ b/src/net/hoopajoo/android/SoftKeys/Theme.java @@ -0,0 +1,191 @@ +/* + * + * Copyright (c) 2010 Steve Slaven + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * +*/ +package net.hoopajoo.android.SoftKeys; + +import java.util.ArrayList; +import java.util.List; + +import android.app.Activity; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.content.res.XmlResourceParser; +import android.graphics.drawable.Drawable; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.RemoteViews; + +public class Theme { + // the stack of resources we look through for stuff, first match + // is the returned item (typically will be theme, app) + List<IdPack> mResources = new ArrayList<IdPack>(); + + Theme( Context c, String name ) { + PackageManager pm = c.getPackageManager(); + try { + IdPack i = new IdPack(); + i.name = name; + i.R = pm.getResourcesForApplication( name ); + mResources.add( i ); + }catch( Exception e ) { + // bad theme name + } + + // add app as last resort + IdPack i = new IdPack(); + i.name = c.getPackageName(); + i.R = c.getResources(); + mResources.add( i ); + } + + // Semi-stacked actions, look in theme, if not found, look in app + // this way you can have a generic "button" but also more specific buttons, + // like "service_back_button" if they need something more flashy allowing each + // individual button to be different, or just define the base "button" and have + // different icons + public Drawable getDrawable( String[] name ) { + IdPack i = getId( name, "drawable" ); + if( i != null ) { + return i.R.getDrawable( i.id ); + } + //Log.e( "SoftKeysTheme", "Unable to find drawable resource: " + name ); + return( null ); + } + + // For use mostly with the notification bar, allowing custom themes to include + // new icons primarily, but since it's a layout they can do more than that + public RemoteViews getRemoteViews( String[] name ) { + IdPack i = getId( name, "layout" ); + if( i != null ) { + Log.e( "SoftKeysTheme", "Found remoteview" ); + return new RemoteViews( i.name, i.id ); + } + + return null; + } + + public View inflateLayout( Context c, String[] name, ViewGroup root, boolean add ) { + // this makes a phony context to fool the layout inflater to use alternate resources + // for resolution, e.g. android:background="@drawable/background.png" + // without the phony context, we would instead end up using resources from the main + // app instead of the resources referenced in the theme + // + // this is not documented but I can't find an officially supported way to inflate views + // containing references from other packages + IdPack i = getId( name, "layout" ); + if( i != null ) { + FakeContext fake = new FakeContext( c, i.R ); + // you can't create this from the fake context, it still pulls a system service + LayoutInflater inflater = LayoutInflater.from( c ).cloneInContext( fake ); + return inflater.inflate( i.R.getXml( i.id ), root, add ); + } + + return( null ); + } + + /* + public XmlResourceParser getLayout( String[] name ) { + IdPack i = getId( name, "layout" ); + if( i != null ) { + return i.R.getXml( i.id ); + } + Log.e( "SoftKeysTheme", "Unable to find layout resource: " + name ); + return null; + } + */ + + private IdPack getId( String[] name, String type ) { + // return the most specific match, from theme first then from app + for( IdPack check : mResources ) { + for( String n : name ) { + int id = check.R.getIdentifier( n, type, check.name ); + if( id != 0 ) { + IdPack i = new IdPack(); // return copy in case they need more than 1 id going (we don't right now) + i.id = id; + i.R = check.R; + i.name = check.name; + return( i ); + } + } + } + + return null; + } + + private class IdPack { + int id; + Resources R; + String name; + + IdPack() { + + } + } + + private class FakeContext extends ContextWrapper { + // from perusing layoutinflater.java it basically uses the context + // for getResources() so we use this to fake it out + private Resources mResources = null; + private Resources.Theme mTheme = null; + private int mThemeResource = 0; + + FakeContext( Context c, Resources r ) { + super( c ); + mResources = r; + } + + // this is based on ContextImpl + // also override gettheme since it caches the old context resource + @Override + public void setTheme(int resid) { + mThemeResource = resid; + } + + @Override + public Resources.Theme getTheme() { + if (mTheme == null) { + if( mThemeResource == 0 ) { +// mThemeResource = com.android.internal.R.style.Theme; + try { + mThemeResource = (Integer) Class.forName( + "com.android.internal.R$style").getField("Theme").get(null); + }catch( Exception e ) { + + } + } + + mTheme = mResources.newTheme(); + if( mThemeResource != 0 ) { + mTheme.applyStyle(mThemeResource, true); + } + } + return mTheme; + } + + @Override + public Resources getResources() { + //Log.d( "fake", "returning fake resources" ); + return mResources; + } + } +} +
\ No newline at end of file |