1 /*
2  * Copyright (C) 2015 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.timer;
18 
19 import android.content.Context;
20 import android.os.SystemClock;
21 import android.text.TextUtils;
22 import android.util.AttributeSet;
23 import android.widget.ImageView;
24 import android.widget.LinearLayout;
25 import android.widget.TextView;
26 
27 import com.android.deskclock.CircleButtonsLayout;
28 import com.android.deskclock.R;
29 import com.android.deskclock.data.Timer;
30 
31 /**
32  * This view is a visual representation of a {@link Timer}.
33  */
34 class TimerItem extends LinearLayout {
35 
36     /** Displays the remaining time or time since expiration. */
37     private CountingTimerView mTimerText;
38 
39     /** Displays timer progress as a color circle that changes from white to red. */
40     private TimerCircleView mCircleView;
41 
42     /** A button that either resets the timer or adds time to it, depending on its state. */
43     private ImageView mResetAddButton;
44 
45     /** Displays the label associated with the timer. Tapping it presents an edit dialog. */
46     private TextView mLabelView;
47 
48     /** The last state of the timer that was rendered; used to avoid expensive operations. */
49     private Timer.State mLastState;
50 
TimerItem(Context context)51     public TimerItem(Context context) {
52         this(context, null);
53     }
54 
TimerItem(Context context, AttributeSet attrs)55     public TimerItem(Context context, AttributeSet attrs) {
56         super(context, attrs);
57     }
58 
59     @Override
onFinishInflate()60     protected void onFinishInflate() {
61         super.onFinishInflate();
62         mLabelView = (TextView) findViewById(R.id.timer_label);
63         mResetAddButton = (ImageView) findViewById(R.id.reset_add);
64         mCircleView = (TimerCircleView) findViewById(R.id.timer_time);
65         mTimerText = (CountingTimerView) findViewById(R.id.timer_time_text);
66 
67         // This layout positions dynamically positions the label and reset buttons.
68         final CircleButtonsLayout cbl = (CircleButtonsLayout) findViewById(R.id.timer_circle);
69         cbl.setCircleTimerViewIds(R.id.timer_time, R.id.reset_add, R.id.timer_label);
70     }
71 
72     /**
73      * Updates this view to display the latest state of the {@code timer}.
74      */
update(Timer timer)75     void update(Timer timer) {
76         // Update the time.
77         mTimerText.setTime(timer.getRemainingTime(), false, true);
78 
79         // Update the progress of the circle.
80         mCircleView.update(timer);
81 
82         // Update the label if it changed.
83         final String label = timer.getLabel();
84         if (!TextUtils.equals(label, mLabelView.getText())) {
85             mLabelView.setText(label);
86         }
87 
88         // Update visibility of things that may blink.
89         final boolean blinkOff = SystemClock.elapsedRealtime() % 1000 < 500;
90         mCircleView.setVisibility(timer.isExpired() && blinkOff ? INVISIBLE : VISIBLE);
91         mTimerText.showTime(!timer.isPaused() || !blinkOff);
92 
93         // Update some potentially expensive areas of the user interface only on state changes.
94         if (timer.getState() != mLastState) {
95             mLastState = timer.getState();
96             switch (mLastState) {
97                 case RESET: {
98                     final String resetDesc = getResources().getString(R.string.timer_reset);
99                     mResetAddButton.setImageResource(R.drawable.ic_reset);
100                     mResetAddButton.setContentDescription(resetDesc);
101                     mTimerText.setTimeStrTextColor(false, true);
102                     break;
103                 }
104                 case RUNNING: {
105                     final String addTimeDesc = getResources().getString(R.string.timer_plus_one);
106                     mResetAddButton.setImageResource(R.drawable.ic_plusone);
107                     mResetAddButton.setContentDescription(addTimeDesc);
108                     mTimerText.setTimeStrTextColor(false, true);
109                     break;
110                 }
111                 case PAUSED: {
112                     final String resetDesc = getResources().getString(R.string.timer_reset);
113                     mResetAddButton.setImageResource(R.drawable.ic_reset);
114                     mResetAddButton.setContentDescription(resetDesc);
115                     mTimerText.setTimeStrTextColor(false, true);
116                     break;
117                 }
118                 case EXPIRED: {
119                     final String addTimeDesc = getResources().getString(R.string.timer_plus_one);
120                     mResetAddButton.setImageResource(R.drawable.ic_plusone);
121                     mResetAddButton.setContentDescription(addTimeDesc);
122                     mTimerText.setTimeStrTextColor(true, true);
123                     break;
124                 }
125             }
126         }
127     }
128 }