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 final 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 DayFragment()73 public DayFragment() { 74 mSelectedDay.setToNow(); 75 } 76 DayFragment(long timeMillis, int numOfDays)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 onCreate(Bundle icicle)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 onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)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 makeView()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 onResume()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 onSaveInstanceState(Bundle outState)140 public void onSaveInstanceState(Bundle outState) { 141 super.onSaveInstanceState(outState); 142 } 143 144 @Override onPause()145 public void onPause() { 146 super.onPause(); 147 DayView view = (DayView) mViewSwitcher.getCurrentView(); 148 view.cleanup(); 149 view = (DayView) mViewSwitcher.getNextView(); 150 view.cleanup(); 151 mEventLoader.stopBackgroundThread(); 152 153 // Stop events cross-fade animation 154 view.stopEventsAnimation(); 155 ((DayView) mViewSwitcher.getNextView()).stopEventsAnimation(); 156 } 157 startProgressSpinner()158 void startProgressSpinner() { 159 // start the progress spinner 160 mProgressBar.setVisibility(View.VISIBLE); 161 } 162 stopProgressSpinner()163 void stopProgressSpinner() { 164 // stop the progress spinner 165 mProgressBar.setVisibility(View.GONE); 166 } 167 goTo(Time goToTime, boolean ignoreTime, boolean animateToday)168 private void goTo(Time goToTime, boolean ignoreTime, boolean animateToday) { 169 if (mViewSwitcher == null) { 170 // The view hasn't been set yet. Just save the time and use it later. 171 mSelectedDay.set(goToTime); 172 return; 173 } 174 175 DayView currentView = (DayView) mViewSwitcher.getCurrentView(); 176 177 // How does goTo time compared to what's already displaying? 178 int diff = currentView.compareToVisibleTimeRange(goToTime); 179 180 if (diff == 0) { 181 // In visible range. No need to switch view 182 currentView.setSelected(goToTime, ignoreTime, animateToday); 183 } else { 184 // Figure out which way to animate 185 if (diff > 0) { 186 mViewSwitcher.setInAnimation(mInAnimationForward); 187 mViewSwitcher.setOutAnimation(mOutAnimationForward); 188 } else { 189 mViewSwitcher.setInAnimation(mInAnimationBackward); 190 mViewSwitcher.setOutAnimation(mOutAnimationBackward); 191 } 192 193 DayView next = (DayView) mViewSwitcher.getNextView(); 194 if (ignoreTime) { 195 next.setFirstVisibleHour(currentView.getFirstVisibleHour()); 196 } 197 198 next.setSelected(goToTime, ignoreTime, animateToday); 199 next.reloadEvents(); 200 mViewSwitcher.showNext(); 201 next.requestFocus(); 202 next.updateTitle(); 203 next.restartCurrentTimeUpdates(); 204 } 205 } 206 207 /** 208 * Returns the selected time in milliseconds. The milliseconds are measured 209 * in UTC milliseconds from the epoch and uniquely specifies any selectable 210 * time. 211 * 212 * @return the selected time in milliseconds 213 */ getSelectedTimeInMillis()214 public long getSelectedTimeInMillis() { 215 if (mViewSwitcher == null) { 216 return -1; 217 } 218 DayView view = (DayView) mViewSwitcher.getCurrentView(); 219 if (view == null) { 220 return -1; 221 } 222 return view.getSelectedTimeInMillis(); 223 } 224 eventsChanged()225 public void eventsChanged() { 226 if (mViewSwitcher == null) { 227 return; 228 } 229 DayView view = (DayView) mViewSwitcher.getCurrentView(); 230 view.clearCachedEvents(); 231 view.reloadEvents(); 232 233 view = (DayView) mViewSwitcher.getNextView(); 234 view.clearCachedEvents(); 235 } 236 getNextView()237 public DayView getNextView() { 238 return (DayView) mViewSwitcher.getNextView(); 239 } 240 getSupportedEventTypes()241 public long getSupportedEventTypes() { 242 return EventType.GO_TO | EventType.EVENTS_CHANGED; 243 } 244 handleEvent(EventInfo msg)245 public void handleEvent(EventInfo msg) { 246 if (msg.eventType == EventType.GO_TO) { 247 // TODO support a range of time 248 // TODO support event_id 249 // TODO support select message 250 goTo(msg.selectedTime, (msg.extraLong & CalendarController.EXTRA_GOTO_DATE) != 0, 251 (msg.extraLong & CalendarController.EXTRA_GOTO_TODAY) != 0); 252 } else if (msg.eventType == EventType.EVENTS_CHANGED) { 253 eventsChanged(); 254 } 255 } 256 } 257