OSDN Git Service

b/2123455 Single tap on an event will always launch the event details.
[android-x86/packages-apps-Calendar.git] / src / com / android / calendar / CalendarActivity.java
1 /*
2  * Copyright (C) 2007 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.calendar;
18
19 import android.app.Activity;
20 import android.content.BroadcastReceiver;
21 import android.content.ContentResolver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.database.ContentObserver;
26 import android.os.Bundle;
27 import android.os.Handler;
28 import android.provider.Calendar;
29 import android.text.format.Time;
30 import android.view.GestureDetector;
31 import android.view.Menu;
32 import android.view.MenuItem;
33 import android.view.MotionEvent;
34 import android.view.View;
35 import android.view.animation.Animation;
36 import android.view.animation.AnimationUtils;
37 import android.view.animation.TranslateAnimation;
38 import android.widget.ProgressBar;
39 import android.widget.ViewSwitcher;
40
41 import dalvik.system.VMRuntime;
42
43 /**
44  * This is the base class for Day and Week Activities.
45  */
46 public class CalendarActivity extends Activity implements Navigator {
47
48     private static final long INITIAL_HEAP_SIZE = 4*1024*1024;
49     private static final long ANIMATION_DURATION = 400;
50
51     protected static final String BUNDLE_KEY_RESTORE_TIME = "key_restore_time";
52
53     private ContentResolver mContentResolver;
54
55     protected ProgressBar mProgressBar;
56     protected ViewSwitcher mViewSwitcher;
57     protected Animation mInAnimationForward;
58     protected Animation mOutAnimationForward;
59     protected Animation mInAnimationBackward;
60     protected Animation mOutAnimationBackward;
61     EventLoader mEventLoader;
62
63     Time mSelectedDay = new Time();
64
65     /* package */ GestureDetector mGestureDetector;
66
67     /**
68      * Listens for intent broadcasts
69      */
70     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
71         @Override
72         public void onReceive(Context context, Intent intent) {
73             String action = intent.getAction();
74             if (action.equals(Intent.ACTION_TIME_CHANGED)
75                     || action.equals(Intent.ACTION_DATE_CHANGED)
76                     || action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
77                 eventsChanged();
78             }
79         }
80     };
81
82     // Create an observer so that we can update the views whenever a
83     // Calendar event changes.
84     private ContentObserver mObserver = new ContentObserver(new Handler())
85     {
86         @Override
87         public boolean deliverSelfNotifications() {
88             return true;
89         }
90
91         @Override
92         public void onChange(boolean selfChange) {
93             eventsChanged();
94         }
95     };
96
97     @Override
98     protected void onCreate(Bundle icicle) {
99         super.onCreate(icicle);
100
101         // Eliminate extra GCs during startup by setting the initial heap size to 4MB.
102         // TODO: We should restore the old heap size once the activity reaches the idle state
103         VMRuntime.getRuntime().setMinimumHeapSize(INITIAL_HEAP_SIZE);
104
105         setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
106         mContentResolver = getContentResolver();
107
108         mInAnimationForward = AnimationUtils.loadAnimation(this, R.anim.slide_left_in);
109         mOutAnimationForward = AnimationUtils.loadAnimation(this, R.anim.slide_left_out);
110         mInAnimationBackward = AnimationUtils.loadAnimation(this, R.anim.slide_right_in);
111         mOutAnimationBackward = AnimationUtils.loadAnimation(this, R.anim.slide_right_out);
112
113         mGestureDetector = new GestureDetector(this, new CalendarGestureListener());
114         mEventLoader = new EventLoader(this);
115     }
116
117     @Override
118     protected void onRestoreInstanceState(Bundle savedInstanceState) {
119         super.onRestoreInstanceState(savedInstanceState);
120
121         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
122         Time time = new Time();
123         time.set(savedInstanceState.getLong(BUNDLE_KEY_RESTORE_TIME));
124         view.setSelectedDay(time);
125     }
126
127     @Override
128     protected void onNewIntent(Intent intent) {
129         long timeMillis = Utils.timeFromIntentInMillis(intent);
130         if (timeMillis > 0) {
131             Time time = new Time();
132             time.set(timeMillis);
133             goTo(time);
134         }
135     }
136
137     @Override
138     protected void onResume() {
139         super.onResume();
140         mEventLoader.startBackgroundThread();
141         eventsChanged();
142
143         // Register for Intent broadcasts
144         IntentFilter filter = new IntentFilter();
145
146         filter.addAction(Intent.ACTION_TIME_CHANGED);
147         filter.addAction(Intent.ACTION_DATE_CHANGED);
148         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
149         registerReceiver(mIntentReceiver, filter);
150
151         mContentResolver.registerContentObserver(Calendar.Events.CONTENT_URI,
152                 true, mObserver);
153     }
154
155     @Override
156     protected void onSaveInstanceState(Bundle outState) {
157         super.onSaveInstanceState(outState);
158
159         outState.putLong(BUNDLE_KEY_RESTORE_TIME, getSelectedTimeInMillis());
160     }
161
162     @Override
163     protected void onPause() {
164         super.onPause();
165         mContentResolver.unregisterContentObserver(mObserver);
166         unregisterReceiver(mIntentReceiver);
167
168         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
169         view.cleanup();
170         view = (CalendarView) mViewSwitcher.getNextView();
171         view.cleanup();
172         mEventLoader.stopBackgroundThread();
173     }
174
175     void startProgressSpinner() {
176         // start the progress spinner
177         mProgressBar.setVisibility(View.VISIBLE);
178     }
179
180     void stopProgressSpinner() {
181         // stop the progress spinner
182         mProgressBar.setVisibility(View.GONE);
183     }
184
185     /* Navigator interface methods */
186     public void goTo(Time time) {
187         CalendarView current = (CalendarView) mViewSwitcher.getCurrentView();
188
189         if (current.getSelectedTime().before(time)) {
190             mViewSwitcher.setInAnimation(mInAnimationForward);
191             mViewSwitcher.setOutAnimation(mOutAnimationForward);
192         } else {
193             mViewSwitcher.setInAnimation(mInAnimationBackward);
194             mViewSwitcher.setOutAnimation(mOutAnimationBackward);
195         }
196
197         CalendarView next = (CalendarView) mViewSwitcher.getNextView();
198         next.setSelectedDay(time);
199         next.reloadEvents();
200         mViewSwitcher.showNext();
201         next.requestFocus();
202     }
203
204     /**
205      * Returns the selected time in milliseconds. The milliseconds are measured
206      * in UTC milliseconds from the epoch and uniquely specifies any selectable
207      * time.
208      *
209      * @return the selected time in milliseconds
210      */
211     public long getSelectedTimeInMillis() {
212         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
213         return view.getSelectedTimeInMillis();
214     }
215
216     public long getSelectedTime() {
217         return getSelectedTimeInMillis();
218     }
219
220     public void goToToday() {
221         mSelectedDay.set(System.currentTimeMillis());
222         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
223         view.setSelectedDay(mSelectedDay);
224         view.reloadEvents();
225     }
226
227     public boolean getAllDay() {
228         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
229         return view.mSelectionAllDay;
230     }
231
232     void eventsChanged() {
233         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
234         view.clearCachedEvents();
235         view.reloadEvents();
236     }
237
238     Event getSelectedEvent() {
239         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
240         return view.getSelectedEvent();
241     }
242
243     boolean isEventSelected() {
244         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
245         return view.isEventSelected();
246     }
247
248     Event getNewEvent() {
249         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
250         return view.getNewEvent();
251     }
252
253     public CalendarView getNextView() {
254         return (CalendarView) mViewSwitcher.getNextView();
255     }
256
257     public View switchViews(boolean forward, float xOffSet, float width) {
258         float progress = Math.abs(xOffSet) / width;
259         if (progress > 1.0f) {
260             progress = 1.0f;
261         }
262
263         float inFromXValue, inToXValue;
264         float outFromXValue, outToXValue;
265         if (forward) {
266             inFromXValue = 1.0f - progress;
267             inToXValue = 0.0f;
268             outFromXValue = -progress;
269             outToXValue = -1.0f;
270         } else {
271             inFromXValue = progress - 1.0f;
272             inToXValue = 0.0f;
273             outFromXValue = progress;
274             outToXValue = 1.0f;
275         }
276
277         // We have to allocate these animation objects each time we switch views
278         // because that is the only way to set the animation parameters.
279         TranslateAnimation inAnimation = new TranslateAnimation(
280                 Animation.RELATIVE_TO_SELF, inFromXValue,
281                 Animation.RELATIVE_TO_SELF, inToXValue,
282                 Animation.ABSOLUTE, 0.0f,
283                 Animation.ABSOLUTE, 0.0f);
284
285         TranslateAnimation outAnimation = new TranslateAnimation(
286                 Animation.RELATIVE_TO_SELF, outFromXValue,
287                 Animation.RELATIVE_TO_SELF, outToXValue,
288                 Animation.ABSOLUTE, 0.0f,
289                 Animation.ABSOLUTE, 0.0f);
290
291         // Reduce the animation duration based on how far we have already swiped.
292         long duration = (long) (ANIMATION_DURATION * (1.0f - progress));
293         inAnimation.setDuration(duration);
294         outAnimation.setDuration(duration);
295         mViewSwitcher.setInAnimation(inAnimation);
296         mViewSwitcher.setOutAnimation(outAnimation);
297
298         CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
299         view.cleanup();
300         mViewSwitcher.showNext();
301         view = (CalendarView) mViewSwitcher.getCurrentView();
302         view.requestFocus();
303         view.reloadEvents();
304         return view;
305     }
306
307     @Override
308     public boolean onPrepareOptionsMenu(Menu menu) {
309         MenuHelper.onPrepareOptionsMenu(this, menu);
310         return super.onPrepareOptionsMenu(menu);
311     }
312
313     @Override
314     public boolean onCreateOptionsMenu(Menu menu) {
315         if (! MenuHelper.onCreateOptionsMenu(menu)) {
316             return false;
317         }
318         return super.onCreateOptionsMenu(menu);
319     }
320
321     @Override
322     public boolean onOptionsItemSelected(MenuItem item) {
323         if (MenuHelper.onOptionsItemSelected(this, item, this)) {
324             return true;
325         }
326         return super.onOptionsItemSelected(item);
327     }
328
329     @Override
330     public boolean onTouchEvent(MotionEvent ev) {
331         if (mGestureDetector.onTouchEvent(ev)) {
332             return true;
333         }
334         return super.onTouchEvent(ev);
335     }
336
337     class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
338         @Override
339         public boolean onSingleTapUp(MotionEvent ev) {
340             CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
341             view.doSingleTapUp(ev);
342             return true;
343         }
344
345         @Override
346         public void onLongPress(MotionEvent ev) {
347             CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
348             view.doLongPress(ev);
349         }
350
351         @Override
352         public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
353             CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
354             view.doScroll(e1, e2, distanceX, distanceY);
355             return true;
356         }
357
358         @Override
359         public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
360             CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
361             view.doFling(e1, e2, velocityX, velocityY);
362             return true;
363         }
364
365         @Override
366         public boolean onDown(MotionEvent ev) {
367             CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
368             view.doDown(ev);
369             return true;
370         }
371     }
372 }
373