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