Home | History | Annotate | Download | only in calendar
      1 /*
      2  * Copyright (C) 2010 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 com.android.calendar.CalendarController.EventInfo;
     20 import com.android.calendar.CalendarController.EventType;
     21 
     22 import android.app.Fragment;
     23 import android.content.Context;
     24 import android.os.Bundle;
     25 import android.text.format.Time;
     26 import android.view.LayoutInflater;
     27 import android.view.View;
     28 import android.view.ViewGroup;
     29 import android.view.ViewGroup.LayoutParams;
     30 import android.view.animation.Animation;
     31 import android.view.animation.AnimationUtils;
     32 import android.widget.ProgressBar;
     33 import android.widget.ViewSwitcher;
     34 import android.widget.ViewSwitcher.ViewFactory;
     35 
     36 /**
     37  * This is the base class for Day and Week Activities.
     38  */
     39 public class DayFragment extends Fragment implements CalendarController.EventHandler, ViewFactory {
     40     /**
     41      * The view id used for all the views we create. It's OK to have all child
     42      * views have the same ID. This ID is used to pick which view receives
     43      * focus when a view hierarchy is saved / restore
     44      */
     45     private static final int VIEW_ID = 1;
     46 
     47     protected static final String BUNDLE_KEY_RESTORE_TIME = "key_restore_time";
     48 
     49     protected ProgressBar mProgressBar;
     50     protected ViewSwitcher mViewSwitcher;
     51     protected Animation mInAnimationForward;
     52     protected Animation mOutAnimationForward;
     53     protected Animation mInAnimationBackward;
     54     protected Animation mOutAnimationBackward;
     55     EventLoader mEventLoader;
     56 
     57     Time mSelectedDay = new Time();
     58 
     59     private final Runnable mTZUpdater = new Runnable() {
     60         @Override
     61         public void run() {
     62             if (!DayFragment.this.isAdded()) {
     63                 return;
     64             }
     65             String tz = Utils.getTimeZone(getActivity(), mTZUpdater);
     66             mSelectedDay.timezone = tz;
     67             mSelectedDay.normalize(true);
     68         }
     69     };
     70 
     71     private int mNumDays;
     72 
     73     public DayFragment() {
     74         mSelectedDay.setToNow();
     75     }
     76 
     77     public DayFragment(long timeMillis, int numOfDays) {
     78         mNumDays = numOfDays;
     79         if (timeMillis == 0) {
     80             mSelectedDay.setToNow();
     81         } else {
     82             mSelectedDay.set(timeMillis);
     83         }
     84     }
     85 
     86     @Override
     87     public void onCreate(Bundle icicle) {
     88         super.onCreate(icicle);
     89 
     90         Context context = getActivity();
     91 
     92         mInAnimationForward = AnimationUtils.loadAnimation(context, R.anim.slide_left_in);
     93         mOutAnimationForward = AnimationUtils.loadAnimation(context, R.anim.slide_left_out);
     94         mInAnimationBackward = AnimationUtils.loadAnimation(context, R.anim.slide_right_in);
     95         mOutAnimationBackward = AnimationUtils.loadAnimation(context, R.anim.slide_right_out);
     96 
     97         mEventLoader = new EventLoader(context);
     98     }
     99 
    100     @Override
    101     public View onCreateView(LayoutInflater inflater, ViewGroup container,
    102             Bundle savedInstanceState) {
    103         View v = inflater.inflate(R.layout.day_activity, null);
    104 
    105         mViewSwitcher = (ViewSwitcher) v.findViewById(R.id.switcher);
    106         mViewSwitcher.setFactory(this);
    107         mViewSwitcher.getCurrentView().requestFocus();
    108         ((DayView) mViewSwitcher.getCurrentView()).updateTitle();
    109 
    110         return v;
    111     }
    112 
    113     public View makeView() {
    114         mTZUpdater.run();
    115         DayView view = new DayView(getActivity(), CalendarController
    116                 .getInstance(getActivity()), mViewSwitcher, mEventLoader, mNumDays);
    117         view.setId(VIEW_ID);
    118         view.setLayoutParams(new ViewSwitcher.LayoutParams(
    119                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    120         view.setSelected(mSelectedDay, false, false);
    121         return view;
    122     }
    123 
    124     @Override
    125     public void onResume() {
    126         super.onResume();
    127         mEventLoader.startBackgroundThread();
    128         mTZUpdater.run();
    129         eventsChanged();
    130         DayView view = (DayView) mViewSwitcher.getCurrentView();
    131         view.handleOnResume();
    132         view.restartCurrentTimeUpdates();
    133 
    134         view = (DayView) mViewSwitcher.getNextView();
    135         view.handleOnResume();
    136         view.restartCurrentTimeUpdates();
    137     }
    138 
    139     @Override
    140     public void onSaveInstanceState(Bundle outState) {
    141         super.onSaveInstanceState(outState);
    142 
    143         long time = getSelectedTimeInMillis();
    144         if (time != -1) {
    145             outState.putLong(BUNDLE_KEY_RESTORE_TIME, time);
    146         }
    147     }
    148 
    149     @Override
    150     public void onPause() {
    151         super.onPause();
    152         DayView view = (DayView) mViewSwitcher.getCurrentView();
    153         view.cleanup();
    154         view = (DayView) mViewSwitcher.getNextView();
    155         view.cleanup();
    156         mEventLoader.stopBackgroundThread();
    157 
    158         // Stop events cross-fade animation
    159         view.stopEventsAnimation();
    160         ((DayView) mViewSwitcher.getNextView()).stopEventsAnimation();
    161     }
    162 
    163     void startProgressSpinner() {
    164         // start the progress spinner
    165         mProgressBar.setVisibility(View.VISIBLE);
    166     }
    167 
    168     void stopProgressSpinner() {
    169         // stop the progress spinner
    170         mProgressBar.setVisibility(View.GONE);
    171     }
    172 
    173     private void goTo(Time goToTime, boolean ignoreTime, boolean animateToday) {
    174         if (mViewSwitcher == null) {
    175             // The view hasn't been set yet. Just save the time and use it later.
    176             mSelectedDay.set(goToTime);
    177             return;
    178         }
    179 
    180         DayView currentView = (DayView) mViewSwitcher.getCurrentView();
    181 
    182         // How does goTo time compared to what's already displaying?
    183         int diff = currentView.compareToVisibleTimeRange(goToTime);
    184 
    185         if (diff == 0) {
    186             // In visible range. No need to switch view
    187             currentView.setSelected(goToTime, ignoreTime, animateToday);
    188         } else {
    189             // Figure out which way to animate
    190             if (diff > 0) {
    191                 mViewSwitcher.setInAnimation(mInAnimationForward);
    192                 mViewSwitcher.setOutAnimation(mOutAnimationForward);
    193             } else {
    194                 mViewSwitcher.setInAnimation(mInAnimationBackward);
    195                 mViewSwitcher.setOutAnimation(mOutAnimationBackward);
    196             }
    197 
    198             DayView next = (DayView) mViewSwitcher.getNextView();
    199             if (ignoreTime) {
    200                 next.setFirstVisibleHour(currentView.getFirstVisibleHour());
    201             }
    202 
    203             next.setSelected(goToTime, ignoreTime, animateToday);
    204             next.reloadEvents();
    205             mViewSwitcher.showNext();
    206             next.requestFocus();
    207             next.updateTitle();
    208             next.restartCurrentTimeUpdates();
    209         }
    210     }
    211 
    212     /**
    213      * Returns the selected time in milliseconds. The milliseconds are measured
    214      * in UTC milliseconds from the epoch and uniquely specifies any selectable
    215      * time.
    216      *
    217      * @return the selected time in milliseconds
    218      */
    219     public long getSelectedTimeInMillis() {
    220         if (mViewSwitcher == null) {
    221             return -1;
    222         }
    223         DayView view = (DayView) mViewSwitcher.getCurrentView();
    224         if (view == null) {
    225             return -1;
    226         }
    227         return view.getSelectedTimeInMillis();
    228     }
    229 
    230     public void eventsChanged() {
    231         if (mViewSwitcher == null) {
    232             return;
    233         }
    234         DayView view = (DayView) mViewSwitcher.getCurrentView();
    235         view.clearCachedEvents();
    236         view.reloadEvents();
    237 
    238         view = (DayView) mViewSwitcher.getNextView();
    239         view.clearCachedEvents();
    240     }
    241 
    242     Event getSelectedEvent() {
    243         DayView view = (DayView) mViewSwitcher.getCurrentView();
    244         return view.getSelectedEvent();
    245     }
    246 
    247     boolean isEventSelected() {
    248         DayView view = (DayView) mViewSwitcher.getCurrentView();
    249         return view.isEventSelected();
    250     }
    251 
    252     Event getNewEvent() {
    253         DayView view = (DayView) mViewSwitcher.getCurrentView();
    254         return view.getNewEvent();
    255     }
    256 
    257     public DayView getNextView() {
    258         return (DayView) mViewSwitcher.getNextView();
    259     }
    260 
    261     public long getSupportedEventTypes() {
    262         return EventType.GO_TO | EventType.EVENTS_CHANGED;
    263     }
    264 
    265     public void handleEvent(EventInfo msg) {
    266         if (msg.eventType == EventType.GO_TO) {
    267 // TODO support a range of time
    268 // TODO support event_id
    269 // TODO support select message
    270             goTo(msg.selectedTime, (msg.extraLong & CalendarController.EXTRA_GOTO_DATE) != 0,
    271                     (msg.extraLong & CalendarController.EXTRA_GOTO_TODAY) != 0);
    272         } else if (msg.eventType == EventType.EVENTS_CHANGED) {
    273             eventsChanged();
    274         }
    275     }
    276 }
    277