AllInOneActivity.java revision 81c3e1f6b03d3ad6e78aee64bfd4d726c3b1205e
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 static android.provider.Calendar.EVENT_BEGIN_TIME;
20import static android.provider.Calendar.EVENT_END_TIME;
21
22import com.android.calendar.CalendarController.EventHandler;
23import com.android.calendar.CalendarController.EventInfo;
24import com.android.calendar.CalendarController.EventType;
25import com.android.calendar.CalendarController.ViewType;
26import com.android.calendar.agenda.AgendaFragment;
27import com.android.calendar.event.EditEventFragment;
28import com.android.calendar.selectcalendars.SelectCalendarsFragment;
29
30import android.app.ActionBar;
31import android.app.Activity;
32import android.app.Fragment;
33import android.app.FragmentTransaction;
34import android.content.ContentResolver;
35import android.content.Intent;
36import android.content.SharedPreferences;
37import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
38import android.content.res.Configuration;
39import android.database.ContentObserver;
40import android.net.Uri;
41import android.os.Bundle;
42import android.os.Handler;
43import android.provider.Calendar;
44import android.text.format.DateUtils;
45import android.text.format.Time;
46import android.util.Log;
47import android.view.Menu;
48import android.view.MenuItem;
49import android.view.View;
50
51public class AllInOneActivity extends Activity implements EventHandler,
52        OnSharedPreferenceChangeListener {
53    private static final String TAG = "AllInOneActivity";
54    private static final boolean DEBUG = false;
55    private static final String BUNDLE_KEY_RESTORE_TIME = "key_restore_time";
56    private static final int HANDLER_KEY = 0;
57    private static CalendarController mController;
58    private static boolean mIsMultipane;
59    private ContentResolver mContentResolver;
60    private int mPreviousView;
61    private int mCurrentView;
62
63    // Create an observer so that we can update the views whenever a
64    // Calendar event changes.
65    private ContentObserver mObserver = new ContentObserver(new Handler())
66    {
67        @Override
68        public boolean deliverSelfNotifications() {
69            return true;
70        }
71
72        @Override
73        public void onChange(boolean selfChange) {
74            eventsChanged();
75        }
76    };
77
78    @Override
79    protected void onCreate(Bundle icicle) {
80        super.onCreate(icicle);
81
82        // This needs to be created before setContentView
83        mController = CalendarController.getInstance(this);
84        // Get time from intent or icicle
85        long timeMillis;
86        if (icicle != null) {
87            timeMillis = icicle.getLong(BUNDLE_KEY_RESTORE_TIME);
88        } else {
89            timeMillis = Utils.timeFromIntentInMillis(getIntent());
90        }
91        int viewType = Utils.getViewTypeFromIntentAndSharedPref(this);
92        Time t = new Time();
93        t.set(timeMillis);
94
95        mIsMultipane = (getResources().getConfiguration().screenLayout &
96                Configuration.SCREENLAYOUT_SIZE_XLARGE) != 0;
97
98        // Must be the first to register because this activity can modify the
99        // list of event handlers in it's handle method. This affects who the
100        // rest of the handlers the controller dispatches to are.
101        mController.registerEventHandler(HANDLER_KEY, this);
102
103        setContentView(R.layout.all_in_one);
104
105        initFragments(timeMillis, viewType);
106
107        // Listen for changes that would require this to be refreshed
108        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(this);
109        prefs.registerOnSharedPreferenceChangeListener(this);
110        mContentResolver = getContentResolver();
111    }
112
113    @Override
114    protected void onResume() {
115        super.onResume();
116        mContentResolver.registerContentObserver(Calendar.Events.CONTENT_URI, true, mObserver);
117    }
118
119    @Override
120    protected void onPause() {
121        super.onPause();
122        mContentResolver.unregisterContentObserver(mObserver);
123        //FRAG_TODO save highlighted days of the week;
124        if (mController.getViewType() != ViewType.EDIT) {
125            Utils.setDefaultView(this, mController.getViewType());
126        }
127    }
128
129    @Override
130    public void onSaveInstanceState(Bundle outState) {
131        super.onSaveInstanceState(outState);
132
133        outState.putLong(BUNDLE_KEY_RESTORE_TIME, mController.getTime());
134    }
135
136    @Override
137    protected void onDestroy() {
138        super.onDestroy();
139
140        SharedPreferences prefs = CalendarPreferenceActivity.getSharedPreferences(this);
141        prefs.unregisterOnSharedPreferenceChangeListener(this);
142        CalendarController.removeInstance(this);
143    }
144
145    private void initFragments(long timeMillis, int viewType) {
146        FragmentTransaction ft = getFragmentManager().openTransaction();
147
148        if (mIsMultipane) {
149            Fragment miniMonthFrag = new MonthFragment(false, timeMillis, true);
150            ft.replace(R.id.mini_month, miniMonthFrag);
151            mController.registerEventHandler(R.id.mini_month, (EventHandler) miniMonthFrag);
152
153            Fragment selectCalendarsFrag = new SelectCalendarsFragment();
154            ft.replace(R.id.calendar_list, selectCalendarsFrag);
155        }
156        if (!mIsMultipane || viewType == ViewType.EDIT){
157            findViewById(R.id.mini_month).setVisibility(View.GONE);
158            findViewById(R.id.calendar_list).setVisibility(View.GONE);
159        }
160
161        EventInfo info = null;
162        if (viewType == ViewType.EDIT) {
163            mPreviousView = CalendarPreferenceActivity.getSharedPreferences(this).getInt(
164                    CalendarPreferenceActivity.KEY_START_VIEW,
165                    CalendarPreferenceActivity.DEFAULT_START_VIEW);
166
167            int eventId = -1;
168            Intent intent = getIntent();
169            Uri data = intent.getData();
170            if (data != null) {
171                try {
172                    eventId = Integer.parseInt(data.getLastPathSegment());
173                } catch (NumberFormatException e) {
174                    if (DEBUG) {
175                        Log.d(TAG, "Create new event");
176                    }
177                }
178            }
179            long begin = intent.getLongExtra(EVENT_BEGIN_TIME, -1);
180            long end = intent.getLongExtra(EVENT_END_TIME, -1);
181            info = new EventInfo();
182            if (end != -1) {
183                info.endTime = new Time();
184                info.endTime.set(end);
185            }
186            if (begin != -1) {
187                info.startTime = new Time();
188                info.startTime.set(begin);
189            }
190            info.id = eventId;
191            // We set the viewtype so if the user presses back when they are
192            // done editing the controller knows we were in the Edit Event
193            // screen.
194            mController.setViewType(viewType);
195        } else {
196            mPreviousView = viewType;
197        }
198        setMainPane(ft, R.id.main_pane, viewType, timeMillis, true, info);
199
200        ft.commit(); // this needs to be after setMainPane()
201
202        Time t = new Time();
203        t.set(timeMillis);
204        if (viewType != ViewType.EDIT) {
205            mController.sendEvent(this, EventType.GO_TO, t, null, -1, viewType);
206        }
207    }
208
209    @Override
210    public void onBackPressed() {
211        if (mPreviousView == mCurrentView) {
212            super.onBackPressed();
213        } else {
214            mController.sendEvent(this, EventType.GO_TO, null, null, -1, mPreviousView);
215        }
216    }
217
218    @Override
219    public boolean onCreateOptionsMenu(Menu menu) {
220        super.onCreateOptionsMenu(menu);
221
222        getMenuInflater().inflate(R.menu.all_in_one_title_bar, menu);
223        return true;
224    }
225
226    @Override
227    public boolean onOptionsItemSelected(MenuItem item) {
228        Time t = null;
229        int viewType = ViewType.CURRENT;
230        switch (item.getItemId()) {
231            case R.id.action_refresh:
232                mController.refreshCalendars();
233                return true;
234            case R.id.action_day:
235                viewType = ViewType.DAY;
236                break;
237            case R.id.action_week:
238                viewType = ViewType.WEEK;
239                break;
240            case R.id.action_month:
241                viewType = ViewType.MONTH;
242                break;
243            case R.id.action_today:
244                viewType = ViewType.CURRENT;
245                t = new Time();
246                t.setToNow();
247                break;
248            case R.id.action_search:
249                onSearchRequested();
250                return true;
251            case R.id.action_create_event:
252                mController.sendEventRelatedEvent(this, EventType.CREATE_EVENT, -1, 0, 0, 0, 0);
253                return true;
254            case R.id.action_manage_calendars:
255                mController.sendEvent(this, EventType.LAUNCH_MANAGE_CALENDARS, null, null, 0, 0);
256                return true;
257            case R.id.action_settings:
258                mController.sendEvent(this, EventType.LAUNCH_SETTINGS, null, null, 0, 0);
259                return true;
260            default:
261                return false;
262        }
263        mController.sendEvent(this, EventType.GO_TO, t, null, -1, viewType);
264        return true;
265    }
266
267    @Override
268    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
269        if (key.equals(CalendarPreferenceActivity.KEY_WEEK_START_DAY)) {
270            initFragments(mController.getTime(), mController.getViewType());
271        }
272    }
273
274    private void setMainPane(FragmentTransaction ft, int viewId, int viewType,
275            long timeMillis, boolean force, EventInfo e) {
276        if(!force && mCurrentView == viewType) {
277            return;
278        }
279
280        if (viewType != mCurrentView) {
281            // The rules for this previous view are different than the
282            // controller's and are used for intercepting the back button.
283            if (mCurrentView != ViewType.EDIT && mCurrentView > 0) {
284                mPreviousView = mCurrentView;
285            }
286            mCurrentView = viewType;
287        }
288        // Create new fragment
289        Fragment frag;
290        switch (viewType) {
291            case ViewType.AGENDA:
292                frag = new AgendaFragment(timeMillis);
293                break;
294            case ViewType.DAY:
295                frag = new DayFragment(timeMillis, 1);
296                break;
297            case ViewType.WEEK:
298                frag = new DayFragment(timeMillis, 7);
299                break;
300            case ViewType.MONTH:
301                frag = new MonthFragment(false, timeMillis, false);
302                break;
303            case ViewType.EDIT:
304                frag = new EditEventFragment(e, mPreviousView);
305                break;
306            default:
307                throw new IllegalArgumentException(
308                        "Must be Agenda, Day, Week, or Month ViewType, not " + viewType);
309        }
310
311        boolean doCommit = false;
312        if (ft == null) {
313            doCommit = true;
314            ft = getFragmentManager().openTransaction();
315        }
316
317        ft.replace(viewId, frag);
318        if (DEBUG) {
319            Log.d(TAG, "Adding handler with viewId " + viewId + " and type " + viewType);
320        }
321        // If the key is already registered this will replace it
322        mController.registerEventHandler(viewId, (EventHandler) frag);
323
324        if (doCommit) {
325            ft.commit();
326        }
327    }
328
329    private void setTitleInActionBar(EventInfo event) {
330        if (event.eventType != EventType.GO_TO) {
331            return;
332        }
333
334        long start = event.startTime.toMillis(false /* use isDst */);
335        long end = start;
336
337        if (event.endTime != null) {
338            end = event.endTime.toMillis(false /* use isDst */);
339        }
340        String msg = DateUtils.formatDateRange(this, start, end, DateUtils.FORMAT_SHOW_DATE);
341
342        ActionBar ab = getActionBar();
343        if (ab != null) {
344            ab.setTitle(msg);
345        }
346    }
347
348    @Override
349    public long getSupportedEventTypes() {
350        return EventType.GO_TO | EventType.VIEW_EVENT | EventType.EDIT_EVENT |
351                EventType.CREATE_EVENT;
352    }
353
354    @Override
355    public void handleEvent(EventInfo event) {
356        if (event.eventType == EventType.GO_TO) {
357            // Set title bar
358            setTitleInActionBar(event);
359
360            setMainPane(null, R.id.main_pane, event.viewType,
361                    event.startTime.toMillis(false), false, event);
362
363            if (!mIsMultipane) {
364                return;
365            }
366            if (event.viewType == ViewType.MONTH) {
367                // hide minimonth and calendar frag
368                findViewById(R.id.mini_month).setVisibility(View.GONE);
369                findViewById(R.id.calendar_list).setVisibility(View.GONE);
370            } else {
371                // show minimonth and calendar frag
372                findViewById(R.id.mini_month).setVisibility(View.VISIBLE);
373                findViewById(R.id.calendar_list).setVisibility(View.VISIBLE);
374            }
375        } else if (event.eventType == EventType.VIEW_EVENT) {
376            EventInfoFragment fragment = new EventInfoFragment(event.id, event.startTime
377                    .toMillis(false), event.endTime.toMillis(false));
378            fragment.setDialogParams(event.x, event.y);
379            fragment.show(getFragmentManager(), "EventInfoFragment");
380        } else if (event.eventType == EventType.EDIT_EVENT ||
381                event.eventType == EventType.CREATE_EVENT) {
382            setMainPane(null, R.id.main_pane, ViewType.EDIT, -1, true, event);
383            // hide minimonth and calendar frag
384            findViewById(R.id.mini_month).setVisibility(View.GONE);
385            findViewById(R.id.calendar_list).setVisibility(View.GONE);
386        }
387    }
388
389    @Override
390    public void eventsChanged() {
391        mController.sendEvent(this, EventType.EVENTS_CHANGED, null, null, -1, ViewType.CURRENT);
392    }
393
394    @Override
395    public boolean getAllDay() {
396        return false;
397    }
398
399    @Override
400    public long getSelectedTime() {
401        return 0;
402    }
403
404    @Override
405    public void goTo(Time time, boolean animate) {
406    }
407
408    @Override
409    public void goToToday() {
410    }
411}
412