1/* 2 * Copyright (C) 2008 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 17package com.android.deskclock; 18 19import android.animation.Animator; 20import android.animation.AnimatorListenerAdapter; 21import android.content.Context; 22import android.content.res.Configuration; 23import android.graphics.Color; 24import android.os.Bundle; 25import android.util.AttributeSet; 26import android.view.LayoutInflater; 27import android.view.View; 28import android.widget.Button; 29import android.widget.ImageButton; 30import android.widget.LinearLayout; 31 32import com.android.deskclock.timer.TimerView; 33 34 35public class TimerSetupView extends LinearLayout implements Button.OnClickListener, 36 Button.OnLongClickListener{ 37 38 protected int mInputSize = 5; 39 40 protected final Button mNumbers [] = new Button [10]; 41 protected int mInput [] = new int [mInputSize]; 42 protected int mInputPointer = -1; 43 protected Button mLeft, mRight; 44 protected ImageButton mStart; 45 protected ImageButton mDelete; 46 protected TimerView mEnteredTime; 47 protected View mDivider; 48 protected final Context mContext; 49 50 private final AnimatorListenerAdapter mHideFabAnimatorListener = new AnimatorListenerAdapter() { 51 @Override 52 public void onAnimationEnd(Animator animation) { 53 if (mStart != null) { 54 mStart.setScaleX(1.0f); 55 mStart.setScaleY(1.0f); 56 mStart.setVisibility(View.INVISIBLE); 57 } 58 } 59 }; 60 61 private final AnimatorListenerAdapter mShowFabAnimatorListener = new AnimatorListenerAdapter() { 62 @Override 63 public void onAnimationStart(Animator animation) { 64 if (mStart != null) { 65 mStart.setVisibility(View.VISIBLE); 66 } 67 } 68 }; 69 70 public TimerSetupView(Context context) { 71 this(context, null); 72 } 73 74 public TimerSetupView(Context context, AttributeSet attrs) { 75 super(context, attrs); 76 mContext = context; 77 LayoutInflater layoutInflater = 78 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 79 layoutInflater.inflate(R.layout.time_setup_view, this); 80 } 81 82 @Override 83 protected void onFinishInflate() { 84 super.onFinishInflate(); 85 86 View v1 = findViewById(R.id.first); 87 View v2 = findViewById(R.id.second); 88 View v3 = findViewById(R.id.third); 89 View v4 = findViewById(R.id.fourth); 90 91 mEnteredTime = (TimerView)findViewById(R.id.timer_time_text); 92 mDelete = (ImageButton)findViewById(R.id.delete); 93 mDelete.setOnClickListener(this); 94 mDelete.setOnLongClickListener(this); 95 mDivider = findViewById(R.id.divider); 96 97 mNumbers[1] = (Button)v1.findViewById(R.id.key_left); 98 mNumbers[2] = (Button)v1.findViewById(R.id.key_middle); 99 mNumbers[3] = (Button)v1.findViewById(R.id.key_right); 100 101 mNumbers[4] = (Button)v2.findViewById(R.id.key_left); 102 mNumbers[5] = (Button)v2.findViewById(R.id.key_middle); 103 mNumbers[6] = (Button)v2.findViewById(R.id.key_right); 104 105 mNumbers[7] = (Button)v3.findViewById(R.id.key_left); 106 mNumbers[8] = (Button)v3.findViewById(R.id.key_middle); 107 mNumbers[9] = (Button)v3.findViewById(R.id.key_right); 108 109 mLeft = (Button)v4.findViewById(R.id.key_left); 110 mNumbers[0] = (Button)v4.findViewById(R.id.key_middle); 111 mRight = (Button)v4.findViewById(R.id.key_right); 112 setLeftRightEnabled(false); 113 114 for (int i = 0; i < 10; i++) { 115 mNumbers[i].setOnClickListener(this); 116 mNumbers[i].setText(String.format("%d", i)); 117 mNumbers[i].setTextColor(Color.WHITE); 118 mNumbers[i].setTag(R.id.numbers_key, new Integer(i)); 119 } 120 updateTime(); 121 } 122 123 public void registerStartButton(ImageButton start) { 124 mStart = start; 125 initializeStartButtonVisibility(); 126 } 127 128 private void initializeStartButtonVisibility() { 129 if (mStart != null) { 130 mStart.setVisibility(isInputHasValue() ? View.VISIBLE : View.INVISIBLE); 131 } 132 } 133 134 private void updateStartButton() { 135 setFabButtonVisibility(isInputHasValue() /* show or hide */); 136 } 137 138 public void updateDeleteButtonAndDivider() { 139 final boolean enabled = isInputHasValue(); 140 if (mDelete != null) { 141 mDelete.setEnabled(enabled); 142 mDivider.setBackgroundResource(enabled ? R.color.hot_pink : R.color.dialog_gray); 143 } 144 } 145 146 private boolean isInputHasValue() { 147 return mInputPointer != -1; 148 } 149 150 private void setFabButtonVisibility(boolean show) { 151 final int finalVisibility = show ? View.VISIBLE : View.INVISIBLE; 152 if (mStart == null || mStart.getVisibility() == finalVisibility) { 153 // Fab is not initialized yet or already shown/hidden 154 return; 155 } 156 157 final Animator scaleAnimator = AnimatorUtils.getScaleAnimator( 158 mStart, show ? 0.0f : 1.0f, show ? 1.0f : 0.0f); 159 scaleAnimator.setDuration(AnimatorUtils.ANIM_DURATION_SHORT); 160 scaleAnimator.addListener(show ? mShowFabAnimatorListener : mHideFabAnimatorListener); 161 scaleAnimator.start(); 162 } 163 164 @Override 165 public void onClick(View v) { 166 doOnClick(v); 167 updateStartButton(); 168 updateDeleteButtonAndDivider(); 169 } 170 171 protected void doOnClick(View v) { 172 173 Integer val = (Integer) v.getTag(R.id.numbers_key); 174 // A number was pressed 175 if (val != null) { 176 // pressing "0" as the first digit does nothing 177 if (mInputPointer == -1 && val == 0) { 178 return; 179 } 180 if (mInputPointer < mInputSize - 1) { 181 for (int i = mInputPointer; i >= 0; i--) { 182 mInput[i+1] = mInput[i]; 183 } 184 mInputPointer++; 185 mInput [0] = val; 186 updateTime(); 187 } 188 return; 189 } 190 191 // other keys 192 if (v == mDelete) { 193 if (mInputPointer >= 0) { 194 for (int i = 0; i < mInputPointer; i++) { 195 mInput[i] = mInput[i + 1]; 196 } 197 mInput[mInputPointer] = 0; 198 mInputPointer--; 199 updateTime(); 200 } 201 } 202 } 203 204 @Override 205 public boolean onLongClick(View v) { 206 if (v == mDelete) { 207 reset(); 208 updateStartButton(); 209 updateDeleteButtonAndDivider(); 210 return true; 211 } 212 return false; 213 } 214 215 protected void updateTime() { 216 mEnteredTime.setTime(mInput[4], mInput[3], mInput[2], 217 mInput[1] * 10 + mInput[0]); 218 } 219 220 public void reset() { 221 for (int i = 0; i < mInputSize; i ++) { 222 mInput[i] = 0; 223 } 224 mInputPointer = -1; 225 updateTime(); 226 } 227 228 public int getTime() { 229 return mInput[4] * 3600 + mInput[3] * 600 + mInput[2] * 60 + mInput[1] * 10 + mInput[0]; 230 } 231 232 public void saveEntryState(Bundle outState, String key) { 233 outState.putIntArray(key, mInput); 234 } 235 236 public void restoreEntryState(Bundle inState, String key) { 237 int[] input = inState.getIntArray(key); 238 if (input != null && mInputSize == input.length) { 239 for (int i = 0; i < mInputSize; i++) { 240 mInput[i] = input[i]; 241 if (mInput[i] != 0) { 242 mInputPointer = i; 243 } 244 } 245 updateTime(); 246 } 247 initializeStartButtonVisibility(); 248 } 249 250 protected void setLeftRightEnabled(boolean enabled) { 251 mLeft.setEnabled(enabled); 252 mRight.setEnabled(enabled); 253 if (!enabled) { 254 mLeft.setContentDescription(null); 255 mRight.setContentDescription(null); 256 } 257 } 258} 259