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 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 
    159     void startProgressSpinner() {
    160         // start the progress spinner
    161         mProgressBar.setVisibility(View.VISIBLE);
    162     }
    163 
    164     void stopProgressSpinner() {
    165         // stop the progress spinner
    166         mProgressBar.setVisibility(View.GONE);
    167     }
    168 
    169     private void goTo(Time goToTime, boolean ignoreTime, boolean animateToday) {
    170         if (mViewSwitcher == null) {
    171             // The view hasn't been set yet. Just save the time and use it later.
    172             mSelectedDay.set(goToTime);
    173             return;
    174         }
    175 
    176         DayView currentView = (DayView) mViewSwitcher.getCurrentView();
    177 
    178         // How does goTo time compared to what's already displaying?
    179         int diff = currentView.compareToVisibleTimeRange(goToTime);
    180 
    181         if (diff == 0) {
    182             // In visible range. No need to switch view
    183             currentView.setSelected(goToTime, ignoreTime, animateToday);
    184         } else {
    185             // Figure out which way to animate
    186             if (diff > 0) {
    187                 mViewSwitcher.setInAnimation(mInAnimationForward);
    188                 mViewSwitcher.setOutAnimation(mOutAnimationForward);
    189             } else {
    190                 mViewSwitcher.setInAnimation(mInAnimationBackward);
    191                 mViewSwitcher.setOutAnimation(mOutAnimationBackward);
    192             }
    193 
    194             DayView next = (DayView) mViewSwitcher.getNextView();
    195             if (ignoreTime) {
    196                 next.setFirstVisibleHour(currentView.getFirstVisibleHour());
    197             }
    198 
    199             next.setSelected(goToTime, ignoreTime, animateToday);
    200             next.reloadEvents();
    201             mViewSwitcher.showNext();
    202             next.requestFocus();
    203             next.updateTitle();
    204             next.restartCurrentTimeUpdates();
    205         }
    206     }
    207 
    208     /**
    209      * Returns the selected time in milliseconds. The milliseconds are measured
    210      * in UTC milliseconds from the epoch and uniquely specifies any selectable
    211      * time.
    212      *
    213      * @return the selected time in milliseconds
    214      */
    215     public long getSelectedTimeInMillis() {
    216         if (mViewSwitcher == null) {
    217             return -1;
    218         }
    219         DayView view = (DayView) mViewSwitcher.getCurrentView();
    220         if (view == null) {
    221             return -1;
    222         }
    223         return view.getSelectedTimeInMillis();
    224     }
    225 
    226     public void eventsChanged() {
    227         if (mViewSwitcher == null) {
    228             return;
    229         }
    230         DayView view = (DayView) mViewSwitcher.getCurrentView();
    231         view.clearCachedEvents();
    232         view.reloadEvents();
    233 
    234         view = (DayView) mViewSwitcher.getNextView();
    235         view.clearCachedEvents();
    236     }
    237 
    238     Event getSelectedEvent() {
    239         DayView view = (DayView) mViewSwitcher.getCurrentView();
    240         return view.getSelectedEvent();
    241     }
    242 
    243     boolean isEventSelected() {
    244         DayView view = (DayView) mViewSwitcher.getCurrentView();
    245         return view.isEventSelected();
    246     }
    247 
    248     Event getNewEvent() {
    249         DayView view = (DayView) mViewSwitcher.getCurrentView();
    250         return view.getNewEvent();
    251     }
    252 
    253     public DayView getNextView() {
    254         return (DayView) mViewSwitcher.getNextView();
    255     }
    256 
    257     public long getSupportedEventTypes() {
    258         return EventType.GO_TO | EventType.EVENTS_CHANGED;
    259     }
    260 
    261     public void handleEvent(EventInfo msg) {
    262         if (msg.eventType == EventType.GO_TO) {
    263 // TODO support a range of time
    264 // TODO support event_id
    265 // TODO support select message
    266             goTo(msg.selectedTime, (msg.extraLong & CalendarController.EXTRA_GOTO_DATE) != 0,
    267                     (msg.extraLong & CalendarController.EXTRA_GOTO_TODAY) != 0);
    268         } else if (msg.eventType == EventType.EVENTS_CHANGED) {
    269             eventsChanged();
    270         }
    271     }
    272 }
    273