Home | History | Annotate | Download | only in calendar
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 package com.android.calendar;
     17 
     18 import android.content.Context;
     19 import android.content.res.TypedArray;
     20 import android.graphics.Canvas;
     21 import android.graphics.drawable.Drawable;
     22 import android.util.AttributeSet;
     23 import android.util.Log;
     24 import android.view.Gravity;
     25 import android.widget.Button;
     26 
     27 /**
     28  * <p>
     29  * A button with more than two states. When the button is pressed
     30  * or clicked, the state transitions automatically.
     31  * </p>
     32  *
     33  * <p><strong>XML attributes</strong></p>
     34  * <p>
     35  * See {@link R.styleable#MultiStateButton
     36  * MultiStateButton Attributes}, {@link android.R.styleable#Button Button
     37  * Attributes}, {@link android.R.styleable#TextView TextView Attributes}, {@link
     38  * android.R.styleable#View View Attributes}
     39  * </p>
     40  */
     41 
     42 public class MultiStateButton extends Button {
     43     //The current state for this button, ranging from 0 to maxState-1
     44     private int mState;
     45     //The maximum number of states allowed for this button.
     46     private int mMaxStates;
     47     //The currently displaying resource ID. This gets set to a default on creation and remains
     48     //on the last set if the resources get set to null.
     49     private int mButtonResource;
     50     //A list of all drawable resources used by this button in the order it uses them.
     51     private int[] mButtonResources;
     52     private Drawable mButtonDrawable;
     53     private String TAG = "MSB";
     54 
     55     public MultiStateButton(Context context) {
     56         this(context, null);
     57     }
     58 
     59     public MultiStateButton(Context context, AttributeSet attrs) {
     60         this(context, attrs, 0);
     61     }
     62 
     63     public MultiStateButton(Context context, AttributeSet attrs, int defStyle) {
     64         //Currently using the standard buttonStyle, will update when new resources are added.
     65         super(context, attrs, defStyle);
     66         mMaxStates = 1;
     67         mState = 0;
     68         //TODO add a more generic default button
     69         mButtonResources = new int[] { R.drawable.widget_show };
     70         setButtonDrawable(mButtonResources[mState]);
     71     }
     72 
     73     @Override
     74     public boolean performClick() {
     75         /* When clicked, toggle the state */
     76         transitionState();
     77         return super.performClick();
     78     }
     79 
     80     public void transitionState() {
     81         mState = (mState + 1) % mMaxStates;
     82         setButtonDrawable(mButtonResources[mState]);
     83     }
     84 
     85     /**
     86      * Allows for a new set of drawable resource ids to be set.
     87      *
     88      * This sets the maximum states allowed to the length of the resources array. It will also
     89      * set the current state to the maximum allowed if it's greater than the new max.
     90      */
     91     public void setButtonResources(int[] resources) throws IllegalArgumentException {
     92         if(resources == null) {
     93             throw new IllegalArgumentException("Button resources cannot be null");
     94         }
     95         mMaxStates = resources.length;
     96         if(mState >= mMaxStates) {
     97             mState = mMaxStates - 1;
     98         }
     99         mButtonResources = resources;
    100     }
    101 
    102     /**
    103      * Attempts to set the state. Returns true if successful, false otherwise.
    104      */
    105     public boolean setState(int state){
    106         if(state >= mMaxStates || state < 0) {
    107             //When moved out of Calendar the tag should be changed.
    108             Log.w("Cal", "MultiStateButton state set to value greater than maxState or < 0");
    109             return false;
    110         }
    111         mState = state;
    112         setButtonDrawable(mButtonResources[mState]);
    113         return true;
    114     }
    115 
    116     public int getState() {
    117         return mState;
    118     }
    119 
    120     /**
    121      * Set the background to a given Drawable, identified by its resource id.
    122      *
    123      * @param resid the resource id of the drawable to use as the background
    124      */
    125     public void setButtonDrawable(int resid) {
    126         if (resid != 0 && resid == mButtonResource) {
    127             return;
    128         }
    129 
    130         mButtonResource = resid;
    131 
    132         Drawable d = null;
    133         if (mButtonResource != 0) {
    134             d = getResources().getDrawable(mButtonResource);
    135         }
    136         setButtonDrawable(d);
    137     }
    138 
    139     /**
    140      * Set the background to a given Drawable
    141      *
    142      * @param d The Drawable to use as the background
    143      */
    144     public void setButtonDrawable(Drawable d) {
    145         if (d != null) {
    146             if (mButtonDrawable != null) {
    147                 mButtonDrawable.setCallback(null);
    148                 unscheduleDrawable(mButtonDrawable);
    149             }
    150             d.setCallback(this);
    151             d.setState(getDrawableState());
    152             d.setVisible(getVisibility() == VISIBLE, false);
    153             mButtonDrawable = d;
    154             mButtonDrawable.setState(null);
    155             setMinHeight(mButtonDrawable.getIntrinsicHeight());
    156             setWidth(mButtonDrawable.getIntrinsicWidth());
    157         }
    158         refreshDrawableState();
    159     }
    160 
    161     @Override
    162     protected void onDraw(Canvas canvas) {
    163         super.onDraw(canvas);
    164         if (mButtonDrawable != null) {
    165             final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
    166             final int horizontalGravity = getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK;
    167             final int height = mButtonDrawable.getIntrinsicHeight();
    168             final int width = mButtonDrawable.getIntrinsicWidth();
    169 
    170             int y = 0;
    171             int x = 0;
    172 
    173             switch (verticalGravity) {
    174                 case Gravity.BOTTOM:
    175                     y = getHeight() - height;
    176                     break;
    177                 case Gravity.CENTER_VERTICAL:
    178                     y = (getHeight() - height) / 2;
    179                     break;
    180             }
    181             switch (horizontalGravity) {
    182                 case Gravity.RIGHT:
    183                     x = getWidth() - width;
    184                     break;
    185                 case Gravity.CENTER_HORIZONTAL:
    186                     x = (getWidth() - width) / 2;
    187                     break;
    188             }
    189 
    190             mButtonDrawable.setBounds(x, y, x + width, y + height);
    191             mButtonDrawable.draw(canvas);
    192         }
    193     }
    194 }
    195