2 * Copyright (C) 2007 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.calendar;
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;
41 import dalvik.system.VMRuntime;
44 * This is the base class for Day and Week Activities.
46 public class CalendarActivity extends Activity implements Navigator {
48 private static final long INITIAL_HEAP_SIZE = 4*1024*1024;
49 private static final long ANIMATION_DURATION = 400;
51 protected static final String BUNDLE_KEY_RESTORE_TIME = "key_restore_time";
53 private ContentResolver mContentResolver;
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;
63 Time mSelectedDay = new Time();
65 /* package */ GestureDetector mGestureDetector;
68 * Listens for intent broadcasts
70 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
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)) {
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())
87 public boolean deliverSelfNotifications() {
92 public void onChange(boolean selfChange) {
98 protected void onCreate(Bundle icicle) {
99 super.onCreate(icicle);
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);
105 setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);
106 mContentResolver = getContentResolver();
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);
113 mGestureDetector = new GestureDetector(this, new CalendarGestureListener());
114 mEventLoader = new EventLoader(this);
118 protected void onRestoreInstanceState(Bundle savedInstanceState) {
119 super.onRestoreInstanceState(savedInstanceState);
121 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
122 Time time = new Time();
123 time.set(savedInstanceState.getLong(BUNDLE_KEY_RESTORE_TIME));
124 view.setSelectedDay(time);
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);
138 protected void onResume() {
140 mEventLoader.startBackgroundThread();
143 // Register for Intent broadcasts
144 IntentFilter filter = new IntentFilter();
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);
151 mContentResolver.registerContentObserver(Calendar.Events.CONTENT_URI,
156 protected void onSaveInstanceState(Bundle outState) {
157 super.onSaveInstanceState(outState);
159 outState.putLong(BUNDLE_KEY_RESTORE_TIME, getSelectedTimeInMillis());
163 protected void onPause() {
165 mContentResolver.unregisterContentObserver(mObserver);
166 unregisterReceiver(mIntentReceiver);
168 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
170 view = (CalendarView) mViewSwitcher.getNextView();
172 mEventLoader.stopBackgroundThread();
175 void startProgressSpinner() {
176 // start the progress spinner
177 mProgressBar.setVisibility(View.VISIBLE);
180 void stopProgressSpinner() {
181 // stop the progress spinner
182 mProgressBar.setVisibility(View.GONE);
185 /* Navigator interface methods */
186 public void goTo(Time time) {
187 CalendarView current = (CalendarView) mViewSwitcher.getCurrentView();
189 if (current.getSelectedTime().before(time)) {
190 mViewSwitcher.setInAnimation(mInAnimationForward);
191 mViewSwitcher.setOutAnimation(mOutAnimationForward);
193 mViewSwitcher.setInAnimation(mInAnimationBackward);
194 mViewSwitcher.setOutAnimation(mOutAnimationBackward);
197 CalendarView next = (CalendarView) mViewSwitcher.getNextView();
198 next.setSelectedDay(time);
200 mViewSwitcher.showNext();
205 * Returns the selected time in milliseconds. The milliseconds are measured
206 * in UTC milliseconds from the epoch and uniquely specifies any selectable
209 * @return the selected time in milliseconds
211 public long getSelectedTimeInMillis() {
212 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
213 return view.getSelectedTimeInMillis();
216 public long getSelectedTime() {
217 return getSelectedTimeInMillis();
220 public void goToToday() {
221 mSelectedDay.set(System.currentTimeMillis());
222 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
223 view.setSelectedDay(mSelectedDay);
227 public boolean getAllDay() {
228 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
229 return view.mSelectionAllDay;
232 void eventsChanged() {
233 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
234 view.clearCachedEvents();
238 Event getSelectedEvent() {
239 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
240 return view.getSelectedEvent();
243 boolean isEventSelected() {
244 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
245 return view.isEventSelected();
248 Event getNewEvent() {
249 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
250 return view.getNewEvent();
253 public CalendarView getNextView() {
254 return (CalendarView) mViewSwitcher.getNextView();
257 public View switchViews(boolean forward, float xOffSet, float width) {
258 float progress = Math.abs(xOffSet) / width;
259 if (progress > 1.0f) {
263 float inFromXValue, inToXValue;
264 float outFromXValue, outToXValue;
266 inFromXValue = 1.0f - progress;
268 outFromXValue = -progress;
271 inFromXValue = progress - 1.0f;
273 outFromXValue = progress;
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);
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);
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);
298 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
300 mViewSwitcher.showNext();
301 view = (CalendarView) mViewSwitcher.getCurrentView();
308 public boolean onPrepareOptionsMenu(Menu menu) {
309 MenuHelper.onPrepareOptionsMenu(this, menu);
310 return super.onPrepareOptionsMenu(menu);
314 public boolean onCreateOptionsMenu(Menu menu) {
315 if (! MenuHelper.onCreateOptionsMenu(menu)) {
318 return super.onCreateOptionsMenu(menu);
322 public boolean onOptionsItemSelected(MenuItem item) {
323 if (MenuHelper.onOptionsItemSelected(this, item, this)) {
326 return super.onOptionsItemSelected(item);
330 public boolean onTouchEvent(MotionEvent ev) {
331 if (mGestureDetector.onTouchEvent(ev)) {
334 return super.onTouchEvent(ev);
337 class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
339 public boolean onSingleTapUp(MotionEvent ev) {
340 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
341 view.doSingleTapUp(ev);
346 public void onLongPress(MotionEvent ev) {
347 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();
348 view.doLongPress(ev);
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);
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);
366 public boolean onDown(MotionEvent ev) {
367 CalendarView view = (CalendarView) mViewSwitcher.getCurrentView();