SimpleWeeksAdapter.java revision c485b45ef36fe103428b50cef399ba199c57b385
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.month; 18 19// TODO Remove calendar imports when the required methods have been 20// refactored into the public api 21import com.android.calendar.CalendarController; 22import com.android.calendar.Utils; 23 24import android.content.Context; 25import android.text.format.Time; 26import android.util.Log; 27import android.view.GestureDetector; 28import android.view.MotionEvent; 29import android.view.View; 30import android.view.View.OnTouchListener; 31import android.view.ViewGroup; 32import android.widget.AbsListView.LayoutParams; 33import android.widget.BaseAdapter; 34 35import java.util.HashMap; 36import java.util.Locale; 37 38import libcore.icu.LocaleData; 39 40/** 41 * <p> 42 * This is a specialized adapter for creating a list of weeks with selectable 43 * days. It can be configured to display the week number, start the week on a 44 * given day, show a reduced number of days, or display an arbitrary number of 45 * weeks at a time. See {@link SimpleDayPickerFragment} for usage. 46 * </p> 47 */ 48public class SimpleWeeksAdapter extends BaseAdapter implements OnTouchListener { 49 50 private static final String TAG = "MonthByWeek"; 51 52 /** 53 * The number of weeks to display at a time. 54 */ 55 public static final String WEEK_PARAMS_NUM_WEEKS = "num_weeks"; 56 /** 57 * Which month should be in focus currently. 58 */ 59 public static final String WEEK_PARAMS_FOCUS_MONTH = "focus_month"; 60 /** 61 * Whether the week number should be shown. Non-zero to show them. 62 */ 63 public static final String WEEK_PARAMS_SHOW_WEEK = "week_numbers"; 64 /** 65 * Which day the week should start on. {@link Time#SUNDAY} through 66 * {@link Time#SATURDAY}. 67 */ 68 public static final String WEEK_PARAMS_WEEK_START = "week_start"; 69 /** 70 * The Julian day to highlight as selected. 71 */ 72 public static final String WEEK_PARAMS_JULIAN_DAY = "selected_day"; 73 /** 74 * How many days of the week to display [1-7]. 75 */ 76 public static final String WEEK_PARAMS_DAYS_PER_WEEK = "days_per_week"; 77 78 protected static final int WEEK_COUNT = CalendarController.MAX_CALENDAR_WEEK 79 - CalendarController.MIN_CALENDAR_WEEK; 80 protected static int DEFAULT_NUM_WEEKS = 6; 81 protected static int DEFAULT_MONTH_FOCUS = 0; 82 protected static int DEFAULT_DAYS_PER_WEEK = 7; 83 protected static int DEFAULT_WEEK_HEIGHT = 32; 84 protected static int WEEK_7_OVERHANG_HEIGHT = 7; 85 86 protected static float mScale = 0; 87 protected Context mContext; 88 // The day to highlight as selected 89 protected Time mSelectedDay; 90 // The week since 1970 that the selected day is in 91 protected int mSelectedWeek; 92 protected int mFirstDayOfWeek = LocaleData.get(Locale.getDefault()).firstDayOfWeek - 1; 93 protected boolean mShowWeekNumber = false; 94 protected GestureDetector mGestureDetector; 95 protected int mNumWeeks = DEFAULT_NUM_WEEKS; 96 protected int mDaysPerWeek = DEFAULT_DAYS_PER_WEEK; 97 protected int mFocusMonth = DEFAULT_MONTH_FOCUS; 98 99 public SimpleWeeksAdapter(Context context, HashMap<String, Integer> params) { 100 mContext = context; 101 102 103 if (mScale == 0) { 104 mScale = context.getResources().getDisplayMetrics().density; 105 if (mScale != 1) { 106 WEEK_7_OVERHANG_HEIGHT *= mScale; 107 } 108 } 109 init(); 110 updateParams(params); 111 } 112 113 /** 114 * Set up the gesture detector and selected time 115 */ 116 protected void init() { 117 mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener()); 118 mSelectedDay = new Time(); 119 mSelectedDay.setToNow(); 120 } 121 122 /** 123 * Parse the parameters and set any necessary fields. See 124 * {@link #WEEK_PARAMS_NUM_WEEKS} for parameter details. 125 * 126 * @param params A list of parameters for this adapter 127 */ 128 public void updateParams(HashMap<String, Integer> params) { 129 if (params == null) { 130 Log.e(TAG, "WeekParameters are null! Cannot update adapter."); 131 return; 132 } 133 if (params.containsKey(WEEK_PARAMS_FOCUS_MONTH)) { 134 mFocusMonth = params.get(WEEK_PARAMS_FOCUS_MONTH); 135 } 136 if (params.containsKey(WEEK_PARAMS_FOCUS_MONTH)) { 137 mNumWeeks = params.get(WEEK_PARAMS_NUM_WEEKS); 138 } 139 if (params.containsKey(WEEK_PARAMS_SHOW_WEEK)) { 140 mShowWeekNumber = params.get(WEEK_PARAMS_SHOW_WEEK) != 0; 141 } 142 if (params.containsKey(WEEK_PARAMS_WEEK_START)) { 143 mFirstDayOfWeek = params.get(WEEK_PARAMS_WEEK_START); 144 } 145 if (params.containsKey(WEEK_PARAMS_JULIAN_DAY)) { 146 int julianDay = params.get(WEEK_PARAMS_JULIAN_DAY); 147 mSelectedDay.setJulianDay(julianDay); 148 mSelectedWeek = Utils.getWeeksSinceEpochFromJulianDay(julianDay, mFirstDayOfWeek); 149 } 150 if (params.containsKey(WEEK_PARAMS_DAYS_PER_WEEK)) { 151 mDaysPerWeek = params.get(WEEK_PARAMS_DAYS_PER_WEEK); 152 } 153 refresh(); 154 } 155 156 /** 157 * Updates the selected day and related parameters. 158 * 159 * @param selectedTime The time to highlight 160 */ 161 public void setSelectedDay(Time selectedTime) { 162 mSelectedDay.set(selectedTime); 163 long millis = mSelectedDay.normalize(true); 164 mSelectedWeek = Utils.getWeeksSinceEpochFromJulianDay( 165 Time.getJulianDay(millis, mSelectedDay.gmtoff), mFirstDayOfWeek); 166 notifyDataSetChanged(); 167 } 168 169 /** 170 * Returns the currently highlighted day 171 * 172 * @return 173 */ 174 public Time getSelectedDay() { 175 return mSelectedDay; 176 } 177 178 /** 179 * updates any config options that may have changed and refreshes the view 180 */ 181 protected void refresh() { 182 notifyDataSetChanged(); 183 } 184 185 @Override 186 public int getCount() { 187 return WEEK_COUNT; 188 } 189 190 @Override 191 public Object getItem(int position) { 192 return null; 193 } 194 195 @Override 196 public long getItemId(int position) { 197 return position; 198 } 199 200 @SuppressWarnings("unchecked") 201 @Override 202 public View getView(int position, View convertView, ViewGroup parent) { 203 SimpleWeekView v; 204 HashMap<String, Integer> drawingParams = null; 205 if (convertView != null) { 206 v = (SimpleWeekView) convertView; 207 // We store the drawing parameters in the view so it can be recycled 208 drawingParams = (HashMap<String, Integer>) v.getTag(); 209 } else { 210 v = new SimpleWeekView(mContext); 211 // Set up the new view 212 LayoutParams params = new LayoutParams( 213 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 214 v.setLayoutParams(params); 215 v.setClickable(true); 216 v.setOnTouchListener(this); 217 } 218 if (drawingParams == null) { 219 drawingParams = new HashMap<String, Integer>(); 220 } 221 drawingParams.clear(); 222 223 int selectedDay = -1; 224 if (mSelectedWeek == position) { 225 selectedDay = mSelectedDay.weekDay; 226 } 227 228 // pass in all the view parameters 229 drawingParams.put(SimpleWeekView.VIEW_PARAMS_HEIGHT, 230 (parent.getHeight() - WEEK_7_OVERHANG_HEIGHT) / mNumWeeks); 231 drawingParams.put(SimpleWeekView.VIEW_PARAMS_SELECTED_DAY, selectedDay); 232 drawingParams.put(SimpleWeekView.VIEW_PARAMS_SHOW_WK_NUM, mShowWeekNumber ? 1 : 0); 233 drawingParams.put(SimpleWeekView.VIEW_PARAMS_WEEK_START, mFirstDayOfWeek); 234 drawingParams.put(SimpleWeekView.VIEW_PARAMS_NUM_DAYS, mDaysPerWeek); 235 drawingParams.put(SimpleWeekView.VIEW_PARAMS_WEEK, position); 236 drawingParams.put(SimpleWeekView.VIEW_PARAMS_FOCUS_MONTH, mFocusMonth); 237 v.setWeekParams(drawingParams, mSelectedDay.timezone); 238 v.invalidate(); 239 240 return v; 241 } 242 243 /** 244 * Changes which month is in focus and updates the view. 245 * 246 * @param month The month to show as in focus [0-11] 247 */ 248 public void updateFocusMonth(int month) { 249 mFocusMonth = month; 250 notifyDataSetChanged(); 251 } 252 253 @Override 254 public boolean onTouch(View v, MotionEvent event) { 255 if (mGestureDetector.onTouchEvent(event)) { 256 SimpleWeekView view = (SimpleWeekView) v; 257 Time day = ((SimpleWeekView)v).getDayFromLocation(event.getX()); 258 if (Log.isLoggable(TAG, Log.DEBUG)) { 259 Log.d(TAG, "Touched day at Row=" + view.mWeek + " day=" + day.toString()); 260 } 261 if (day != null) { 262 onDayTapped(day); 263 } 264 return true; 265 } 266 return false; 267 } 268 269 /** 270 * Maintains the same hour/min/sec but moves the day to the tapped day. 271 * 272 * @param day The day that was tapped 273 */ 274 protected void onDayTapped(Time day) { 275 day.hour = mSelectedDay.hour; 276 day.minute = mSelectedDay.minute; 277 day.second = mSelectedDay.second; 278 setSelectedDay(day); 279 } 280 281 282 /** 283 * This is here so we can identify single tap events and set the selected 284 * day correctly 285 */ 286 protected class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener { 287 @Override 288 public boolean onSingleTapUp(MotionEvent e) { 289 return true; 290 } 291 } 292} 293