blob: 4d1a2a5ede2c8f7f4cab696fdbeed1e924f3c772 [file] [log] [blame]
The Android Open Source Project146de362009-03-03 19:32:18 -08001/*
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
17package com.android.calendar;
18
Erike0f6a5c2010-09-08 17:41:31 -070019import dalvik.system.VMRuntime;
20
The Android Open Source Project146de362009-03-03 19:32:18 -080021import android.app.Activity;
22import android.content.BroadcastReceiver;
23import android.content.ContentResolver;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
27import android.database.ContentObserver;
28import android.os.Bundle;
29import android.os.Handler;
30import android.provider.Calendar;
31import android.text.format.Time;
32import android.view.GestureDetector;
33import android.view.Menu;
34import android.view.MenuItem;
35import android.view.MotionEvent;
36import android.view.View;
37import android.view.animation.Animation;
38import android.view.animation.AnimationUtils;
The Android Open Source Project7abd8562009-03-05 14:34:37 -080039import android.view.animation.TranslateAnimation;
The Android Open Source Project146de362009-03-03 19:32:18 -080040import android.widget.ProgressBar;
41import android.widget.ViewSwitcher;
42
43/**
44 * This is the base class for Day and Week Activities.
45 */
46public class CalendarActivity extends Activity implements Navigator {
47
48 private static final long INITIAL_HEAP_SIZE = 4*1024*1024;
The Android Open Source Project7abd8562009-03-05 14:34:37 -080049 private static final long ANIMATION_DURATION = 400;
The Android Open Source Project146de362009-03-03 19:32:18 -080050
51 protected static final String BUNDLE_KEY_RESTORE_TIME = "key_restore_time";
52
53 private ContentResolver mContentResolver;
54
The Android Open Source Project146de362009-03-03 19:32:18 -080055 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
Erike0f6a5c2010-09-08 17:41:31 -070063 Time mSelectedDay;
64
65 // This gets run if the time zone is updated in the db
66 private Runnable mUpdateTZ = new Runnable() {
67 @Override
68 public void run() {
69 // We want this to keep the same day so we swap the tz
70 mSelectedDay.timezone = Utils.getTimeZone(CalendarActivity.this, this);
71 mSelectedDay.normalize(true);
72 }
73 };
The Android Open Source Project146de362009-03-03 19:32:18 -080074
75 /* package */ GestureDetector mGestureDetector;
76
77 /**
78 * Listens for intent broadcasts
79 */
80 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
81 @Override
82 public void onReceive(Context context, Intent intent) {
83 String action = intent.getAction();
84 if (action.equals(Intent.ACTION_TIME_CHANGED)
85 || action.equals(Intent.ACTION_DATE_CHANGED)
86 || action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
87 eventsChanged();
88 }
89 }
90 };
91
92 // Create an observer so that we can update the views whenever a
93 // Calendar event changes.
94 private ContentObserver mObserver = new ContentObserver(new Handler())
95 {
96 @Override
97 public boolean deliverSelfNotifications() {
98 return true;
99 }
100
101 @Override
102 public void onChange(boolean selfChange) {
103 eventsChanged();
104 }
105 };
106
107 @Override
108 protected void onCreate(Bundle icicle) {
109 super.onCreate(icicle);
110
Erike0f6a5c2010-09-08 17:41:31 -0700111 mSelectedDay = new Time(Utils.getTimeZone(this, mUpdateTZ));
112
The Android Open Source Project146de362009-03-03 19:32:18 -0800113 // Eliminate extra GCs during startup by setting the initial heap size to 4MB.
114 // TODO: We should restore the old heap size once the activity reaches the idle state
Michael Chan98ab9de2009-05-14 16:09:13 -0700115 VMRuntime.getRuntime().setMinimumHeapSize(INITIAL_HEAP_SIZE);
The Android Open Source Project146de362009-03-03 19:32:18 -0800116
117 setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
118 mContentResolver = getContentResolver();
119
120 mInAnimationForward = AnimationUtils.loadAnimation(this, R.anim.slide_left_in);
121 mOutAnimationForward = AnimationUtils.loadAnimation(this, R.anim.slide_left_out);
122 mInAnimationBackward = AnimationUtils.loadAnimation(this, R.anim.slide_right_in);
123 mOutAnimationBackward = AnimationUtils.loadAnimation(this, R.anim.slide_right_out);
124
125 mGestureDetector = new GestureDetector(this, new CalendarGestureListener());
126 mEventLoader = new EventLoader(this);
127 }
128
129 @Override
130 protected void onRestoreInstanceState(Bundle savedInstanceState) {
131 super.onRestoreInstanceState(savedInstanceState);
132
133 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
Erike0f6a5c2010-09-08 17:41:31 -0700134 Time time = new Time(Utils.getTimeZone(this, mUpdateTZ));
The Android Open Source Project146de362009-03-03 19:32:18 -0800135 time.set(savedInstanceState.getLong(BUNDLE_KEY_RESTORE_TIME));
136 view.setSelectedDay(time);
137 }
138
139 @Override
Michael Chan23f400c2009-08-14 13:03:39 -0700140 protected void onNewIntent(Intent intent) {
141 long timeMillis = Utils.timeFromIntentInMillis(intent);
142 if (timeMillis > 0) {
Erike0f6a5c2010-09-08 17:41:31 -0700143 Time time = new Time(Utils.getTimeZone(this, mUpdateTZ));
Michael Chan23f400c2009-08-14 13:03:39 -0700144 time.set(timeMillis);
Michael Chan79edc462009-09-28 16:50:46 -0700145 goTo(time, false);
Michael Chan23f400c2009-08-14 13:03:39 -0700146 }
147 }
148
149 @Override
The Android Open Source Project146de362009-03-03 19:32:18 -0800150 protected void onResume() {
151 super.onResume();
152 mEventLoader.startBackgroundThread();
153 eventsChanged();
Erik8ca2e942010-10-25 10:30:42 -0700154 CalendarView view = (CalendarView) mViewSwitcher.getNextView();
Erik69ab3342010-03-23 17:03:28 -0700155 view.updateIs24HourFormat();
Erike0f6a5c2010-09-08 17:41:31 -0700156 view.updateView();
The Android Open Source Project146de362009-03-03 19:32:18 -0800157
Erik8ca2e942010-10-25 10:30:42 -0700158 view = (CalendarView) mViewSwitcher.getCurrentView();
Erik69ab3342010-03-23 17:03:28 -0700159 view.updateIs24HourFormat();
Michael Chan2f87d8b2010-10-18 16:05:38 -0700160 view.updateView();
Erik69ab3342010-03-23 17:03:28 -0700161
The Android Open Source Project146de362009-03-03 19:32:18 -0800162 // Register for Intent broadcasts
163 IntentFilter filter = new IntentFilter();
164
165 filter.addAction(Intent.ACTION_TIME_CHANGED);
166 filter.addAction(Intent.ACTION_DATE_CHANGED);
167 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
168 registerReceiver(mIntentReceiver, filter);
169
170 mContentResolver.registerContentObserver(Calendar.Events.CONTENT_URI,
171 true, mObserver);
172 }
173
174 @Override
175 protected void onSaveInstanceState(Bundle outState) {
176 super.onSaveInstanceState(outState);
177
178 outState.putLong(BUNDLE_KEY_RESTORE_TIME, getSelectedTimeInMillis());
179 }
180
181 @Override
The Android Open Source Project146de362009-03-03 19:32:18 -0800182 protected void onPause() {
183 super.onPause();
184 mContentResolver.unregisterContentObserver(mObserver);
185 unregisterReceiver(mIntentReceiver);
186
187 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
188 view.cleanup();
189 view = (CalendarView) mViewSwitcher.getNextView();
190 view.cleanup();
191 mEventLoader.stopBackgroundThread();
192 }
193
194 void startProgressSpinner() {
195 // start the progress spinner
196 mProgressBar.setVisibility(View.VISIBLE);
197 }
198
199 void stopProgressSpinner() {
200 // stop the progress spinner
201 mProgressBar.setVisibility(View.GONE);
202 }
203
204 /* Navigator interface methods */
Michael Chan79edc462009-09-28 16:50:46 -0700205 public void goTo(Time time, boolean animate) {
206 if (animate) {
207 CalendarView current = (CalendarView) mViewSwitcher.getCurrentView();
208 if (current.getSelectedTime().before(time)) {
209 mViewSwitcher.setInAnimation(mInAnimationForward);
210 mViewSwitcher.setOutAnimation(mOutAnimationForward);
211 } else {
212 mViewSwitcher.setInAnimation(mInAnimationBackward);
213 mViewSwitcher.setOutAnimation(mOutAnimationBackward);
214 }
The Android Open Source Project146de362009-03-03 19:32:18 -0800215 }
216
217 CalendarView next = (CalendarView) mViewSwitcher.getNextView();
218 next.setSelectedDay(time);
219 next.reloadEvents();
220 mViewSwitcher.showNext();
221 next.requestFocus();
222 }
223
224 /**
225 * Returns the selected time in milliseconds. The milliseconds are measured
226 * in UTC milliseconds from the epoch and uniquely specifies any selectable
227 * time.
228 *
229 * @return the selected time in milliseconds
230 */
231 public long getSelectedTimeInMillis() {
232 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
233 return view.getSelectedTimeInMillis();
234 }
235
236 public long getSelectedTime() {
237 return getSelectedTimeInMillis();
238 }
239
240 public void goToToday() {
241 mSelectedDay.set(System.currentTimeMillis());
Erik2adb0a52010-09-10 17:17:53 -0700242 mSelectedDay.normalize(true);
The Android Open Source Project146de362009-03-03 19:32:18 -0800243 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
244 view.setSelectedDay(mSelectedDay);
245 view.reloadEvents();
246 }
247
248 public boolean getAllDay() {
249 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
250 return view.mSelectionAllDay;
251 }
252
253 void eventsChanged() {
254 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
255 view.clearCachedEvents();
256 view.reloadEvents();
257 }
258
259 Event getSelectedEvent() {
260 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
261 return view.getSelectedEvent();
262 }
263
264 boolean isEventSelected() {
265 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
266 return view.isEventSelected();
267 }
268
269 Event getNewEvent() {
270 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
271 return view.getNewEvent();
272 }
273
274 public CalendarView getNextView() {
275 return (CalendarView) mViewSwitcher.getNextView();
276 }
277
278 public View switchViews(boolean forward, float xOffSet, float width) {
The Android Open Source Project7abd8562009-03-05 14:34:37 -0800279 float progress = Math.abs(xOffSet) / width;
The Android Open Source Project7a8505f2009-03-05 15:45:11 -0800280 if (progress > 1.0f) {
281 progress = 1.0f;
282 }
Michael Chan23f400c2009-08-14 13:03:39 -0700283
The Android Open Source Project7abd8562009-03-05 14:34:37 -0800284 float inFromXValue, inToXValue;
285 float outFromXValue, outToXValue;
The Android Open Source Project146de362009-03-03 19:32:18 -0800286 if (forward) {
The Android Open Source Project7abd8562009-03-05 14:34:37 -0800287 inFromXValue = 1.0f - progress;
288 inToXValue = 0.0f;
289 outFromXValue = -progress;
290 outToXValue = -1.0f;
The Android Open Source Project146de362009-03-03 19:32:18 -0800291 } else {
The Android Open Source Project7abd8562009-03-05 14:34:37 -0800292 inFromXValue = progress - 1.0f;
293 inToXValue = 0.0f;
294 outFromXValue = progress;
295 outToXValue = 1.0f;
The Android Open Source Project146de362009-03-03 19:32:18 -0800296 }
Michael Chan23f400c2009-08-14 13:03:39 -0700297
The Android Open Source Project7abd8562009-03-05 14:34:37 -0800298 // We have to allocate these animation objects each time we switch views
299 // because that is the only way to set the animation parameters.
300 TranslateAnimation inAnimation = new TranslateAnimation(
301 Animation.RELATIVE_TO_SELF, inFromXValue,
302 Animation.RELATIVE_TO_SELF, inToXValue,
303 Animation.ABSOLUTE, 0.0f,
304 Animation.ABSOLUTE, 0.0f);
305
306 TranslateAnimation outAnimation = new TranslateAnimation(
307 Animation.RELATIVE_TO_SELF, outFromXValue,
308 Animation.RELATIVE_TO_SELF, outToXValue,
309 Animation.ABSOLUTE, 0.0f,
310 Animation.ABSOLUTE, 0.0f);
Michael Chan23f400c2009-08-14 13:03:39 -0700311
The Android Open Source Project7abd8562009-03-05 14:34:37 -0800312 // Reduce the animation duration based on how far we have already swiped.
313 long duration = (long) (ANIMATION_DURATION * (1.0f - progress));
314 inAnimation.setDuration(duration);
315 outAnimation.setDuration(duration);
316 mViewSwitcher.setInAnimation(inAnimation);
317 mViewSwitcher.setOutAnimation(outAnimation);
Michael Chan23f400c2009-08-14 13:03:39 -0700318
The Android Open Source Project146de362009-03-03 19:32:18 -0800319 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
320 view.cleanup();
321 mViewSwitcher.showNext();
322 view = (CalendarView) mViewSwitcher.getCurrentView();
323 view.requestFocus();
324 view.reloadEvents();
325 return view;
326 }
327
328 @Override
329 public boolean onPrepareOptionsMenu(Menu menu) {
330 MenuHelper.onPrepareOptionsMenu(this, menu);
331 return super.onPrepareOptionsMenu(menu);
332 }
333
334 @Override
335 public boolean onCreateOptionsMenu(Menu menu) {
336 if (! MenuHelper.onCreateOptionsMenu(menu)) {
337 return false;
338 }
339 return super.onCreateOptionsMenu(menu);
340 }
341
342 @Override
343 public boolean onOptionsItemSelected(MenuItem item) {
344 if (MenuHelper.onOptionsItemSelected(this, item, this)) {
345 return true;
346 }
347 return super.onOptionsItemSelected(item);
348 }
349
350 @Override
351 public boolean onTouchEvent(MotionEvent ev) {
352 if (mGestureDetector.onTouchEvent(ev)) {
353 return true;
354 }
355 return super.onTouchEvent(ev);
356 }
357
358 class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
359 @Override
360 public boolean onSingleTapUp(MotionEvent ev) {
361 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
362 view.doSingleTapUp(ev);
363 return true;
364 }
365
366 @Override
The Android Open Source Project146de362009-03-03 19:32:18 -0800367 public void onLongPress(MotionEvent ev) {
368 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
369 view.doLongPress(ev);
370 }
371
372 @Override
373 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
374 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
375 view.doScroll(e1, e2, distanceX, distanceY);
376 return true;
377 }
378
379 @Override
380 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
381 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
382 view.doFling(e1, e2, velocityX, velocityY);
383 return true;
384 }
385
386 @Override
387 public boolean onDown(MotionEvent ev) {
388 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
389 view.doDown(ev);
390 return true;
391 }
392 }
393}
394