blob: 8034b28ea1ff7ddac7dd41c8bafa98f697052b5d [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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.android.calendar;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.widget.Button;
/**
* <p>
* A button with more than two states. When the button is pressed
* or clicked, the state transitions automatically.
* </p>
*
* <p><strong>XML attributes</strong></p>
* <p>
* See {@link R.styleable#MultiStateButton
* MultiStateButton Attributes}, {@link android.R.styleable#Button Button
* Attributes}, {@link android.R.styleable#TextView TextView Attributes}, {@link
* android.R.styleable#View View Attributes}
* </p>
*/
public class MultiStateButton extends Button {
//The current state for this button, ranging from 0 to maxState-1
private int mState;
//The maximum number of states allowed for this button.
private int mMaxStates;
//The currently displaying resource ID. This gets set to a default on creation and remains
//on the last set if the resources get set to null.
private int mButtonResource;
//A list of all drawable resources used by this button in the order it uses them.
private int[] mButtonResources;
private Drawable mButtonDrawable;
public MultiStateButton(Context context) {
this(context, null);
}
public MultiStateButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MultiStateButton(Context context, AttributeSet attrs, int defStyle) {
//Currently using the standard buttonStyle, will update when new resources are added.
super(context, attrs, defStyle);
mMaxStates = 1;
mState = 0;
//TODO add a more generic default button
mButtonResources = new int[] { R.drawable.widget_show };
setButtonDrawable(mButtonResources[mState]);
}
@Override
public boolean performClick() {
/* When clicked, toggle the state */
transitionState();
return super.performClick();
}
public void transitionState() {
mState = (mState + 1) % mMaxStates;
setButtonDrawable(mButtonResources[mState]);
}
/**
* Allows for a new set of drawable resource ids to be set.
*
* This sets the maximum states allowed to the length of the resources array. It will also
* set the current state to the maximum allowed if it's greater than the new max.
*/
public void setButtonResources(int[] resources) throws IllegalArgumentException {
if(resources == null) {
throw new IllegalArgumentException("Button resources cannot be null");
}
mMaxStates = resources.length;
if(mState >= mMaxStates) {
mState = mMaxStates - 1;
}
mButtonResources = resources;
}
/**
* Attempts to set the state. Returns true if successful, false otherwise.
*/
public boolean setState(int state){
if(state >= mMaxStates || state < 0) {
//When moved out of Calendar the tag should be changed.
Log.w("Cal", "MultiStateButton state set to value greater than maxState or < 0");
return false;
}
mState = state;
setButtonDrawable(mButtonResources[mState]);
return true;
}
public int getState() {
return mState;
}
/**
* Set the background to a given Drawable, identified by its resource id.
*
* @param resid the resource id of the drawable to use as the background
*/
public void setButtonDrawable(int resid) {
if (resid != 0 && resid == mButtonResource) {
return;
}
mButtonResource = resid;
Drawable d = null;
if (mButtonResource != 0) {
d = getResources().getDrawable(mButtonResource);
}
setButtonDrawable(d);
}
/**
* Set the background to a given Drawable
*
* @param d The Drawable to use as the background
*/
public void setButtonDrawable(Drawable d) {
if (d != null) {
if (mButtonDrawable != null) {
mButtonDrawable.setCallback(null);
unscheduleDrawable(mButtonDrawable);
}
d.setCallback(this);
d.setState(getDrawableState());
d.setVisible(getVisibility() == VISIBLE, false);
mButtonDrawable = d;
mButtonDrawable.setState(null);
setMinHeight(mButtonDrawable.getIntrinsicHeight());
setWidth(mButtonDrawable.getIntrinsicWidth());
}
refreshDrawableState();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mButtonDrawable != null) {
final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
final int horizontalGravity = getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK;
final int height = mButtonDrawable.getIntrinsicHeight();
final int width = mButtonDrawable.getIntrinsicWidth();
int y = 0;
int x = 0;
switch (verticalGravity) {
case Gravity.BOTTOM:
y = getHeight() - height;
break;
case Gravity.CENTER_VERTICAL:
y = (getHeight() - height) / 2;
break;
}
switch (horizontalGravity) {
case Gravity.RIGHT:
x = getWidth() - width;
break;
case Gravity.CENTER_HORIZONTAL:
x = (getWidth() - width) / 2;
break;
}
mButtonDrawable.setBounds(x, y, x + width, y + height);
mButtonDrawable.draw(canvas);
}
}
}