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