Home | History | Annotate | Download | only in calendar
      1 /*
      2  * Copyright (C) 2006 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 static android.provider.Calendar.EVENT_BEGIN_TIME;
     20 import dalvik.system.VMRuntime;
     21 
     22 import android.app.Activity;
     23 import android.content.BroadcastReceiver;
     24 import android.content.ContentResolver;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.IntentFilter;
     28 import android.content.SharedPreferences;
     29 import android.database.ContentObserver;
     30 import android.os.Bundle;
     31 import android.os.Handler;
     32 import android.preference.PreferenceManager;
     33 import android.provider.Calendar.Events;
     34 import android.text.format.DateUtils;
     35 import android.text.format.Time;
     36 import android.view.Menu;
     37 import android.view.MenuItem;
     38 import android.view.View;
     39 import android.view.animation.Animation;
     40 import android.view.animation.AnimationUtils;
     41 import android.view.animation.Animation.AnimationListener;
     42 import android.widget.ProgressBar;
     43 import android.widget.TextView;
     44 import android.widget.ViewSwitcher;
     45 import android.widget.Gallery.LayoutParams;
     46 
     47 import java.util.Calendar;
     48 
     49 public class MonthActivity extends Activity implements ViewSwitcher.ViewFactory,
     50         Navigator, AnimationListener {
     51     private static final int INITIAL_HEAP_SIZE = 4 * 1024 * 1024;
     52     private Animation mInAnimationPast;
     53     private Animation mInAnimationFuture;
     54     private Animation mOutAnimationPast;
     55     private Animation mOutAnimationFuture;
     56     private ViewSwitcher mSwitcher;
     57     private Time mTime;
     58 
     59     private ContentResolver mContentResolver;
     60     EventLoader mEventLoader;
     61     private int mStartDay;
     62 
     63     private ProgressBar mProgressBar;
     64 
     65     private static final int DAY_OF_WEEK_LABEL_IDS[] = {
     66         R.id.day0, R.id.day1, R.id.day2, R.id.day3, R.id.day4, R.id.day5, R.id.day6
     67     };
     68     private static final int DAY_OF_WEEK_KINDS[] = {
     69         Calendar.SUNDAY, Calendar.MONDAY, Calendar.TUESDAY, Calendar.WEDNESDAY,
     70         Calendar.THURSDAY, Calendar.FRIDAY, Calendar.SATURDAY
     71     };
     72 
     73     protected void startProgressSpinner() {
     74         // start the progress spinner
     75         mProgressBar.setVisibility(View.VISIBLE);
     76     }
     77 
     78     protected void stopProgressSpinner() {
     79         // stop the progress spinner
     80         mProgressBar.setVisibility(View.GONE);
     81     }
     82 
     83     /* ViewSwitcher.ViewFactory interface methods */
     84     public View makeView() {
     85         MonthView mv = new MonthView(this, this);
     86         mv.setLayoutParams(new ViewSwitcher.LayoutParams(
     87                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
     88         mv.setSelectedTime(mTime);
     89         return mv;
     90     }
     91 
     92     /* Navigator interface methods */
     93     public void goTo(Time time, boolean animate) {
     94         TextView title = (TextView) findViewById(R.id.title);
     95         title.setText(Utils.formatMonthYear(this, time));
     96 
     97         MonthView current = (MonthView) mSwitcher.getCurrentView();
     98         current.dismissPopup();
     99 
    100         Time currentTime = current.getTime();
    101 
    102         // Compute a month number that is monotonically increasing for any
    103         // two adjacent months.
    104         // This is faster than calling getSelectedTime() because we avoid
    105         // a call to Time#normalize().
    106         if (animate) {
    107             int currentMonth = currentTime.month + currentTime.year * 12;
    108             int nextMonth = time.month + time.year * 12;
    109             if (nextMonth < currentMonth) {
    110                 mSwitcher.setInAnimation(mInAnimationPast);
    111                 mSwitcher.setOutAnimation(mOutAnimationPast);
    112             } else {
    113                 mSwitcher.setInAnimation(mInAnimationFuture);
    114                 mSwitcher.setOutAnimation(mOutAnimationFuture);
    115             }
    116         }
    117 
    118         MonthView next = (MonthView) mSwitcher.getNextView();
    119         next.setSelectionMode(current.getSelectionMode());
    120         next.setSelectedTime(time);
    121         next.reloadEvents();
    122         next.animationStarted();
    123         mSwitcher.showNext();
    124         next.requestFocus();
    125         mTime = time;
    126     }
    127 
    128     public void goToToday() {
    129         Time now = new Time();
    130         now.set(System.currentTimeMillis());
    131         now.minute = 0;
    132         now.second = 0;
    133         now.normalize(false);
    134 
    135         TextView title = (TextView) findViewById(R.id.title);
    136         title.setText(Utils.formatMonthYear(this, now));
    137         mTime = now;
    138 
    139         MonthView view = (MonthView) mSwitcher.getCurrentView();
    140         view.setSelectedTime(now);
    141         view.reloadEvents();
    142     }
    143 
    144     public long getSelectedTime() {
    145         MonthView mv = (MonthView) mSwitcher.getCurrentView();
    146         return mv.getSelectedTimeInMillis();
    147     }
    148 
    149     public boolean getAllDay() {
    150         return false;
    151     }
    152 
    153     int getStartDay() {
    154         return mStartDay;
    155     }
    156 
    157     void eventsChanged() {
    158         MonthView view = (MonthView) mSwitcher.getCurrentView();
    159         view.reloadEvents();
    160     }
    161 
    162     /**
    163      * Listens for intent broadcasts
    164      */
    165     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
    166         @Override
    167         public void onReceive(Context context, Intent intent) {
    168             String action = intent.getAction();
    169             if (action.equals(Intent.ACTION_TIME_CHANGED)
    170                     || action.equals(Intent.ACTION_DATE_CHANGED)
    171                     || action.equals(Intent.ACTION_TIMEZONE_CHANGED)) {
    172                 eventsChanged();
    173             }
    174         }
    175     };
    176 
    177     // Create an observer so that we can update the views whenever a
    178     // Calendar event changes.
    179     private ContentObserver mObserver = new ContentObserver(new Handler())
    180     {
    181         @Override
    182         public boolean deliverSelfNotifications() {
    183             return true;
    184         }
    185 
    186         @Override
    187         public void onChange(boolean selfChange) {
    188             eventsChanged();
    189         }
    190     };
    191 
    192     public void onAnimationStart(Animation animation) {
    193     }
    194 
    195     // Notifies the MonthView when an animation has finished.
    196     public void onAnimationEnd(Animation animation) {
    197         MonthView monthView = (MonthView) mSwitcher.getCurrentView();
    198         monthView.animationFinished();
    199     }
    200 
    201     public void onAnimationRepeat(Animation animation) {
    202     }
    203 
    204     @Override
    205     protected void onCreate(Bundle icicle) {
    206         super.onCreate(icicle);
    207 
    208         // Eliminate extra GCs during startup by setting the initial heap size to 4MB.
    209         // TODO: We should restore the old heap size once the activity reaches the idle state
    210         VMRuntime.getRuntime().setMinimumHeapSize(INITIAL_HEAP_SIZE);
    211 
    212         setContentView(R.layout.month_activity);
    213         mContentResolver = getContentResolver();
    214 
    215         long time;
    216         if (icicle != null) {
    217             time = icicle.getLong(EVENT_BEGIN_TIME);
    218         } else {
    219             time = Utils.timeFromIntentInMillis(getIntent());
    220         }
    221 
    222         mTime = new Time();
    223         mTime.set(time);
    224         mTime.normalize(true);
    225 
    226         // Get first day of week based on locale and populate the day headers
    227         mStartDay = Calendar.getInstance().getFirstDayOfWeek();
    228         int diff = mStartDay - Calendar.SUNDAY - 1;
    229         final int startDay = Utils.getFirstDayOfWeek();
    230         final int sundayColor = getResources().getColor(R.color.sunday_text_color);
    231         final int saturdayColor = getResources().getColor(R.color.saturday_text_color);
    232 
    233         for (int day = 0; day < 7; day++) {
    234             final String dayString = DateUtils.getDayOfWeekString(
    235                     (DAY_OF_WEEK_KINDS[day] + diff) % 7 + 1, DateUtils.LENGTH_MEDIUM);
    236             final TextView label = (TextView) findViewById(DAY_OF_WEEK_LABEL_IDS[day]);
    237             label.setText(dayString);
    238             if (Utils.isSunday(day, startDay)) {
    239                 label.setTextColor(sundayColor);
    240             } else if (Utils.isSaturday(day, startDay)) {
    241                 label.setTextColor(saturdayColor);
    242             }
    243         }
    244 
    245         // Set the initial title
    246         TextView title = (TextView) findViewById(R.id.title);
    247         title.setText(Utils.formatMonthYear(this, mTime));
    248 
    249         mEventLoader = new EventLoader(this);
    250         mProgressBar = (ProgressBar) findViewById(R.id.progress_circular);
    251 
    252         mSwitcher = (ViewSwitcher) findViewById(R.id.switcher);
    253         mSwitcher.setFactory(this);
    254         mSwitcher.getCurrentView().requestFocus();
    255 
    256         mInAnimationPast = AnimationUtils.loadAnimation(this, R.anim.slide_down_in);
    257         mOutAnimationPast = AnimationUtils.loadAnimation(this, R.anim.slide_down_out);
    258         mInAnimationFuture = AnimationUtils.loadAnimation(this, R.anim.slide_up_in);
    259         mOutAnimationFuture = AnimationUtils.loadAnimation(this, R.anim.slide_up_out);
    260 
    261         mInAnimationPast.setAnimationListener(this);
    262         mInAnimationFuture.setAnimationListener(this);
    263     }
    264 
    265     @Override
    266     protected void onNewIntent(Intent intent) {
    267         long timeMillis = Utils.timeFromIntentInMillis(intent);
    268         if (timeMillis > 0) {
    269             Time time = new Time();
    270             time.set(timeMillis);
    271             goTo(time, false);
    272         }
    273     }
    274 
    275     @Override
    276     protected void onPause() {
    277         super.onPause();
    278         if (isFinishing()) {
    279             mEventLoader.stopBackgroundThread();
    280         }
    281         mContentResolver.unregisterContentObserver(mObserver);
    282         unregisterReceiver(mIntentReceiver);
    283 
    284         MonthView view = (MonthView) mSwitcher.getCurrentView();
    285         view.dismissPopup();
    286         view = (MonthView) mSwitcher.getNextView();
    287         view.dismissPopup();
    288         mEventLoader.stopBackgroundThread();
    289 
    290         // Record Month View as the (new) start view
    291         Utils.setDefaultView(this, CalendarApplication.MONTH_VIEW_ID);
    292     }
    293 
    294     @Override
    295     protected void onResume() {
    296         super.onResume();
    297         mEventLoader.startBackgroundThread();
    298         eventsChanged();
    299 
    300         MonthView view1 = (MonthView) mSwitcher.getCurrentView();
    301         MonthView view2 = (MonthView) mSwitcher.getNextView();
    302         SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(this);
    303         String str = prefs.getString(CalendarPreferenceActivity.KEY_DETAILED_VIEW,
    304                 CalendarPreferenceActivity.DEFAULT_DETAILED_VIEW);
    305         view1.setDetailedView(str);
    306         view2.setDetailedView(str);
    307 
    308         // Register for Intent broadcasts
    309         IntentFilter filter = new IntentFilter();
    310 
    311         filter.addAction(Intent.ACTION_TIME_CHANGED);
    312         filter.addAction(Intent.ACTION_DATE_CHANGED);
    313         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
    314         registerReceiver(mIntentReceiver, filter);
    315 
    316         mContentResolver.registerContentObserver(Events.CONTENT_URI,
    317                 true, mObserver);
    318     }
    319 
    320     @Override
    321     protected void onSaveInstanceState(Bundle outState) {
    322         super.onSaveInstanceState(outState);
    323         outState.putLong(EVENT_BEGIN_TIME, mTime.toMillis(true));
    324     }
    325 
    326     @Override
    327     public boolean onPrepareOptionsMenu(Menu menu) {
    328         MenuHelper.onPrepareOptionsMenu(this, menu);
    329         return super.onPrepareOptionsMenu(menu);
    330     }
    331 
    332     @Override
    333     public boolean onCreateOptionsMenu(Menu menu) {
    334         MenuHelper.onCreateOptionsMenu(menu);
    335         return super.onCreateOptionsMenu(menu);
    336     }
    337 
    338     @Override
    339     public boolean onOptionsItemSelected(MenuItem item) {
    340         MenuHelper.onOptionsItemSelected(this, item, this);
    341         return super.onOptionsItemSelected(item);
    342     }
    343 }
    344