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