/******************************************************************************* * Copyright 2012-present Pixate, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.pixate.freestyle.styling.virtualAdapters; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Map; import android.graphics.drawable.Drawable; import android.widget.CompoundButton; import com.pixate.freestyle.styling.PXRuleSet; import com.pixate.freestyle.styling.adapters.PXCompoundButtonStyleAdapter; import com.pixate.freestyle.styling.cache.PXStyleInfo; import com.pixate.freestyle.styling.stylers.PXStylerContext; import com.pixate.freestyle.util.PXDrawableUtil; import com.pixate.freestyle.util.PXLog; /** * A base class for virtual children for compound buttons icons. Every widget * that required this kind of support has to extend this class in order to * provide specific {@link #createAdditionalDrawableStates(int)} implementation * that is required when creating the state-drawables. * * @author Shalom Gibly */ public class PXVirtualCompoundButtonIconAdapter extends PXVirtualChildAdapter { private static String TAG = PXVirtualCompoundButtonIconAdapter.class.getSimpleName(); private static String ELEMENT_NAME = "icon"; private static PXVirtualCompoundButtonIconAdapter instance; /** * Returns a singleton instance of this class. * * @return a {@link PXVirtualCompoundButtonIconAdapter} */ public static PXVirtualCompoundButtonIconAdapter getInstance() { synchronized (PXVirtualCompoundButtonIconAdapter.class) { if (instance == null) { instance = new PXVirtualCompoundButtonIconAdapter(); } } return instance; } protected PXVirtualCompoundButtonIconAdapter() { } /** * Returns the supported pseudo classes that maps to the {@link Drawable} * states. General possible values that are acceptable by a {@link Drawable} * are: * <ul> * <li>"state_focused" * <li>"state_window_focused" * <li>"state_enabled" * <li>"state_checked" * <li>"state_selected" * <li>"state_active" * <li>"state_single" * <li>"state_first" * <li>"state_mid" * <li>"state_last" * <li>"state_pressed" * <li>"state_activated" * <li>"state_hovered" * <li>"state_drag_can_accept" * <li>"state_drag_hovered" * </ul> * Note: The returned View list of pseudo class will omit the "state_" * prefix from those values. * * @return A list of supported pseudo classes. * @see PXDrawableUtil#getSupportedStates() */ @Override public List<String> getSupportedPseudoClasses(Object styleable) { return new ArrayList<String>(PXDrawableUtil.getSupportedStates().keySet()); } /* * (non-Javadoc) * @see * com.pixate.freestyle.styling.adapters.PXStyleAdapter#getDefaultPseudoClass * (java.lang.Object) */ @Override public String getDefaultPseudoClass(Object styleable) { return PXStyleInfo.DEFAULT_STYLE; } /* * (non-Javadoc) * @see * com.pixate.freestyle.styling.adapters.PXStyleAdapter#getElementName(java * .lang.Object) */ @Override public String getElementName(Object object) { return ELEMENT_NAME; } /* * (non-Javadoc) * @see * com.pixate.freestyle.styling.adapters.PXStyleAdapter#updateStyle(java. * util.List, java.util.List) */ @Override public boolean updateStyle(List<PXRuleSet> ruleSets, List<PXStylerContext> contexts) { if (!super.updateStyle(ruleSets, contexts)) { return false; } // Style the compound button background image. We will construct the // drawable from then context states, and then set the constructed // drawable as a buttons-background using the // CompoundButton#setButtonBackground(Drawable) call. Note that this is // different than the View#setBackground(Drawable) call that is handled // in the default View adapter. CompoundButton view = (CompoundButton) contexts.get(0).getStyleable(); // Grab the existing states. Map<int[], Drawable> existingStates = PXDrawableUtil .getExistingStates(getBackgroundDrawable(view)); // Generate the new StateListDrawable and set it as the button's // drawable. view.setButtonDrawable(PXDrawableUtil.createDrawable(this, existingStates, ruleSets, contexts)); return true; } /* * (non-Javadoc) * @see com.pixate.freestyle.styling.adapters.PXViewStyleAdapter# * createAdditionalStates (int) */ @Override public int[][] createAdditionalDrawableStates(int initialValue) { // Grab the additional states from the compound button adapter. return PXCompoundButtonStyleAdapter.getInstance().createAdditionalDrawableStates( initialValue); } /** * Returns the button-background drawable of a view. Note that * {@link CompoundButton} views have a different way to set the background * than over views. * * @param view * @return A button's background drawable (can be null) */ protected static Drawable getBackgroundDrawable(CompoundButton view) { if (view == null) { return null; } // We have to get the drawable value through reflection... try { Field field = CompoundButton.class.getDeclaredField("mButtonDrawable"); field.setAccessible(true); return (Drawable) field.get(view); } catch (Exception e) { PXLog.e(TAG, e, "Error getting the mButtonDrawable value."); } return null; } }