DayFragment.java revision a60657d3f50d8943f27b9e649953690d797cc7f9
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
17package com.android.calendar;
18
19import com.android.calendar.CalendarController.EventInfo;
20import com.android.calendar.CalendarController.EventType;
21
22import android.app.Fragment;
23import android.content.Context;
24import android.os.Bundle;
25import android.text.format.Time;
26import android.view.LayoutInflater;
27import android.view.View;
28import android.view.ViewGroup;
29import android.view.ViewGroup.LayoutParams;
30import android.view.animation.Animation;
31import android.view.animation.AnimationUtils;
32import android.widget.ProgressBar;
33import android.widget.ViewSwitcher;
34import android.widget.ViewSwitcher.ViewFactory;
35
36/**
37 * This is the base class for Day and Week Activities.
38 */
39public 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);
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        // Register for Intent broadcasts
139//        IntentFilter filter = new IntentFilter();
140//
141//        filter.addAction(Intent.ACTION_TIME_CHANGED);
142//        filter.addAction(Intent.ACTION_DATE_CHANGED);
143//        filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
144//        registerReceiver(mIntentReceiver, filter);
145
146//        mContentResolver.registerContentObserver(Calendar.Events.CONTENT_URI,
147//                true, mObserver);
148    }
149
150    @Override
151    public void onSaveInstanceState(Bundle outState) {
152        super.onSaveInstanceState(outState);
153
154        long time = getSelectedTimeInMillis();
155        if (time != -1) {
156            outState.putLong(BUNDLE_KEY_RESTORE_TIME, time);
157        }
158    }
159
160    @Override
161    public void onPause() {
162        super.onPause();
163//        mContentResolver.unregisterContentObserver(mObserver);
164//        unregisterReceiver(mIntentReceiver);
165
166        DayView view = (DayView) mViewSwitcher.getCurrentView();
167        view.cleanup();
168        view = (DayView) mViewSwitcher.getNextView();
169        view.cleanup();
170        mEventLoader.stopBackgroundThread();
171    }
172
173    void startProgressSpinner() {
174        // start the progress spinner
175        mProgressBar.setVisibility(View.VISIBLE);
176    }
177
178    void stopProgressSpinner() {
179        // stop the progress spinner
180        mProgressBar.setVisibility(View.GONE);
181    }
182
183    private void goTo(Time goToTime, boolean ignoreTime) {
184        if (mViewSwitcher == null) {
185            // The view hasn't been set yet. Just save the time and use it later.
186            mSelectedDay.set(goToTime);
187            return;
188        }
189
190        DayView currentView = (DayView) mViewSwitcher.getCurrentView();
191
192        // How does goTo time compared to what's already displaying?
193        int diff = currentView.compareToVisibleTimeRange(goToTime);
194
195        if (diff == 0) {
196            // In visible range. No need to switch view
197            currentView.setSelected(goToTime, ignoreTime);
198        } else {
199            // Figure out which way to animate
200            if (diff > 0) {
201                mViewSwitcher.setInAnimation(mInAnimationForward);
202                mViewSwitcher.setOutAnimation(mOutAnimationForward);
203            } else {
204                mViewSwitcher.setInAnimation(mInAnimationBackward);
205                mViewSwitcher.setOutAnimation(mOutAnimationBackward);
206            }
207
208            DayView next = (DayView) mViewSwitcher.getNextView();
209            if (ignoreTime) {
210                next.setFirstVisibleHour(currentView.getFirstVisibleHour());
211            }
212
213            next.setSelected(goToTime, ignoreTime);
214            next.reloadEvents();
215            mViewSwitcher.showNext();
216            next.requestFocus();
217            next.updateTitle();
218        }
219    }
220
221    /**
222     * Returns the selected time in milliseconds. The milliseconds are measured
223     * in UTC milliseconds from the epoch and uniquely specifies any selectable
224     * time.
225     *
226     * @return the selected time in milliseconds
227     */
228    public long getSelectedTimeInMillis() {
229        if (mViewSwitcher == null) {
230            return -1;
231        }
232        DayView view = (DayView) mViewSwitcher.getCurrentView();
233        if (view == null) {
234            return -1;
235        }
236        return view.getSelectedTimeInMillis();
237    }
238
239    public void eventsChanged() {
240        if (mViewSwitcher == null) {
241            return;
242        }
243        DayView view = (DayView) mViewSwitcher.getCurrentView();
244        view.clearCachedEvents();
245        view.reloadEvents();
246
247        view = (DayView) mViewSwitcher.getNextView();
248        view.clearCachedEvents();
249    }
250
251    Event getSelectedEvent() {
252        DayView view = (DayView) mViewSwitcher.getCurrentView();
253        return view.getSelectedEvent();
254    }
255
256    boolean isEventSelected() {
257        DayView view = (DayView) mViewSwitcher.getCurrentView();
258        return view.isEventSelected();
259    }
260
261    Event getNewEvent() {
262        DayView view = (DayView) mViewSwitcher.getCurrentView();
263        return view.getNewEvent();
264    }
265
266    public DayView getNextView() {
267        return (DayView) mViewSwitcher.getNextView();
268    }
269
270    public long getSupportedEventTypes() {
271        return EventType.GO_TO | EventType.EVENTS_CHANGED;
272    }
273
274    public void handleEvent(EventInfo msg) {
275        if (msg.eventType == EventType.GO_TO) {
276// TODO support a range of time
277// TODO support event_id
278// TODO support select message
279            goTo(msg.selectedTime, msg.extraLong == CalendarController.EXTRA_GOTO_DATE);
280        } else if (msg.eventType == EventType.EVENTS_CHANGED) {
281            eventsChanged();
282        }
283    }
284}
285