/** * Copyright (C) 2010-2012 Regis Montoya (aka r3gis - www.r3gis.fr) * This file is part of CSipSimple. * * CSipSimple 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. * If you own a pjsip commercial license you can also redistribute it * and/or modify it under the terms of the GNU Lesser General Public License * as an android library. * * CSipSimple 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 CSipSimple. If not, see <http://www.gnu.org/licenses/>. */ package com.csipsimple.utils; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.res.Resources; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.StateListDrawable; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.ImageView; import android.widget.TextView; import com.actionbarsherlock.internal.utils.UtilityWrapper; import com.csipsimple.R; import com.csipsimple.api.SipConfigManager; import com.csipsimple.api.SipManager; import java.util.HashMap; import java.util.List; public class Theme { private static final String THIS_FILE = "Theme"; private final PackageManager pm; private Resources remoteRes = null; private PackageInfo pInfos = null; public Theme(Context ctxt, String packageName) { pm = ctxt.getPackageManager(); ComponentName cn = ComponentName.unflattenFromString(packageName); try { pInfos = pm.getPackageInfo(cn.getPackageName(), 0); remoteRes = pm.getResourcesForApplication(cn.getPackageName()); } catch (NameNotFoundException e) { Log.e(THIS_FILE, "Impossible to get resources from " + cn.toShortString()); remoteRes = null; pInfos = null; } } public static Theme getCurrentTheme(Context ctxt) { String themeName = SipConfigManager.getPreferenceStringValue(ctxt, SipConfigManager.THEME); if(!TextUtils.isEmpty(themeName)) { return new Theme(ctxt, themeName); } return null; } public static HashMap<String, String> getAvailableThemes(Context ctxt){ HashMap<String, String> result = new HashMap<String, String>(); result.put("", ctxt.getResources().getString(R.string.app_name)); PackageManager packageManager = ctxt.getPackageManager(); Intent it = new Intent(SipManager.ACTION_GET_DRAWABLES); List<ResolveInfo> availables = packageManager.queryBroadcastReceivers(it, 0); Log.d(THIS_FILE, "We found " + availables.size() + "themes"); for(ResolveInfo resInfo : availables) { Log.d(THIS_FILE, "We have -- "+resInfo); ActivityInfo actInfos = resInfo.activityInfo; ComponentName cmp = new ComponentName(actInfos.packageName, actInfos.name); String label = (String) actInfos.loadLabel(packageManager); if(TextUtils.isEmpty(label)) { label = (String) resInfo.loadLabel(packageManager); } result.put(cmp.flattenToString(), label); } return result; } public Drawable getDrawableResource(String name) { if(remoteRes != null && pInfos != null) { int id = remoteRes.getIdentifier(name, "drawable", pInfos.packageName); return pm.getDrawable(pInfos.packageName, id, pInfos.applicationInfo); }else { Log.d(THIS_FILE, "No results yet !! "); } return null; } public Integer getDimension(String name) { if(remoteRes != null && pInfos != null) { int id = remoteRes.getIdentifier(name, "dimen", pInfos.packageName); if(id > 0) { return remoteRes.getDimensionPixelSize(id); } }else { Log.d(THIS_FILE, "No results yet !! "); } return null; } public Integer getColor(String name) { if(remoteRes != null && pInfos != null) { int id = remoteRes.getIdentifier(name, "color", pInfos.packageName); if(id > 0) { return remoteRes.getColor(id); } }else { Log.d(THIS_FILE, "No results yet !! "); } return null; } public void applyBackgroundDrawable(View button, String res) { Drawable d = getDrawableResource(res); if(d != null) { UtilityWrapper.getInstance().setBackgroundDrawable(button, d); } } public void applyImageDrawable(ImageView subV, String res) { Drawable d = getDrawableResource(res); if(d != null) { subV.setImageDrawable(d); } } public void applyTextColor(TextView subV, String name) { Integer color = getColor(name); if(color != null) { subV.setTextColor(color); } } public void applyBackgroundStateListDrawable(View v, String prefix) { Drawable pressed = getDrawableResource(prefix+"_press"); Drawable focused = getDrawableResource(prefix+"_focus"); Drawable normal = getDrawableResource(prefix+"_normal"); if(focused == null) { focused = pressed; } StateListDrawable std = null; if(pressed != null && focused != null && normal != null) { std = new StateListDrawable(); std.addState(new int[] {android.R.attr.state_pressed}, pressed); std.addState(new int[] {android.R.attr.state_focused}, focused); std.addState(new int[] {}, normal); } if(std != null) { UtilityWrapper.getInstance().setBackgroundDrawable(v, std); } } public void applyBackgroundStateListSelectableDrawable(View v, String prefix) { Drawable pressed = getDrawableResource(prefix+"_press"); Drawable focused = getDrawableResource(prefix+"_focus"); Drawable selected = getDrawableResource(prefix+"_selected"); Drawable unselected = getDrawableResource(prefix+"_unselected"); if(focused == null) { focused = pressed; } StateListDrawable std = null; if(pressed != null && focused != null && selected != null && unselected != null) { std = new StateListDrawable(); std.addState(new int[] {android.R.attr.state_pressed}, pressed); std.addState(new int[] {android.R.attr.state_focused}, focused); std.addState(new int[] {android.R.attr.state_selected}, selected); std.addState(new int[] {}, unselected); } if(std != null) { UtilityWrapper.getInstance().setBackgroundDrawable(v, std); } } public void applyLayoutMargin(View v, String prefix) { ViewGroup.MarginLayoutParams lp = null; try { lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams(); }catch (ClassCastException e) { Log.e(THIS_FILE, "Trying to apply layout params to invalid layout " + v.getLayoutParams()); } Integer marginTop = getDimension(prefix + "_top"); Integer marginBottom = getDimension(prefix + "_bottom"); Integer marginRight = getDimension(prefix + "_right"); Integer marginLeft = getDimension(prefix + "_left"); if(marginTop != null) { lp.topMargin = marginTop; } if(marginBottom != null) { lp.bottomMargin = marginBottom; } if(marginRight != null) { lp.rightMargin = marginRight; } if(marginLeft != null) { lp.leftMargin = marginLeft; } v.setLayoutParams(lp); } public void applyLayoutSize(View v, String prefix) { LayoutParams lp = v.getLayoutParams(); Integer width = getDimension(prefix + "_width"); Integer height = getDimension(prefix + "_height"); if(width != null) { lp.width = width; } if(height != null) { lp.height = height; } v.setLayoutParams(lp); } private static boolean needRepeatableFix() { // In ICS and upper the problem is fixed, so no need to apply by code return (!Compatibility.isCompatible(14)); } /** * @param v The view to fix background of. * @see #fixRepeatableDrawable(Drawable) */ public static void fixRepeatableBackground(View v) { if(!needRepeatableFix()) { return; } fixRepeatableDrawable(v.getBackground()); } /** * Fix the repeatable background of a drawable. * This support both bitmap and layer drawables * @param d the drawable to fix. */ public static void fixRepeatableDrawable(Drawable d) { if(!needRepeatableFix()) { return; } if (d instanceof LayerDrawable) { LayerDrawable layer = (LayerDrawable) d; for (int i = 0; i < layer.getNumberOfLayers(); i++) { fixRepeatableDrawable(layer.getDrawable(i)); } } else if (d instanceof BitmapDrawable) { fixRepeatableBitmapDrawable((BitmapDrawable) d); } } /** * Fix the repeatable background of a bitmap drawable. * This only support a BitmapDrawable * @param d the BitmapDrawable to set repeatable. */ public static void fixRepeatableBitmapDrawable(BitmapDrawable d) { if(!needRepeatableFix()) { return; } // I don't want to mutate because it's better to share the drawable fix for all that share this constant state //d.mutate(); //Log.d(THIS_FILE, "Exisiting tile mode : " + d.getTileModeX() + ", "+ d.getTileModeY()); d.setTileModeXY(d.getTileModeX(), d.getTileModeY()); } }