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