summaryrefslogtreecommitdiff
path: root/src/com/android/calendar/MultiStateButton.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/calendar/MultiStateButton.kt')
-rw-r--r--src/com/android/calendar/MultiStateButton.kt166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/com/android/calendar/MultiStateButton.kt b/src/com/android/calendar/MultiStateButton.kt
new file mode 100644
index 00000000..f86ee6ba
--- /dev/null
+++ b/src/com/android/calendar/MultiStateButton.kt
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2021 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
+
+/**
+ * A button with more than two states. When the button is pressed
+ * or clicked, the state transitions automatically.
+ *
+ * **XML attributes**
+ * See [ MultiStateButton Attributes][R.styleable.MultiStateButton],
+ * [Button][android.R.styleable.Button], [TextView Attributes][android.R.styleable.TextView],
+ * [ ][android.R.styleable.View]
+ *
+ */
+class MultiStateButton(context: Context?, attrs: AttributeSet?, defStyle: Int) :
+ Button(context, attrs, defStyle) {
+ //The current state for this button, ranging from 0 to maxState-1
+ var mState = 0
+ private set
+
+ //The maximum number of states allowed for this button.
+ private var mMaxStates = 1
+
+ //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 var mButtonResource = 0
+
+ //A list of all drawable resources used by this button in the order it uses them.
+ private var mButtonResources: IntArray
+ private var mButtonDrawable: Drawable? = null
+
+ constructor(context: Context?) : this(context, null) {}
+ constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0) {}
+
+ override fun performClick(): Boolean {
+ /* When clicked, toggle the state */
+ transitionState()
+ return super.performClick()
+ }
+
+ fun 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.
+ */
+ //@Throws(IllegalArgumentException::class)
+ fun setButtonResources(resources: IntArray?) {
+ if (resources == null) {
+ throw IllegalArgumentException("Button resources cannot be null")
+ }
+ mMaxStates = resources.size
+ if (mState >= mMaxStates) {
+ mState = mMaxStates - 1
+ }
+ mButtonResources = resources
+ }
+
+ /**
+ * Attempts to set the state. Returns true if successful, false otherwise.
+ */
+ fun setState(state: Int): Boolean {
+ 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
+ }
+
+ /**
+ * 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
+ */
+ fun setButtonDrawable(resid: Int) {
+ if (resid != 0 && resid == mButtonResource) {
+ return
+ }
+ mButtonResource = resid
+ var d: Drawable? = 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
+ */
+ fun setButtonDrawable(d: Drawable?) {
+ 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(getDrawableState())
+ setMinHeight(mButtonDrawable?.getIntrinsicHeight() ?: 0)
+ setWidth(mButtonDrawable?.getIntrinsicWidth() ?: 0)
+ }
+ refreshDrawableState()
+ }
+
+ protected override fun onDraw(canvas: Canvas) {
+ super.onDraw(canvas)
+ if (mButtonDrawable != null) {
+ val verticalGravity: Int = getGravity() and Gravity.VERTICAL_GRAVITY_MASK
+ val horizontalGravity: Int = getGravity() and Gravity.HORIZONTAL_GRAVITY_MASK
+ val height: Int = mButtonDrawable?.getIntrinsicHeight() ?: 0
+ val width: Int = mButtonDrawable?.getIntrinsicWidth() ?: 0
+ var y = 0
+ var x = 0
+ when (verticalGravity) {
+ Gravity.BOTTOM -> y = getHeight() - height
+ Gravity.CENTER_VERTICAL -> y = (getHeight() - height) / 2
+ }
+ when (horizontalGravity) {
+ Gravity.RIGHT -> x = getWidth() - width
+ Gravity.CENTER_HORIZONTAL -> x = (getWidth() - width) / 2
+ }
+ mButtonDrawable?.setBounds(x, y, x + width, y + height)
+ mButtonDrawable?.draw(canvas)
+ }
+ }
+
+ init {
+ //Currently using the standard buttonStyle, will update when new resources are added.
+ //TODO add a more generic default button
+ mButtonResources = intArrayOf(R.drawable.widget_show)
+ setButtonDrawable(mButtonResources[mState])
+ }
+} \ No newline at end of file