1981874e61ecf29a96a77601a3172b2503b6537eeErik/* 2981874e61ecf29a96a77601a3172b2503b6537eeErik * Copyright (C) 2010 The Android Open Source Project 3981874e61ecf29a96a77601a3172b2503b6537eeErik * 4981874e61ecf29a96a77601a3172b2503b6537eeErik * Licensed under the Apache License, Version 2.0 (the "License"); 5981874e61ecf29a96a77601a3172b2503b6537eeErik * you may not use this file except in compliance with the License. 6981874e61ecf29a96a77601a3172b2503b6537eeErik * You may obtain a copy of the License at 7981874e61ecf29a96a77601a3172b2503b6537eeErik * 8981874e61ecf29a96a77601a3172b2503b6537eeErik * http://www.apache.org/licenses/LICENSE-2.0 9981874e61ecf29a96a77601a3172b2503b6537eeErik * 10981874e61ecf29a96a77601a3172b2503b6537eeErik * Unless required by applicable law or agreed to in writing, software 11981874e61ecf29a96a77601a3172b2503b6537eeErik * distributed under the License is distributed on an "AS IS" BASIS, 12981874e61ecf29a96a77601a3172b2503b6537eeErik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13981874e61ecf29a96a77601a3172b2503b6537eeErik * See the License for the specific language governing permissions and 14981874e61ecf29a96a77601a3172b2503b6537eeErik * limitations under the License. 15981874e61ecf29a96a77601a3172b2503b6537eeErik */ 16981874e61ecf29a96a77601a3172b2503b6537eeErik 17981874e61ecf29a96a77601a3172b2503b6537eeErikpackage com.android.calendar.month; 18981874e61ecf29a96a77601a3172b2503b6537eeErik 19981874e61ecf29a96a77601a3172b2503b6537eeErikimport android.content.Context; 203553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.content.res.Configuration; 21981874e61ecf29a96a77601a3172b2503b6537eeErikimport android.text.format.Time; 22981874e61ecf29a96a77601a3172b2503b6537eeErikimport android.util.Log; 2359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelsonimport android.view.GestureDetector; 2459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelsonimport android.view.MotionEvent; 253553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.view.View; 2659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelsonimport android.view.ViewConfiguration; 273553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.view.ViewGroup; 283553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.widget.AbsListView.LayoutParams; 29981874e61ecf29a96a77601a3172b2503b6537eeErik 3059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelsonimport com.android.calendar.CalendarController; 3159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelsonimport com.android.calendar.CalendarController.EventType; 3259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelsonimport com.android.calendar.CalendarController.ViewType; 3359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelsonimport com.android.calendar.Event; 3459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelsonimport com.android.calendar.R; 3559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelsonimport com.android.calendar.Utils; 3659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson 37981874e61ecf29a96a77601a3172b2503b6537eeErikimport java.util.ArrayList; 3882b318634af1b6594e60cfd1f2df4d3845f80587Erikimport java.util.HashMap; 39981874e61ecf29a96a77601a3172b2503b6537eeErik 40e21674aefc9755ba519dfc5b3ff4348be4814903Erikpublic class MonthByWeekAdapter extends SimpleWeeksAdapter { 413553621c824afe1f3eacbe8555678005ca1264a1Erik private static final String TAG = "MonthByWeek"; 423553621c824afe1f3eacbe8555678005ca1264a1Erik 433553621c824afe1f3eacbe8555678005ca1264a1Erik public static final String WEEK_PARAMS_IS_MINI = "mini_month"; 4482b318634af1b6594e60cfd1f2df4d3845f80587Erik protected static int DEFAULT_QUERY_DAYS = 7 * 8; // 8 weeks 455b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private static final long ANIMATE_TODAY_TIMEOUT = 1000; 46981874e61ecf29a96a77601a3172b2503b6537eeErik 4782b318634af1b6594e60cfd1f2df4d3845f80587Erik protected CalendarController mController; 48981874e61ecf29a96a77601a3172b2503b6537eeErik protected String mHomeTimeZone; 4982b318634af1b6594e60cfd1f2df4d3845f80587Erik protected Time mTempTime; 5082b318634af1b6594e60cfd1f2df4d3845f80587Erik protected Time mToday; 5182b318634af1b6594e60cfd1f2df4d3845f80587Erik protected int mFirstJulianDay; 5240bcd101b212c9863c3110c05a487a7ae6ebc3caErik protected int mQueryDays; 533553621c824afe1f3eacbe8555678005ca1264a1Erik protected boolean mIsMiniMonth = true; 543553621c824afe1f3eacbe8555678005ca1264a1Erik protected int mOrientation = Configuration.ORIENTATION_LANDSCAPE; 5559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson private final boolean mShowAgendaWithMonth; 56981874e61ecf29a96a77601a3172b2503b6537eeErik 5782b318634af1b6594e60cfd1f2df4d3845f80587Erik protected ArrayList<ArrayList<Event>> mEventDayList = new ArrayList<ArrayList<Event>>(); 58092caec951caa0fabcd51729678e3ddcd6ca2f03RoboErik protected ArrayList<Event> mEvents = null; 59981874e61ecf29a96a77601a3172b2503b6537eeErik 605b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private boolean mAnimateToday = false; 615b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik private long mAnimateTime = 0; 625b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 6359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson MonthWeekEventsView mClickedView; 6459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson MonthWeekEventsView mSingleTapUpView; 6559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson 6659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson float mClickedXLocation; // Used to find which day was clicked 6759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson long mClickTime; // Used to calculate minimum click animation time 6859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Used to insure minimal time for seeing the click animation before switching views 6959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson private static final int mOnTapDelay = 100; 7059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Minimal time for a down touch action before stating the click animation, this insures that 7159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // there is no click animation on flings 7259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson private static int mOnDownDelay; 7359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson private static int mTotalClickDelay; 7459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Minimal distance to move the finger in order to cancel the click animation 7559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson private static float mMovedPixelToCancel; 7659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson 7782b318634af1b6594e60cfd1f2df4d3845f80587Erik public MonthByWeekAdapter(Context context, HashMap<String, Integer> params) { 7882b318634af1b6594e60cfd1f2df4d3845f80587Erik super(context, params); 793553621c824afe1f3eacbe8555678005ca1264a1Erik if (params.containsKey(WEEK_PARAMS_IS_MINI)) { 803553621c824afe1f3eacbe8555678005ca1264a1Erik mIsMiniMonth = params.get(WEEK_PARAMS_IS_MINI) != 0; 813553621c824afe1f3eacbe8555678005ca1264a1Erik } 826a18258975212568af7f2ce94f4044d5865a39d9Isaac Katzenelson mShowAgendaWithMonth = Utils.getConfigBool(context, R.bool.show_agenda_with_month); 8359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson ViewConfiguration vc = ViewConfiguration.get(context); 849e196e46b238e6bca1ef86c7d673807b78ab7016Michael Chan mOnDownDelay = ViewConfiguration.getTapTimeout(); 8559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mMovedPixelToCancel = vc.getScaledTouchSlop(); 8659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mTotalClickDelay = mOnDownDelay + mOnTapDelay; 8759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson 88981874e61ecf29a96a77601a3172b2503b6537eeErik } 89981874e61ecf29a96a77601a3172b2503b6537eeErik 905b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik public void animateToday() { 915b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateToday = true; 925b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateTime = System.currentTimeMillis(); 935b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 945b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik 9582b318634af1b6594e60cfd1f2df4d3845f80587Erik @Override 9682b318634af1b6594e60cfd1f2df4d3845f80587Erik protected void init() { 9782b318634af1b6594e60cfd1f2df4d3845f80587Erik super.init(); 9882b318634af1b6594e60cfd1f2df4d3845f80587Erik mController = CalendarController.getInstance(mContext); 9982b318634af1b6594e60cfd1f2df4d3845f80587Erik mHomeTimeZone = Utils.getTimeZone(mContext, null); 10082b318634af1b6594e60cfd1f2df4d3845f80587Erik mSelectedDay.switchTimezone(mHomeTimeZone); 101981874e61ecf29a96a77601a3172b2503b6537eeErik mToday = new Time(mHomeTimeZone); 102981874e61ecf29a96a77601a3172b2503b6537eeErik mToday.setToNow(); 103981874e61ecf29a96a77601a3172b2503b6537eeErik mTempTime = new Time(mHomeTimeZone); 104981874e61ecf29a96a77601a3172b2503b6537eeErik } 105981874e61ecf29a96a77601a3172b2503b6537eeErik 10682b318634af1b6594e60cfd1f2df4d3845f80587Erik private void updateTimeZones() { 10782b318634af1b6594e60cfd1f2df4d3845f80587Erik mSelectedDay.timezone = mHomeTimeZone; 10882b318634af1b6594e60cfd1f2df4d3845f80587Erik mSelectedDay.normalize(true); 10982b318634af1b6594e60cfd1f2df4d3845f80587Erik mToday.timezone = mHomeTimeZone; 11082b318634af1b6594e60cfd1f2df4d3845f80587Erik mToday.setToNow(); 11182b318634af1b6594e60cfd1f2df4d3845f80587Erik mTempTime.switchTimezone(mHomeTimeZone); 11282b318634af1b6594e60cfd1f2df4d3845f80587Erik } 113981874e61ecf29a96a77601a3172b2503b6537eeErik 11440bcd101b212c9863c3110c05a487a7ae6ebc3caErik @Override 11540bcd101b212c9863c3110c05a487a7ae6ebc3caErik public void setSelectedDay(Time selectedTime) { 11640bcd101b212c9863c3110c05a487a7ae6ebc3caErik mSelectedDay.set(selectedTime); 11740bcd101b212c9863c3110c05a487a7ae6ebc3caErik long millis = mSelectedDay.normalize(true); 11840bcd101b212c9863c3110c05a487a7ae6ebc3caErik mSelectedWeek = Utils.getWeeksSinceEpochFromJulianDay( 11940bcd101b212c9863c3110c05a487a7ae6ebc3caErik Time.getJulianDay(millis, mSelectedDay.gmtoff), mFirstDayOfWeek); 12040bcd101b212c9863c3110c05a487a7ae6ebc3caErik notifyDataSetChanged(); 12140bcd101b212c9863c3110c05a487a7ae6ebc3caErik } 12240bcd101b212c9863c3110c05a487a7ae6ebc3caErik 12382b318634af1b6594e60cfd1f2df4d3845f80587Erik public void setEvents(int firstJulianDay, int numDays, ArrayList<Event> events) { 1243553621c824afe1f3eacbe8555678005ca1264a1Erik if (mIsMiniMonth) { 1253553621c824afe1f3eacbe8555678005ca1264a1Erik if (Log.isLoggable(TAG, Log.ERROR)) { 1263553621c824afe1f3eacbe8555678005ca1264a1Erik Log.e(TAG, "Attempted to set events for mini view. Events only supported in full" 1273553621c824afe1f3eacbe8555678005ca1264a1Erik + " view."); 1283553621c824afe1f3eacbe8555678005ca1264a1Erik } 1293553621c824afe1f3eacbe8555678005ca1264a1Erik return; 1303553621c824afe1f3eacbe8555678005ca1264a1Erik } 131092caec951caa0fabcd51729678e3ddcd6ca2f03RoboErik mEvents = events; 13282b318634af1b6594e60cfd1f2df4d3845f80587Erik mFirstJulianDay = firstJulianDay; 13340bcd101b212c9863c3110c05a487a7ae6ebc3caErik mQueryDays = numDays; 13440bcd101b212c9863c3110c05a487a7ae6ebc3caErik // Create a new list, this is necessary since the weeks are referencing 13540bcd101b212c9863c3110c05a487a7ae6ebc3caErik // pieces of the old list 13640bcd101b212c9863c3110c05a487a7ae6ebc3caErik ArrayList<ArrayList<Event>> eventDayList = new ArrayList<ArrayList<Event>>(); 13740bcd101b212c9863c3110c05a487a7ae6ebc3caErik for (int i = 0; i < numDays; i++) { 13840bcd101b212c9863c3110c05a487a7ae6ebc3caErik eventDayList.add(new ArrayList<Event>()); 139981874e61ecf29a96a77601a3172b2503b6537eeErik } 140981874e61ecf29a96a77601a3172b2503b6537eeErik 141981874e61ecf29a96a77601a3172b2503b6537eeErik if (events == null || events.size() == 0) { 142981874e61ecf29a96a77601a3172b2503b6537eeErik if(Log.isLoggable(TAG, Log.DEBUG)) { 143981874e61ecf29a96a77601a3172b2503b6537eeErik Log.d(TAG, "No events. Returning early--go schedule something fun."); 144981874e61ecf29a96a77601a3172b2503b6537eeErik } 145b331a8217f09c2d48960bc192fc1cda1e6a35faeErik mEventDayList = eventDayList; 146981874e61ecf29a96a77601a3172b2503b6537eeErik refresh(); 147981874e61ecf29a96a77601a3172b2503b6537eeErik return; 148981874e61ecf29a96a77601a3172b2503b6537eeErik } 149981874e61ecf29a96a77601a3172b2503b6537eeErik 150981874e61ecf29a96a77601a3172b2503b6537eeErik // Compute the new set of days with events 151981874e61ecf29a96a77601a3172b2503b6537eeErik for (Event event : events) { 15282b318634af1b6594e60cfd1f2df4d3845f80587Erik int startDay = event.startDay - mFirstJulianDay; 15382b318634af1b6594e60cfd1f2df4d3845f80587Erik int endDay = event.endDay - mFirstJulianDay + 1; 154981874e61ecf29a96a77601a3172b2503b6537eeErik if (startDay < numDays || endDay >= 0) { 155981874e61ecf29a96a77601a3172b2503b6537eeErik if (startDay < 0) { 156981874e61ecf29a96a77601a3172b2503b6537eeErik startDay = 0; 157981874e61ecf29a96a77601a3172b2503b6537eeErik } 158981874e61ecf29a96a77601a3172b2503b6537eeErik if (startDay > numDays) { 159981874e61ecf29a96a77601a3172b2503b6537eeErik continue; 160981874e61ecf29a96a77601a3172b2503b6537eeErik } 161981874e61ecf29a96a77601a3172b2503b6537eeErik if (endDay < 0) { 162981874e61ecf29a96a77601a3172b2503b6537eeErik continue; 163981874e61ecf29a96a77601a3172b2503b6537eeErik } 164981874e61ecf29a96a77601a3172b2503b6537eeErik if (endDay > numDays) { 165981874e61ecf29a96a77601a3172b2503b6537eeErik endDay = numDays; 166981874e61ecf29a96a77601a3172b2503b6537eeErik } 167981874e61ecf29a96a77601a3172b2503b6537eeErik for (int j = startDay; j < endDay; j++) { 16840bcd101b212c9863c3110c05a487a7ae6ebc3caErik eventDayList.get(j).add(event); 169981874e61ecf29a96a77601a3172b2503b6537eeErik } 170981874e61ecf29a96a77601a3172b2503b6537eeErik } 171981874e61ecf29a96a77601a3172b2503b6537eeErik } 172981874e61ecf29a96a77601a3172b2503b6537eeErik if(Log.isLoggable(TAG, Log.DEBUG)) { 173981874e61ecf29a96a77601a3172b2503b6537eeErik Log.d(TAG, "Processed " + events.size() + " events."); 174981874e61ecf29a96a77601a3172b2503b6537eeErik } 17540bcd101b212c9863c3110c05a487a7ae6ebc3caErik mEventDayList = eventDayList; 176981874e61ecf29a96a77601a3172b2503b6537eeErik refresh(); 177981874e61ecf29a96a77601a3172b2503b6537eeErik } 178981874e61ecf29a96a77601a3172b2503b6537eeErik 1793553621c824afe1f3eacbe8555678005ca1264a1Erik @SuppressWarnings("unchecked") 1803553621c824afe1f3eacbe8555678005ca1264a1Erik @Override 1813553621c824afe1f3eacbe8555678005ca1264a1Erik public View getView(int position, View convertView, ViewGroup parent) { 1823553621c824afe1f3eacbe8555678005ca1264a1Erik if (mIsMiniMonth) { 1833553621c824afe1f3eacbe8555678005ca1264a1Erik return super.getView(position, convertView, parent); 1843553621c824afe1f3eacbe8555678005ca1264a1Erik } 1853553621c824afe1f3eacbe8555678005ca1264a1Erik MonthWeekEventsView v; 1863553621c824afe1f3eacbe8555678005ca1264a1Erik LayoutParams params = new LayoutParams( 1873553621c824afe1f3eacbe8555678005ca1264a1Erik LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 1883553621c824afe1f3eacbe8555678005ca1264a1Erik HashMap<String, Integer> drawingParams = null; 1895b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik boolean isAnimatingToday = false; 1903553621c824afe1f3eacbe8555678005ca1264a1Erik if (convertView != null) { 1913553621c824afe1f3eacbe8555678005ca1264a1Erik v = (MonthWeekEventsView) convertView; 1925b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // Checking updateToday uses the current params instead of the new 1935b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // params, so this is assuming the view is relatively stable 1945b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (mAnimateToday && v.updateToday(mSelectedDay.timezone)) { 1955b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik long currentTime = System.currentTimeMillis(); 1965b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // If it's been too long since we tried to start the animation 1975b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // don't show it. This can happen if the user stops a scroll 1985b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // before reaching today. 1995b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (currentTime - mAnimateTime > ANIMATE_TODAY_TIMEOUT) { 2005b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateToday = false; 2015b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateTime = 0; 2025b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } else { 2035b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik isAnimatingToday = true; 2045b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // There is a bug that causes invalidates to not work some 2055b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik // of the time unless we recreate the view. 2065b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik v = new MonthWeekEventsView(mContext); 2075b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2085b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } else { 2095b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik drawingParams = (HashMap<String, Integer>) v.getTag(); 2105b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 2113553621c824afe1f3eacbe8555678005ca1264a1Erik } else { 2123553621c824afe1f3eacbe8555678005ca1264a1Erik v = new MonthWeekEventsView(mContext); 2133553621c824afe1f3eacbe8555678005ca1264a1Erik } 2143553621c824afe1f3eacbe8555678005ca1264a1Erik if (drawingParams == null) { 2153553621c824afe1f3eacbe8555678005ca1264a1Erik drawingParams = new HashMap<String, Integer>(); 2163553621c824afe1f3eacbe8555678005ca1264a1Erik } 2173553621c824afe1f3eacbe8555678005ca1264a1Erik drawingParams.clear(); 2183553621c824afe1f3eacbe8555678005ca1264a1Erik 2193553621c824afe1f3eacbe8555678005ca1264a1Erik v.setLayoutParams(params); 2203553621c824afe1f3eacbe8555678005ca1264a1Erik v.setClickable(true); 2213553621c824afe1f3eacbe8555678005ca1264a1Erik v.setOnTouchListener(this); 2223553621c824afe1f3eacbe8555678005ca1264a1Erik 2233553621c824afe1f3eacbe8555678005ca1264a1Erik int selectedDay = -1; 2243553621c824afe1f3eacbe8555678005ca1264a1Erik if (mSelectedWeek == position) { 2253553621c824afe1f3eacbe8555678005ca1264a1Erik selectedDay = mSelectedDay.weekDay; 2263553621c824afe1f3eacbe8555678005ca1264a1Erik } 2273553621c824afe1f3eacbe8555678005ca1264a1Erik 228e21674aefc9755ba519dfc5b3ff4348be4814903Erik drawingParams.put(SimpleWeekView.VIEW_PARAMS_HEIGHT, 2293bff945d29d6ef277391745cd160f3bf16b98905RoboErik (parent.getHeight() + parent.getTop()) / mNumWeeks); 230e21674aefc9755ba519dfc5b3ff4348be4814903Erik drawingParams.put(SimpleWeekView.VIEW_PARAMS_SELECTED_DAY, selectedDay); 231e21674aefc9755ba519dfc5b3ff4348be4814903Erik drawingParams.put(SimpleWeekView.VIEW_PARAMS_SHOW_WK_NUM, mShowWeekNumber ? 1 : 0); 232e21674aefc9755ba519dfc5b3ff4348be4814903Erik drawingParams.put(SimpleWeekView.VIEW_PARAMS_WEEK_START, mFirstDayOfWeek); 233e21674aefc9755ba519dfc5b3ff4348be4814903Erik drawingParams.put(SimpleWeekView.VIEW_PARAMS_NUM_DAYS, mDaysPerWeek); 234e21674aefc9755ba519dfc5b3ff4348be4814903Erik drawingParams.put(SimpleWeekView.VIEW_PARAMS_WEEK, position); 235e21674aefc9755ba519dfc5b3ff4348be4814903Erik drawingParams.put(SimpleWeekView.VIEW_PARAMS_FOCUS_MONTH, mFocusMonth); 2363553621c824afe1f3eacbe8555678005ca1264a1Erik drawingParams.put(MonthWeekEventsView.VIEW_PARAMS_ORIENTATION, mOrientation); 2373553621c824afe1f3eacbe8555678005ca1264a1Erik 2385b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik if (isAnimatingToday) { 2395b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik drawingParams.put(MonthWeekEventsView.VIEW_PARAMS_ANIMATE_TODAY, 1); 2405b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik mAnimateToday = false; 2415b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik } 24240bcd101b212c9863c3110c05a487a7ae6ebc3caErik 2435b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik v.setWeekParams(drawingParams, mSelectedDay.timezone); 2445b872523e28fc778a3fc34e7e9096ca1197c6509RoboErik sendEventsToView(v); 2453553621c824afe1f3eacbe8555678005ca1264a1Erik return v; 2463553621c824afe1f3eacbe8555678005ca1264a1Erik } 2473553621c824afe1f3eacbe8555678005ca1264a1Erik 24840bcd101b212c9863c3110c05a487a7ae6ebc3caErik private void sendEventsToView(MonthWeekEventsView v) { 24940bcd101b212c9863c3110c05a487a7ae6ebc3caErik if (mEventDayList.size() == 0) { 25040bcd101b212c9863c3110c05a487a7ae6ebc3caErik if (Log.isLoggable(TAG, Log.DEBUG)) { 25140bcd101b212c9863c3110c05a487a7ae6ebc3caErik Log.d(TAG, "No events loaded, did not pass any events to view."); 25240bcd101b212c9863c3110c05a487a7ae6ebc3caErik } 253092caec951caa0fabcd51729678e3ddcd6ca2f03RoboErik v.setEvents(null, null); 25440bcd101b212c9863c3110c05a487a7ae6ebc3caErik return; 25540bcd101b212c9863c3110c05a487a7ae6ebc3caErik } 25640bcd101b212c9863c3110c05a487a7ae6ebc3caErik int viewJulianDay = v.getFirstJulianDay(); 25740bcd101b212c9863c3110c05a487a7ae6ebc3caErik int start = viewJulianDay - mFirstJulianDay; 25840bcd101b212c9863c3110c05a487a7ae6ebc3caErik int end = start + v.mNumDays; 25940bcd101b212c9863c3110c05a487a7ae6ebc3caErik if (start < 0 || end > mEventDayList.size()) { 26040bcd101b212c9863c3110c05a487a7ae6ebc3caErik if (Log.isLoggable(TAG, Log.DEBUG)) { 26140bcd101b212c9863c3110c05a487a7ae6ebc3caErik Log.d(TAG, "Week is outside range of loaded events. viewStart: " + viewJulianDay 26240bcd101b212c9863c3110c05a487a7ae6ebc3caErik + " eventsStart: " + mFirstJulianDay); 26340bcd101b212c9863c3110c05a487a7ae6ebc3caErik } 264092caec951caa0fabcd51729678e3ddcd6ca2f03RoboErik v.setEvents(null, null); 26540bcd101b212c9863c3110c05a487a7ae6ebc3caErik return; 26640bcd101b212c9863c3110c05a487a7ae6ebc3caErik } 267092caec951caa0fabcd51729678e3ddcd6ca2f03RoboErik v.setEvents(mEventDayList.subList(start, end), mEvents); 26840bcd101b212c9863c3110c05a487a7ae6ebc3caErik } 26940bcd101b212c9863c3110c05a487a7ae6ebc3caErik 27082b318634af1b6594e60cfd1f2df4d3845f80587Erik @Override 27182b318634af1b6594e60cfd1f2df4d3845f80587Erik protected void refresh() { 272981874e61ecf29a96a77601a3172b2503b6537eeErik mFirstDayOfWeek = Utils.getFirstDayOfWeek(mContext); 273981874e61ecf29a96a77601a3172b2503b6537eeErik mShowWeekNumber = Utils.getShowWeekNumber(mContext); 274981874e61ecf29a96a77601a3172b2503b6537eeErik mHomeTimeZone = Utils.getTimeZone(mContext, null); 2753553621c824afe1f3eacbe8555678005ca1264a1Erik mOrientation = mContext.getResources().getConfiguration().orientation; 27682b318634af1b6594e60cfd1f2df4d3845f80587Erik updateTimeZones(); 277e566836781f2a653624dceee3399bef25a0ea119Erik notifyDataSetChanged(); 278981874e61ecf29a96a77601a3172b2503b6537eeErik } 279981874e61ecf29a96a77601a3172b2503b6537eeErik 280981874e61ecf29a96a77601a3172b2503b6537eeErik @Override 28182b318634af1b6594e60cfd1f2df4d3845f80587Erik protected void onDayTapped(Time day) { 28240bcd101b212c9863c3110c05a487a7ae6ebc3caErik day.timezone = mHomeTimeZone; 28340bcd101b212c9863c3110c05a487a7ae6ebc3caErik Time currTime = new Time(mHomeTimeZone); 28440bcd101b212c9863c3110c05a487a7ae6ebc3caErik currTime.set(mController.getTime()); 28540bcd101b212c9863c3110c05a487a7ae6ebc3caErik day.hour = currTime.hour; 28640bcd101b212c9863c3110c05a487a7ae6ebc3caErik day.minute = currTime.minute; 28790b01744006009ed5ca7205099523f83ced380f5Michael Chan day.allDay = false; 28840bcd101b212c9863c3110c05a487a7ae6ebc3caErik day.normalize(true); 289d52514a2b3ad91cac622537f31f5c89f5d986d08Sam Blitzstein if (mShowAgendaWithMonth || mIsMiniMonth) { 2906a18258975212568af7f2ce94f4044d5865a39d9Isaac Katzenelson // If agenda view is visible with month view , refresh the views 2916a18258975212568af7f2ce94f4044d5865a39d9Isaac Katzenelson // with the selected day's info 2926a18258975212568af7f2ce94f4044d5865a39d9Isaac Katzenelson mController.sendEvent(mContext, EventType.GO_TO, day, day, -1, 2936a18258975212568af7f2ce94f4044d5865a39d9Isaac Katzenelson ViewType.CURRENT, CalendarController.EXTRA_GOTO_DATE, null, null); 2946a18258975212568af7f2ce94f4044d5865a39d9Isaac Katzenelson } else { 2956a18258975212568af7f2ce94f4044d5865a39d9Isaac Katzenelson // Else , switch to the detailed view 2966a18258975212568af7f2ce94f4044d5865a39d9Isaac Katzenelson mController.sendEvent(mContext, EventType.GO_TO, day, day, -1, 297d52514a2b3ad91cac622537f31f5c89f5d986d08Sam Blitzstein ViewType.DETAIL, 298d52514a2b3ad91cac622537f31f5c89f5d986d08Sam Blitzstein CalendarController.EXTRA_GOTO_DATE 299fb0ec227f0d4b3108438c88a6b6d234f5e40fb5cMichael Chan | CalendarController.EXTRA_GOTO_BACK_TO_PREVIOUS, null, null); 3006a18258975212568af7f2ce94f4044d5865a39d9Isaac Katzenelson } 301981874e61ecf29a96a77601a3172b2503b6537eeErik } 302981874e61ecf29a96a77601a3172b2503b6537eeErik 30359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson @Override 30459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson public boolean onTouch(View v, MotionEvent event) { 305e5b4eee3cc4ee0bc7ef9fe402064e65ef6fb58ddMichael Chan if (!(v instanceof MonthWeekEventsView)) { 306cc272e7bb0c63c09993cb33e4c9e1c5ded75874cMichael Chan return super.onTouch(v, event); 307e5b4eee3cc4ee0bc7ef9fe402064e65ef6fb58ddMichael Chan } 308e5b4eee3cc4ee0bc7ef9fe402064e65ef6fb58ddMichael Chan 30959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson int action = event.getAction(); 31059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson 31159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Event was tapped - switch to the detailed view making sure the click animation 31259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // is done first. 31359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson if (mGestureDetector.onTouchEvent(event)) { 31459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mSingleTapUpView = (MonthWeekEventsView) v; 31559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson long delay = System.currentTimeMillis() - mClickTime; 31659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Make sure the animation is visible for at least mOnTapDelay - mOnDownDelay ms 31759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mListView.postDelayed(mDoSingleTapUp, 31859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson delay > mTotalClickDelay ? 0 : mTotalClickDelay - delay); 31959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson return true; 32059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } else { 32159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Animate a click - on down: show the selected day in the "clicked" color. 32259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // On Up/scroll/move/cancel: hide the "clicked" color. 32359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson switch (action) { 32459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson case MotionEvent.ACTION_DOWN: 32559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mClickedView = (MonthWeekEventsView)v; 32659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mClickedXLocation = event.getX(); 32759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mClickTime = System.currentTimeMillis(); 32859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mListView.postDelayed(mDoClick, mOnDownDelay); 32959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson break; 33059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson case MotionEvent.ACTION_UP: 33159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson case MotionEvent.ACTION_SCROLL: 33259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson case MotionEvent.ACTION_CANCEL: 33359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson clearClickedView((MonthWeekEventsView)v); 33459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson break; 33559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson case MotionEvent.ACTION_MOVE: 33659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // No need to cancel on vertical movement, ACTION_SCROLL will do that. 33759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson if (Math.abs(event.getX() - mClickedXLocation) > mMovedPixelToCancel) { 33859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson clearClickedView((MonthWeekEventsView)v); 33959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 34059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson break; 34159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson default: 34259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson break; 34359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 34459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 34559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Do not tell the frameworks we consumed the touch action so that fling actions can be 34659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // processed by the fragment. 34759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson return false; 34859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 34959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson 35059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson /** 35159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson * This is here so we can identify events and process them 35259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson */ 35359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson protected class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener { 35459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson @Override 35559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson public boolean onSingleTapUp(MotionEvent e) { 35659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson return true; 35759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 35859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 35959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson 36059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Clear the visual cues of the click animation and related running code. 36159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson private void clearClickedView(MonthWeekEventsView v) { 36259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mListView.removeCallbacks(mDoClick); 36359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson synchronized(v) { 36459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson v.clearClickedDay(); 36559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 36659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mClickedView = null; 36759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 36859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson 36959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Perform the tap animation in a runnable to allow a delay before showing the tap color. 37059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // This is done to prevent a click animation when a fling is done. 37159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson private final Runnable mDoClick = new Runnable() { 37259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson @Override 37359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson public void run() { 37459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson if (mClickedView != null) { 37559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson synchronized(mClickedView) { 37659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mClickedView.setClickedDay(mClickedXLocation); 37759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 37859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mClickedView = null; 37959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // This is a workaround , sometimes the top item on the listview doesn't refresh on 38059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // invalidate, so this forces a re-draw. 38159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mListView.invalidate(); 38259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 38359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 38459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson }; 38559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson 38659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // Performs the single tap operation: go to the tapped day. 38759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson // This is done in a runnable to allow the click animation to finish before switching views 38859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson private final Runnable mDoSingleTapUp = new Runnable() { 38959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson @Override 39059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson public void run() { 39159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson if (mSingleTapUpView != null) { 39259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson Time day = mSingleTapUpView.getDayFromLocation(mClickedXLocation); 39359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson if (Log.isLoggable(TAG, Log.DEBUG)) { 39459a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson Log.d(TAG, "Touched day at Row=" + mSingleTapUpView.mWeek + " day=" + day.toString()); 39559a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 39659a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson if (day != null) { 39759a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson onDayTapped(day); 39859a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 39959a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson clearClickedView(mSingleTapUpView); 40059a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson mSingleTapUpView = null; 40159a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 40259a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson } 40359a44aa4bb3fac90f7ceab65da191e7fd81905f2Isaac Katzenelson }; 404981874e61ecf29a96a77601a3172b2503b6537eeErik} 405