AllInOneActivity.java revision 100bdbecdfdcd3449630e5adb3d5b1296a000bd4
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;
21import static android.provider.Calendar.AttendeesColumns.ATTENDEE_STATUS;
22
23import com.android.calendar.CalendarController.EventHandler;
24import com.android.calendar.CalendarController.EventInfo;
25import com.android.calendar.CalendarController.EventType;
26import com.android.calendar.CalendarController.ViewType;
27import com.android.calendar.agenda.AgendaFragment;
28import com.android.calendar.month.MonthByWeekFragment;
29import com.android.calendar.selectcalendars.SelectCalendarsFragment;
30
31import android.animation.Animator;
32import android.animation.Animator.AnimatorListener;
33import android.animation.ObjectAnimator;
34import android.app.ActionBar;
35import android.app.ActionBar.Tab;
36import android.app.Activity;
37import android.app.Fragment;
38import android.app.FragmentManager;
39import android.app.FragmentTransaction;
40import android.content.ContentResolver;
41import android.content.Intent;
42import android.content.SharedPreferences;
43import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
44import android.content.res.Configuration;
45import android.content.res.Resources;
46import android.database.ContentObserver;
47import android.net.Uri;
48import android.os.Bundle;
49import android.os.Handler;
50import android.provider.Calendar;
51import android.text.TextUtils;
52import android.text.format.DateFormat;
53import android.text.format.DateUtils;
54import android.text.format.Time;
55import android.util.Log;
56import android.view.Menu;
57import android.view.MenuItem;
58import android.view.View;
59import android.view.accessibility.AccessibilityEvent;
60import android.widget.RelativeLayout;
61import android.widget.RelativeLayout.LayoutParams;
62import android.widget.SearchView;
63import android.widget.TextView;
64
65import java.util.List;
66import java.util.Locale;
67import java.util.TimeZone;
68
69public class AllInOneActivity extends Activity implements EventHandler,
70        OnSharedPreferenceChangeListener, SearchView.OnQueryTextListener,
71        ActionBar.TabListener {
72    private static final String TAG = "AllInOneActivity";
73    private static final boolean DEBUG = false;
74    private static final String EVENT_INFO_FRAGMENT_TAG = "EventInfoFragment";
75    private static final String BUNDLE_KEY_RESTORE_TIME = "key_restore_time";
76    private static final String BUNDLE_KEY_EVENT_ID = "key_event_id";
77    private static final String BUNDLE_KEY_RESTORE_VIEW = "key_restore_view";
78    private static final int HANDLER_KEY = 0;
79    private static final long CONTROLS_ANIMATE_DURATION = 400;
80    private static int CONTROLS_ANIMATE_WIDTH = 267;
81    private static float mScale = 0;
82
83    private static CalendarController mController;
84    private static boolean mIsMultipane;
85    private boolean mOnSaveInstanceStateCalled = false;
86    private ContentResolver mContentResolver;
87    private int mPreviousView;
88    private int mCurrentView;
89    private boolean mPaused = true;
90    private boolean mUpdateOnResume = false;
91    private boolean mHideControls = false;
92    private boolean mShowSideViews = true;
93    private TextView mHomeTime;
94    private TextView mDateRange;
95    private View mMiniMonth;
96    private View mCalendarsList;
97    private View mMiniMonthContainer;
98    private String mTimeZone;
99
100    private long mViewEventId = -1;
101    private long mIntentEventStartMillis = -1;
102    private long mIntentEventEndMillis = -1;
103    private int mIntentAttendeeResponse = CalendarController.ATTENDEE_NO_RESPONSE;
104
105    // Action bar and Navigation bar (left side of Action bar)
106    private ActionBar mActionBar;
107    private ActionBar.Tab mDayTab;
108    private ActionBar.Tab mWeekTab;
109    private ActionBar.Tab mMonthTab;
110    private SearchView mSearchView;
111    private MenuItem mControlsMenu;
112
113    private String mHideString = "Hide controls";
114    private String mShowString = "Show controls";
115
116    // Params for animating the controls on the right
117    private LayoutParams mControlsParams = new LayoutParams(CONTROLS_ANIMATE_WIDTH, 0);
118
119    private AnimatorListener mSlideAnimationDoneListener = new AnimatorListener() {
120
121        @Override
122        public void onAnimationCancel(Animator animation) {
123        }
124
125        @Override
126        public void onAnimationEnd(android.animation.Animator animation) {
127            int visibility = mShowSideViews ? View.VISIBLE : View.GONE;
128            mMiniMonth.setVisibility(visibility);
129            mCalendarsList.setVisibility(visibility);
130            mMiniMonthContainer.setVisibility(visibility);
131        }
132
133        @Override
134        public void onAnimationRepeat(android.animation.Animator animation) {
135        }
136
137        @Override
138        public void onAnimationStart(android.animation.Animator animation) {
139        }
140    };
141
142    private Runnable mHomeTimeUpdater = new Runnable() {
143        @Override
144        public void run() {
145            updateHomeClock();
146        }
147    };
148
149    // Create an observer so that we can update the views whenever a
150    // Calendar event changes.
151    private ContentObserver mObserver = new ContentObserver(new Handler()) {
152        @Override
153        public boolean deliverSelfNotifications() {
154            return true;
155        }
156
157        @Override
158        public void onChange(boolean selfChange) {
159            eventsChanged();
160        }
161    };
162
163    @Override
164    protected void onNewIntent(Intent intent) {
165        String action = intent.getAction();
166        if (Intent.ACTION_VIEW.equals(action)) {
167            parseViewAction(intent);
168        }
169    }
170
171    @Override
172    protected void onCreate(Bundle icicle) {
173        if (Utils.getSharedPreference(this, OtherPreferences.KEY_OTHER_1, false)) {
174            setTheme(R.style.CalendarTheme_WithActionBarWallpaper);
175        }
176        super.onCreate(icicle);
177
178        // This needs to be created before setContentView
179        mController = CalendarController.getInstance(this);
180        // Get time from intent or icicle
181        long timeMillis = -1;
182        int viewType = -1;
183        final Intent intent = getIntent();
184        if (icicle != null) {
185            timeMillis = icicle.getLong(BUNDLE_KEY_RESTORE_TIME);
186            viewType = icicle.getInt(BUNDLE_KEY_RESTORE_VIEW, -1);
187        } else {
188            String action = intent.getAction();
189            if (Intent.ACTION_VIEW.equals(action)) {
190                // Open EventInfo later
191                timeMillis = parseViewAction(intent);
192            }
193
194            if (timeMillis == -1) {
195                timeMillis = Utils.timeFromIntentInMillis(intent);
196            }
197        }
198
199        if (viewType == -1) {
200            viewType = Utils.getViewTypeFromIntentAndSharedPref(this);
201        }
202        mTimeZone = Utils.getTimeZone(this, mHomeTimeUpdater);
203        Time t = new Time(mTimeZone);
204        t.set(timeMillis);
205
206        if (icicle != null && intent != null) {
207            Log.d(TAG, "both, icicle:" + icicle.toString() + "  intent:" + intent.toString());
208        } else {
209            Log.d(TAG, "not both, icicle:" + icicle + " intent:" + intent);
210        }
211
212        Resources res = getResources();
213        if (mScale == 0) {
214            mScale = res.getDisplayMetrics().density;
215            CONTROLS_ANIMATE_WIDTH *= mScale;
216        }
217        mHideString = res.getString(R.string.hide_controls);
218        mShowString = res.getString(R.string.show_controls);
219        mControlsParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
220
221        mIsMultipane =
222                (res.getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_XLARGE) != 0;
223
224        Utils.setAllowWeekForDetailView(mIsMultipane);
225
226        mDateRange = (TextView) getLayoutInflater().inflate(R.layout.date_range_title, null);
227
228        // setContentView must be called before configureActionBar
229        setContentView(R.layout.all_in_one);
230        // configureActionBar auto-selects the first tab you add, so we need to
231        // call it before we set up our own fragments to make sure it doesn't
232        // overwrite us
233        configureActionBar();
234
235        // Must be the first to register because this activity can modify the
236        // list of event handlers in it's handle method. This affects who the
237        // rest of the handlers the controller dispatches to are.
238        mController.registerEventHandler(HANDLER_KEY, this);
239
240        mHomeTime = (TextView) findViewById(R.id.home_time);
241        mMiniMonth = findViewById(R.id.mini_month);
242        mCalendarsList = findViewById(R.id.calendar_list);
243        mMiniMonthContainer = findViewById(R.id.mini_month_container);
244
245        initFragments(timeMillis, viewType, icicle);
246
247
248        // Listen for changes that would require this to be refreshed
249        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(this);
250        prefs.registerOnSharedPreferenceChangeListener(this);
251
252        mContentResolver = getContentResolver();
253    }
254
255    private long parseViewAction(final Intent intent) {
256        long timeMillis = -1;
257        Uri data = intent.getData();
258        if (data != null && data.isHierarchical()) {
259            List<String> path = data.getPathSegments();
260            if (path.size() == 2 && path.get(0).equals("events")) {
261                try {
262                    mViewEventId = Long.valueOf(data.getLastPathSegment());
263                    if(mViewEventId != -1) {
264                        mIntentEventStartMillis = intent.getLongExtra(EVENT_BEGIN_TIME, 0);
265                        mIntentEventEndMillis = intent.getLongExtra(EVENT_END_TIME, 0);
266                        mIntentAttendeeResponse = intent.getIntExtra(
267                                ATTENDEE_STATUS, CalendarController.ATTENDEE_NO_RESPONSE);
268                        timeMillis = mIntentEventStartMillis;
269                    }
270                } catch (NumberFormatException e) {
271                    // Ignore if mViewEventId can't be parsed
272                }
273            }
274        }
275        return timeMillis;
276    }
277
278    private void configureActionBar() {
279        mActionBar = getActionBar();
280        mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
281        if (mActionBar == null) {
282            Log.w(TAG, "ActionBar is null.");
283        } else {
284            mDayTab = mActionBar.newTab();
285            mDayTab.setText(getString(R.string.day_view));
286            mDayTab.setTabListener(this);
287            mActionBar.addTab(mDayTab);
288            mWeekTab = mActionBar.newTab();
289            mWeekTab.setText(getString(R.string.week_view));
290            mWeekTab.setTabListener(this);
291            mActionBar.addTab(mWeekTab);
292            mMonthTab = mActionBar.newTab();
293            mMonthTab.setText(getString(R.string.month_view));
294            mMonthTab.setTabListener(this);
295            mActionBar.addTab(mMonthTab);
296            mActionBar.setCustomView(mDateRange);
297            mActionBar.setDisplayOptions(
298                    ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME);
299        }
300    }
301
302    @Override
303    protected void onResume() {
304        super.onResume();
305        mContentResolver.registerContentObserver(Calendar.Events.CONTENT_URI, true, mObserver);
306        if (mUpdateOnResume) {
307            initFragments(mController.getTime(), mController.getViewType(), null);
308            mUpdateOnResume = false;
309        }
310        updateHomeClock();
311        if (mControlsMenu != null) {
312            mControlsMenu.setTitle(mHideControls ? mShowString : mHideString);
313        }
314        mPaused = false;
315        mOnSaveInstanceStateCalled = false;
316
317        if (mViewEventId != -1 && mIntentEventStartMillis != -1 && mIntentEventEndMillis != -1) {
318            long currentMillis = System.currentTimeMillis();
319            long selectedTime = -1;
320            if (currentMillis > mIntentEventStartMillis && currentMillis < mIntentEventEndMillis) {
321                selectedTime = currentMillis;
322            }
323            mController.sendEventRelatedEventWithResponse(this, EventType.VIEW_EVENT, mViewEventId,
324                    mIntentEventStartMillis, mIntentEventEndMillis, -1, -1, mIntentAttendeeResponse,
325                    selectedTime);
326            mViewEventId = -1;
327            mIntentEventStartMillis = -1;
328            mIntentEventEndMillis = -1;
329        }
330    }
331
332    @Override
333    protected void onPause() {
334        super.onPause();
335        mPaused = true;
336        mHomeTime.removeCallbacks(mHomeTimeUpdater);
337        mContentResolver.unregisterContentObserver(mObserver);
338        if (isFinishing()) {
339            // Stop listening for changes that would require this to be refreshed
340            SharedPreferences prefs = GeneralPreferences.getSharedPreferences(this);
341            prefs.unregisterOnSharedPreferenceChangeListener(this);
342        }
343        // FRAG_TODO save highlighted days of the week;
344        if (mController.getViewType() != ViewType.EDIT) {
345            Utils.setDefaultView(this, mController.getViewType());
346        }
347    }
348
349    @Override
350    protected void onUserLeaveHint() {
351        mController.sendEvent(this, EventType.USER_HOME, null, null, -1, ViewType.CURRENT);
352        super.onUserLeaveHint();
353    }
354
355    @Override
356    public void onSaveInstanceState(Bundle outState) {
357        mOnSaveInstanceStateCalled = true;
358        super.onSaveInstanceState(outState);
359
360        outState.putLong(BUNDLE_KEY_RESTORE_TIME, mController.getTime());
361        if (mCurrentView == ViewType.EDIT) {
362            outState.putInt(BUNDLE_KEY_RESTORE_VIEW, mCurrentView);
363            outState.putLong(BUNDLE_KEY_EVENT_ID, mController.getEventId());
364        }
365    }
366
367    @Override
368    protected void onDestroy() {
369        super.onDestroy();
370
371        SharedPreferences prefs = GeneralPreferences.getSharedPreferences(this);
372        prefs.unregisterOnSharedPreferenceChangeListener(this);
373        CalendarController.removeInstance(this);
374    }
375
376    private void initFragments(long timeMillis, int viewType, Bundle icicle) {
377        FragmentTransaction ft = getFragmentManager().beginTransaction();
378
379        if (mIsMultipane) {
380            Fragment miniMonthFrag = new MonthByWeekFragment(timeMillis, true);
381            ft.replace(R.id.mini_month, miniMonthFrag);
382            mController.registerEventHandler(R.id.mini_month, (EventHandler) miniMonthFrag);
383
384            Fragment selectCalendarsFrag = new SelectCalendarsFragment();
385            ft.replace(R.id.calendar_list, selectCalendarsFrag);
386            mController.registerEventHandler(
387                    R.id.calendar_list, (EventHandler) selectCalendarsFrag);
388        }
389        if (!mIsMultipane || viewType == ViewType.EDIT) {
390            mMiniMonth.setVisibility(View.GONE);
391            mCalendarsList.setVisibility(View.GONE);
392        }
393
394        EventInfo info = null;
395        if (viewType == ViewType.EDIT) {
396            mPreviousView = GeneralPreferences.getSharedPreferences(this).getInt(
397                    GeneralPreferences.KEY_START_VIEW, GeneralPreferences.DEFAULT_START_VIEW);
398
399            long eventId = -1;
400            Intent intent = getIntent();
401            Uri data = intent.getData();
402            if (data != null) {
403                try {
404                    eventId = Long.parseLong(data.getLastPathSegment());
405                } catch (NumberFormatException e) {
406                    if (DEBUG) {
407                        Log.d(TAG, "Create new event");
408                    }
409                }
410            } else if (icicle != null && icicle.containsKey(BUNDLE_KEY_EVENT_ID)) {
411                eventId = icicle.getLong(BUNDLE_KEY_EVENT_ID);
412            }
413
414            long begin = intent.getLongExtra(EVENT_BEGIN_TIME, -1);
415            long end = intent.getLongExtra(EVENT_END_TIME, -1);
416            info = new EventInfo();
417            if (end != -1) {
418                info.endTime = new Time();
419                info.endTime.set(end);
420            }
421            if (begin != -1) {
422                info.startTime = new Time();
423                info.startTime.set(begin);
424            }
425            info.id = eventId;
426            // We set the viewtype so if the user presses back when they are
427            // done editing the controller knows we were in the Edit Event
428            // screen. Likewise for eventId
429            mController.setViewType(viewType);
430            mController.setEventId(eventId);
431        } else {
432            mPreviousView = viewType;
433        }
434        setMainPane(ft, R.id.main_pane, viewType, timeMillis, true);
435
436        ft.commit(); // this needs to be after setMainPane()
437
438        Time t = new Time(mTimeZone);
439        t.set(timeMillis);
440        if (viewType != ViewType.EDIT) {
441            mController.sendEvent(this, EventType.GO_TO, t, null, -1, viewType);
442        }
443    }
444
445    @Override
446    public void onBackPressed() {
447        if (mCurrentView == ViewType.EDIT || mCurrentView == ViewType.DETAIL) {
448            mController.sendEvent(this, EventType.GO_TO, null, null, -1, mPreviousView);
449        } else {
450            super.onBackPressed();
451        }
452    }
453
454    @Override
455    public boolean onCreateOptionsMenu(Menu menu) {
456        super.onCreateOptionsMenu(menu);
457
458        getMenuInflater().inflate(R.menu.all_in_one_title_bar, menu);
459
460        mSearchView = (SearchView) menu.findItem(R.id.action_search).getActionView();
461        if (mSearchView != null) {
462            mSearchView.setIconifiedByDefault(true);
463            mSearchView.setOnQueryTextListener(this);
464            mSearchView.setSubmitButtonEnabled(true);
465        }
466        mControlsMenu = menu.findItem(R.id.action_hide_controls);
467        if (mControlsMenu != null && mController != null
468                && mController.getViewType() == ViewType.MONTH) {
469            mControlsMenu.setVisible(false);
470            mControlsMenu.setEnabled(false);
471        }
472
473        return true;
474    }
475
476    @Override
477    public boolean onOptionsItemSelected(MenuItem item) {
478        Time t = null;
479        int viewType = ViewType.CURRENT;
480        switch (item.getItemId()) {
481            case R.id.action_refresh:
482                mController.refreshCalendars();
483                return true;
484            case R.id.action_today:
485                viewType = ViewType.CURRENT;
486                t = new Time(mTimeZone);
487                t.setToNow();
488                break;
489            case R.id.action_create_event:
490                t = new Time();
491                t.set(mController.getTime());
492                if (t.minute >= 30) {
493                    t.hour++;
494                    t.minute = 0;
495                } else {
496                    t.minute = 30;
497                }
498                mController.sendEventRelatedEvent(
499                        this, EventType.CREATE_EVENT, -1, t.toMillis(true), 0, 0, 0, -1);
500                return true;
501            case R.id.action_settings:
502                mController.sendEvent(this, EventType.LAUNCH_SETTINGS, null, null, 0, 0);
503                return true;
504            case R.id.action_hide_controls:
505                mHideControls = !mHideControls;
506                item.setTitle(mHideControls ? mShowString : mHideString);
507                final ObjectAnimator slideAnimation = ObjectAnimator.ofInt(this, "controlsOffset",
508                        mHideControls ? 0 : CONTROLS_ANIMATE_WIDTH,
509                        mHideControls ? CONTROLS_ANIMATE_WIDTH : 0);
510                slideAnimation.setDuration(CONTROLS_ANIMATE_DURATION);
511                ObjectAnimator.setFrameDelay(0);
512                slideAnimation.start();
513                return true;
514            default:
515                return false;
516        }
517        mController.sendEvent(this, EventType.GO_TO, t, null, -1, viewType);
518        return true;
519    }
520
521    /**
522     * Sets the offset of the controls on the right for animating them off/on
523     * screen. ProGuard strips this if it's not in proguard.flags
524     *
525     * @param controlsOffset The current offset in pixels
526     */
527    public void setControlsOffset(int controlsOffset) {
528        mMiniMonth.setTranslationX(controlsOffset);
529        mCalendarsList.setTranslationX(controlsOffset);
530        mHomeTime.setTranslationX(controlsOffset);
531        mControlsParams.width = Math.max(0, CONTROLS_ANIMATE_WIDTH - controlsOffset);
532        mMiniMonthContainer.setLayoutParams(mControlsParams);
533    }
534
535    @Override
536    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
537        if (key.equals(GeneralPreferences.KEY_WEEK_START_DAY)) {
538            if (mPaused) {
539                mUpdateOnResume = true;
540            } else {
541                initFragments(mController.getTime(), mController.getViewType(), null);
542            }
543        }
544    }
545
546    private void setMainPane(
547            FragmentTransaction ft, int viewId, int viewType, long timeMillis, boolean force) {
548        if (mOnSaveInstanceStateCalled) {
549            return;
550        }
551        if (!force && mCurrentView == viewType) {
552            return;
553        }
554
555        // Remove this when transition to and from month view looks fine.
556        boolean doTransition = viewType != ViewType.MONTH && mCurrentView != ViewType.MONTH;
557
558        if (viewType != mCurrentView) {
559            // The rules for this previous view are different than the
560            // controller's and are used for intercepting the back button.
561            if (mCurrentView != ViewType.EDIT && mCurrentView > 0) {
562                mPreviousView = mCurrentView;
563            }
564            mCurrentView = viewType;
565        }
566        // Create new fragment
567        Fragment frag;
568        switch (viewType) {
569            case ViewType.AGENDA:
570                frag = new AgendaFragment(timeMillis);
571                break;
572            case ViewType.DAY:
573                if (mActionBar != null && (mActionBar.getSelectedTab() != mDayTab)) {
574                    mActionBar.selectTab(mDayTab);
575                }
576                frag = new DayFragment(timeMillis, 1);
577                break;
578            case ViewType.WEEK:
579                if (mActionBar != null && (mActionBar.getSelectedTab() != mWeekTab)) {
580                    mActionBar.selectTab(mWeekTab);
581                }
582                frag = new DayFragment(timeMillis, 7);
583                break;
584            case ViewType.MONTH:
585                if (mActionBar != null && (mActionBar.getSelectedTab() != mMonthTab)) {
586                    mActionBar.selectTab(mMonthTab);
587                }
588                frag = new MonthByWeekFragment(timeMillis, false);
589                break;
590            default:
591                throw new IllegalArgumentException(
592                        "Must be Agenda, Day, Week, or Month ViewType, not " + viewType);
593        }
594
595        boolean doCommit = false;
596        if (ft == null) {
597            doCommit = true;
598            ft = getFragmentManager().beginTransaction();
599        }
600
601        if (doTransition) {
602            ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
603        }
604
605        ft.replace(viewId, frag);
606
607        if (DEBUG) {
608            Log.d(TAG, "Adding handler with viewId " + viewId + " and type " + viewType);
609        }
610        // If the key is already registered this will replace it
611        mController.registerEventHandler(viewId, (EventHandler) frag);
612
613        if (doCommit) {
614            Log.d(TAG, "setMainPane AllInOne=" + this + " finishing:" + this.isFinishing());
615            ft.commit();
616        }
617    }
618
619    private void setTitleInActionBar(EventInfo event) {
620        if (event.eventType != EventType.UPDATE_TITLE || mActionBar == null) {
621            return;
622        }
623
624        final long start = event.startTime.toMillis(false /* use isDst */);
625        final long end;
626        if (event.endTime != null) {
627            end = event.endTime.toMillis(false /* use isDst */);
628        } else {
629            end = start;
630        }
631
632        final String msg = Utils.formatDateRange(this, start, end, (int) event.extraLong);
633        CharSequence oldDate = mDateRange.getText();
634        mDateRange.setText(msg);
635        if (!TextUtils.equals(oldDate, msg)) {
636            mDateRange.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
637        }
638    }
639
640    private void updateHomeClock() {
641        mTimeZone = Utils.getTimeZone(this, mHomeTimeUpdater);
642        if (mIsMultipane && (mCurrentView == ViewType.DAY || mCurrentView == ViewType.WEEK)
643                && !TextUtils.equals(mTimeZone, Time.getCurrentTimezone())) {
644            Time time = new Time(mTimeZone);
645            time.setToNow();
646            long millis = time.toMillis(true);
647            boolean isDST = time.isDst != 0;
648            int flags = DateUtils.FORMAT_SHOW_TIME;
649            if (DateFormat.is24HourFormat(this)) {
650                flags |= DateUtils.FORMAT_24HOUR;
651            }
652            // Formats the time as
653            String timeString = (new StringBuilder(
654                    Utils.formatDateRange(this, millis, millis, flags))).append(" ").append(
655                    TimeZone.getTimeZone(mTimeZone).getDisplayName(
656                            isDST, TimeZone.SHORT, Locale.getDefault())).toString();
657            mHomeTime.setText(timeString);
658            mHomeTime.setVisibility(View.VISIBLE);
659            // Update when the minute changes
660            mHomeTime.postDelayed(
661                    mHomeTimeUpdater,
662                    DateUtils.MINUTE_IN_MILLIS - (millis % DateUtils.MINUTE_IN_MILLIS));
663        } else {
664            mHomeTime.setVisibility(View.GONE);
665        }
666    }
667
668    @Override
669    public long getSupportedEventTypes() {
670        return EventType.GO_TO | EventType.VIEW_EVENT | EventType.UPDATE_TITLE;
671    }
672
673    @Override
674    public void handleEvent(EventInfo event) {
675        Log.d(TAG, "handleEvent AllInOne=" + this);
676        if (event.eventType == EventType.GO_TO) {
677            setMainPane(
678                    null, R.id.main_pane, event.viewType, event.startTime.toMillis(false), false);
679            if (mSearchView != null) {
680                mSearchView.clearFocus();
681            }
682            if (!mIsMultipane) {
683                return;
684            }
685            if (event.viewType == ViewType.MONTH) {
686                // hide minimonth and calendar frag
687                mShowSideViews = false;
688                if (mControlsMenu != null) {
689                    mControlsMenu.setVisible(false);
690                    mControlsMenu.setEnabled(false);
691
692                    if (!mHideControls) {
693                        final ObjectAnimator slideAnimation = ObjectAnimator.ofInt(this,
694                                "controlsOffset", 0, CONTROLS_ANIMATE_WIDTH);
695                        slideAnimation.addListener(mSlideAnimationDoneListener);
696                        slideAnimation.setDuration(220);
697                        ObjectAnimator.setFrameDelay(0);
698                        slideAnimation.start();
699                    }
700                } else {
701                    mMiniMonth.setVisibility(View.GONE);
702                    mCalendarsList.setVisibility(View.GONE);
703                    mMiniMonthContainer.setVisibility(View.GONE);
704                }
705            } else {
706                // show minimonth and calendar frag
707                mShowSideViews = true;
708                mMiniMonth.setVisibility(View.VISIBLE);
709                mCalendarsList.setVisibility(View.VISIBLE);
710                mMiniMonthContainer.setVisibility(View.VISIBLE);
711                if (mControlsMenu != null) {
712                    mControlsMenu.setVisible(true);
713                    mControlsMenu.setEnabled(true);
714                    if (!mHideControls && mController.getPreviousViewType() == ViewType.MONTH) {
715                        final ObjectAnimator slideAnimation = ObjectAnimator.ofInt(this,
716                                "controlsOffset", CONTROLS_ANIMATE_WIDTH, 0);
717                        slideAnimation.setDuration(220);
718                        ObjectAnimator.setFrameDelay(0);
719                        slideAnimation.start();
720                    }
721                }
722            }
723        } else if (event.eventType == EventType.VIEW_EVENT) {
724            EventInfoFragment fragment = new EventInfoFragment(this,
725                    event.id, event.startTime.toMillis(false), event.endTime.toMillis(false),
726                    (int) event.extraLong);
727            if (event.selectedTime != null) {
728                mController.sendEvent(this, EventType.GO_TO, event.selectedTime, event.selectedTime,
729                        -1, ViewType.DETAIL);
730            }
731            fragment.setDialogParams(event.x, event.y);
732            FragmentManager fm = getFragmentManager();
733            FragmentTransaction ft = fm.beginTransaction();
734            // if we have an old popup close it
735            Fragment fOld = fm.findFragmentByTag(EVENT_INFO_FRAGMENT_TAG);
736            if (fOld != null && fOld.isAdded()) {
737                ft.remove(fOld);
738            }
739            ft.add(fragment, EVENT_INFO_FRAGMENT_TAG);
740            ft.commit();
741        } else if (event.eventType == EventType.UPDATE_TITLE) {
742            setTitleInActionBar(event);
743        }
744        updateHomeClock();
745    }
746
747    @Override
748    public void eventsChanged() {
749        mController.sendEvent(this, EventType.EVENTS_CHANGED, null, null, -1, ViewType.CURRENT);
750    }
751
752    @Override
753    public boolean onQueryTextChange(String newText) {
754        return false;
755    }
756
757    @Override
758    public boolean onQueryTextSubmit(String query) {
759        if (TextUtils.equals(query, "TARDIS")) {
760            Utils.tardis();
761        }
762        mSearchView.clearFocus();
763        mController.sendEvent(this, EventType.SEARCH, null, null, -1, ViewType.CURRENT, -1, query,
764                getComponentName());
765        return false;
766    }
767
768    @Override
769    public void onTabSelected(Tab tab, FragmentTransaction ft) {
770        Log.w(TAG, "TabSelected AllInOne=" + this + " finishing:" + this.isFinishing());
771        if (tab == mDayTab && mCurrentView != ViewType.DAY) {
772            mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.DAY);
773        } else if (tab == mWeekTab && mCurrentView != ViewType.WEEK) {
774            mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.WEEK);
775        } else if (tab == mMonthTab && mCurrentView != ViewType.MONTH) {
776            mController.sendEvent(this, EventType.GO_TO, null, null, -1, ViewType.MONTH);
777        } else {
778            Log.w(TAG, "TabSelected event from unknown tab: "
779                    + (tab == null ? "null" : tab.getText()));
780            Log.w(TAG, "CurrentView:" + mCurrentView + " Tab:" + tab.toString() + " Day:" + mDayTab
781                    + " Week:" + mWeekTab + " Month:" + mMonthTab);
782        }
783    }
784
785    @Override
786    public void onTabReselected(Tab tab, FragmentTransaction ft) {
787    }
788
789    @Override
790    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
791    }
792}
793