blob: 8034b28ea1ff7ddac7dd41c8bafa98f697052b5d [file] [log] [blame]
Erikac6a81d2010-01-26 15:42:15 -08001/*
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 */
16package com.android.calendar;
17
18import android.content.Context;
Erikac6a81d2010-01-26 15:42:15 -080019import android.graphics.Canvas;
20import android.graphics.drawable.Drawable;
21import android.util.AttributeSet;
22import android.util.Log;
23import android.view.Gravity;
24import 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
41public 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;
Erikac6a81d2010-01-26 15:42:15 -080052
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}