Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 1 | /* |
Erik | 954c871 | 2010-08-06 10:12:34 -0700 | [diff] [blame] | 2 | * Copyright (C) 2010 The Android Open Source Project |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 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 | |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 19 | import com.android.calendar.CalendarController.EventInfo; |
| 20 | import com.android.calendar.CalendarController.EventType; |
| 21 | |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 22 | import android.app.Fragment; |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 23 | import android.content.Context; |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 24 | import android.os.Bundle; |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 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 | */ |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 39 | public class DayFragment extends Fragment implements CalendarController.EventHandler, ViewFactory { |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 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 | |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 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 | |
Isaac Katzenelson | 0a30ef1 | 2012-04-12 11:33:39 -0700 | [diff] [blame] | 59 | private final Runnable mTZUpdater = new Runnable() { |
Erik | 40bcd10 | 2010-11-16 15:46:40 -0800 | [diff] [blame] | 60 | @Override |
| 61 | public void run() { |
| 62 | if (!DayFragment.this.isAdded()) { |
| 63 | return; |
| 64 | } |
| 65 | String tz = Utils.getTimeZone(getActivity(), mTZUpdater); |
Erik | 04b2889 | 2011-01-19 16:19:15 -0800 | [diff] [blame] | 66 | mSelectedDay.timezone = tz; |
| 67 | mSelectedDay.normalize(true); |
Erik | 40bcd10 | 2010-11-16 15:46:40 -0800 | [diff] [blame] | 68 | } |
| 69 | }; |
| 70 | |
Michael Chan | 75d9b56 | 2010-07-26 16:54:25 -0700 | [diff] [blame] | 71 | private int mNumDays; |
| 72 | |
Michael Chan | 3458a17 | 2010-07-13 17:58:21 -0700 | [diff] [blame] | 73 | public DayFragment() { |
| 74 | mSelectedDay.setToNow(); |
| 75 | } |
| 76 | |
Michael Chan | 75d9b56 | 2010-07-26 16:54:25 -0700 | [diff] [blame] | 77 | public DayFragment(long timeMillis, int numOfDays) { |
| 78 | mNumDays = numOfDays; |
Michael Chan | 3458a17 | 2010-07-13 17:58:21 -0700 | [diff] [blame] | 79 | if (timeMillis == 0) { |
| 80 | mSelectedDay.setToNow(); |
| 81 | } else { |
| 82 | mSelectedDay.set(timeMillis); |
| 83 | } |
| 84 | } |
| 85 | |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 86 | @Override |
| 87 | public void onCreate(Bundle icicle) { |
| 88 | super.onCreate(icicle); |
| 89 | |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 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 | |
Erik | 954c871 | 2010-08-06 10:12:34 -0700 | [diff] [blame] | 100 | @Override |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 101 | public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| 102 | Bundle savedInstanceState) { |
Michael Chan | 75d9b56 | 2010-07-26 16:54:25 -0700 | [diff] [blame] | 103 | View v = inflater.inflate(R.layout.day_activity, null); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 104 | |
| 105 | mViewSwitcher = (ViewSwitcher) v.findViewById(R.id.switcher); |
| 106 | mViewSwitcher.setFactory(this); |
| 107 | mViewSwitcher.getCurrentView().requestFocus(); |
Erik | eaafa2b | 2010-12-23 14:30:37 -0800 | [diff] [blame] | 108 | ((DayView) mViewSwitcher.getCurrentView()).updateTitle(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 109 | |
| 110 | return v; |
| 111 | } |
| 112 | |
| 113 | public View makeView() { |
Erik | 40bcd10 | 2010-11-16 15:46:40 -0800 | [diff] [blame] | 114 | mTZUpdater.run(); |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 115 | DayView view = new DayView(getActivity(), CalendarController |
Michael Chan | 75d9b56 | 2010-07-26 16:54:25 -0700 | [diff] [blame] | 116 | .getInstance(getActivity()), mViewSwitcher, mEventLoader, mNumDays); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 117 | view.setId(VIEW_ID); |
| 118 | view.setLayoutParams(new ViewSwitcher.LayoutParams( |
| 119 | LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); |
RoboErik | 5b87252 | 2011-10-03 17:24:50 -0700 | [diff] [blame] | 120 | view.setSelected(mSelectedDay, false, false); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 121 | return view; |
| 122 | } |
| 123 | |
| 124 | @Override |
| 125 | public void onResume() { |
| 126 | super.onResume(); |
| 127 | mEventLoader.startBackgroundThread(); |
Erik | 04b2889 | 2011-01-19 16:19:15 -0800 | [diff] [blame] | 128 | mTZUpdater.run(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 129 | eventsChanged(); |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 130 | DayView view = (DayView) mViewSwitcher.getCurrentView(); |
Michael Chan | 61a2e87 | 2011-01-19 17:29:46 -0800 | [diff] [blame] | 131 | view.handleOnResume(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 132 | view.restartCurrentTimeUpdates(); |
| 133 | |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 134 | view = (DayView) mViewSwitcher.getNextView(); |
Michael Chan | 61a2e87 | 2011-01-19 17:29:46 -0800 | [diff] [blame] | 135 | view.handleOnResume(); |
Erik | 4d090a7 | 2011-01-20 14:50:25 -0800 | [diff] [blame] | 136 | view.restartCurrentTimeUpdates(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 137 | } |
| 138 | |
| 139 | @Override |
| 140 | public void onSaveInstanceState(Bundle outState) { |
| 141 | super.onSaveInstanceState(outState); |
| 142 | |
RoboErik | a60657d | 2011-07-20 16:06:55 -0700 | [diff] [blame] | 143 | long time = getSelectedTimeInMillis(); |
| 144 | if (time != -1) { |
| 145 | outState.putLong(BUNDLE_KEY_RESTORE_TIME, time); |
| 146 | } |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 147 | } |
| 148 | |
| 149 | @Override |
| 150 | public void onPause() { |
| 151 | super.onPause(); |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 152 | DayView view = (DayView) mViewSwitcher.getCurrentView(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 153 | view.cleanup(); |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 154 | view = (DayView) mViewSwitcher.getNextView(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 155 | view.cleanup(); |
| 156 | mEventLoader.stopBackgroundThread(); |
Isaac Katzenelson | 0a30ef1 | 2012-04-12 11:33:39 -0700 | [diff] [blame] | 157 | |
| 158 | // Stop events cross-fade animation |
| 159 | view.stopEventsAnimation(); |
| 160 | ((DayView) mViewSwitcher.getNextView()).stopEventsAnimation(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 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 | |
RoboErik | 5b87252 | 2011-10-03 17:24:50 -0700 | [diff] [blame] | 173 | private void goTo(Time goToTime, boolean ignoreTime, boolean animateToday) { |
Michael Chan | 3458a17 | 2010-07-13 17:58:21 -0700 | [diff] [blame] | 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 | |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 180 | DayView currentView = (DayView) mViewSwitcher.getCurrentView(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 181 | |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 182 | // How does goTo time compared to what's already displaying? |
Michael Chan | 487552b | 2010-07-21 03:56:08 -0700 | [diff] [blame] | 183 | int diff = currentView.compareToVisibleTimeRange(goToTime); |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 184 | |
| 185 | if (diff == 0) { |
| 186 | // In visible range. No need to switch view |
RoboErik | 5b87252 | 2011-10-03 17:24:50 -0700 | [diff] [blame] | 187 | currentView.setSelected(goToTime, ignoreTime, animateToday); |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 188 | } else { |
| 189 | // Figure out which way to animate |
Michael Chan | 46a8b11 | 2010-12-14 16:36:27 -0800 | [diff] [blame] | 190 | if (diff > 0) { |
| 191 | mViewSwitcher.setInAnimation(mInAnimationForward); |
| 192 | mViewSwitcher.setOutAnimation(mOutAnimationForward); |
| 193 | } else { |
| 194 | mViewSwitcher.setInAnimation(mInAnimationBackward); |
| 195 | mViewSwitcher.setOutAnimation(mOutAnimationBackward); |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 196 | } |
| 197 | |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 198 | DayView next = (DayView) mViewSwitcher.getNextView(); |
Michael Chan | 46a8b11 | 2010-12-14 16:36:27 -0800 | [diff] [blame] | 199 | if (ignoreTime) { |
| 200 | next.setFirstVisibleHour(currentView.getFirstVisibleHour()); |
| 201 | } |
| 202 | |
RoboErik | 5b87252 | 2011-10-03 17:24:50 -0700 | [diff] [blame] | 203 | next.setSelected(goToTime, ignoreTime, animateToday); |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 204 | next.reloadEvents(); |
| 205 | mViewSwitcher.showNext(); |
| 206 | next.requestFocus(); |
Erik | eaafa2b | 2010-12-23 14:30:37 -0800 | [diff] [blame] | 207 | next.updateTitle(); |
Michael Chan | d9c9a54 | 2011-12-06 18:20:17 -0800 | [diff] [blame] | 208 | next.restartCurrentTimeUpdates(); |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 209 | } |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 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() { |
RoboErik | a60657d | 2011-07-20 16:06:55 -0700 | [diff] [blame] | 220 | if (mViewSwitcher == null) { |
| 221 | return -1; |
| 222 | } |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 223 | DayView view = (DayView) mViewSwitcher.getCurrentView(); |
RoboErik | a60657d | 2011-07-20 16:06:55 -0700 | [diff] [blame] | 224 | if (view == null) { |
| 225 | return -1; |
| 226 | } |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 227 | return view.getSelectedTimeInMillis(); |
| 228 | } |
| 229 | |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 230 | public void eventsChanged() { |
Michael Chan | e6131a5 | 2010-10-28 19:06:14 -0700 | [diff] [blame] | 231 | if (mViewSwitcher == null) { |
| 232 | return; |
| 233 | } |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 234 | DayView view = (DayView) mViewSwitcher.getCurrentView(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 235 | view.clearCachedEvents(); |
| 236 | view.reloadEvents(); |
Michael Chan | 03f5c96 | 2011-01-11 13:23:17 -0800 | [diff] [blame] | 237 | |
| 238 | view = (DayView) mViewSwitcher.getNextView(); |
| 239 | view.clearCachedEvents(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 240 | } |
| 241 | |
| 242 | Event getSelectedEvent() { |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 243 | DayView view = (DayView) mViewSwitcher.getCurrentView(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 244 | return view.getSelectedEvent(); |
| 245 | } |
| 246 | |
| 247 | boolean isEventSelected() { |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 248 | DayView view = (DayView) mViewSwitcher.getCurrentView(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 249 | return view.isEventSelected(); |
| 250 | } |
| 251 | |
| 252 | Event getNewEvent() { |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 253 | DayView view = (DayView) mViewSwitcher.getCurrentView(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 254 | return view.getNewEvent(); |
| 255 | } |
| 256 | |
Michael Chan | d190418 | 2010-07-27 13:23:47 -0700 | [diff] [blame] | 257 | public DayView getNextView() { |
| 258 | return (DayView) mViewSwitcher.getNextView(); |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 259 | } |
| 260 | |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 261 | public long getSupportedEventTypes() { |
Erik | 954c871 | 2010-08-06 10:12:34 -0700 | [diff] [blame] | 262 | return EventType.GO_TO | EventType.EVENTS_CHANGED; |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 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 |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 269 | // TODO support select message |
RoboErik | 5b87252 | 2011-10-03 17:24:50 -0700 | [diff] [blame] | 270 | goTo(msg.selectedTime, (msg.extraLong & CalendarController.EXTRA_GOTO_DATE) != 0, |
| 271 | (msg.extraLong & CalendarController.EXTRA_GOTO_TODAY) != 0); |
Erik | 954c871 | 2010-08-06 10:12:34 -0700 | [diff] [blame] | 272 | } else if (msg.eventType == EventType.EVENTS_CHANGED) { |
| 273 | eventsChanged(); |
Michael Chan | 83b0fe3 | 2010-07-08 16:46:26 -0700 | [diff] [blame] | 274 | } |
| 275 | } |
Michael Chan | ef1a51d | 2010-07-02 13:57:44 -0700 | [diff] [blame] | 276 | } |