blob: d29b2622f88a8d5d0a86b9f1cda5727b453a95de [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.calendar.month;
// TODO Remove calendar imports when the required methods have been
// refactored into the public api
import com.android.calendar.CalendarController;
import com.android.calendar.Utils;
import android.content.Context;
import android.text.format.Time;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.widget.AbsListView.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.ListView;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Locale;
/**
* <p>
* This is a specialized adapter for creating a list of weeks with selectable
* days. It can be configured to display the week number, start the week on a
* given day, show a reduced number of days, or display an arbitrary number of
* weeks at a time. See {@link SimpleDayPickerFragment} for usage.
* </p>
*/
public class SimpleWeeksAdapter extends BaseAdapter implements OnTouchListener {
private static final String TAG = "MonthByWeek";
/**
* The number of weeks to display at a time.
*/
public static final String WEEK_PARAMS_NUM_WEEKS = "num_weeks";
/**
* Which month should be in focus currently.
*/
public static final String WEEK_PARAMS_FOCUS_MONTH = "focus_month";
/**
* Whether the week number should be shown. Non-zero to show them.
*/
public static final String WEEK_PARAMS_SHOW_WEEK = "week_numbers";
/**
* Which day the week should start on. {@link Time#SUNDAY} through
* {@link Time#SATURDAY}.
*/
public static final String WEEK_PARAMS_WEEK_START = "week_start";
/**
* The Julian day to highlight as selected.
*/
public static final String WEEK_PARAMS_JULIAN_DAY = "selected_day";
/**
* How many days of the week to display [1-7].
*/
public static final String WEEK_PARAMS_DAYS_PER_WEEK = "days_per_week";
protected static final int WEEK_COUNT = CalendarController.MAX_CALENDAR_WEEK
- CalendarController.MIN_CALENDAR_WEEK;
protected static int DEFAULT_NUM_WEEKS = 6;
protected static int DEFAULT_MONTH_FOCUS = 0;
protected static int DEFAULT_DAYS_PER_WEEK = 7;
protected static int DEFAULT_WEEK_HEIGHT = 32;
protected static int WEEK_7_OVERHANG_HEIGHT = 7;
protected static float mScale = 0;
protected Context mContext;
// The day to highlight as selected
protected Time mSelectedDay;
// The week since 1970 that the selected day is in
protected int mSelectedWeek;
// When the week starts; numbered like Time.<WEEKDAY> (e.g. SUNDAY=0).
protected int mFirstDayOfWeek;
protected boolean mShowWeekNumber = false;
protected GestureDetector mGestureDetector;
protected int mNumWeeks = DEFAULT_NUM_WEEKS;
protected int mDaysPerWeek = DEFAULT_DAYS_PER_WEEK;
protected int mFocusMonth = DEFAULT_MONTH_FOCUS;
public SimpleWeeksAdapter(Context context, HashMap<String, Integer> params) {
mContext = context;
// Get default week start based on locale, subtracting one for use with android Time.
Calendar cal = Calendar.getInstance(Locale.getDefault());
mFirstDayOfWeek = cal.getFirstDayOfWeek() - 1;
if (mScale == 0) {
mScale = context.getResources().getDisplayMetrics().density;
if (mScale != 1) {
WEEK_7_OVERHANG_HEIGHT *= mScale;
}
}
init();
updateParams(params);
}
/**
* Set up the gesture detector and selected time
*/
protected void init() {
mGestureDetector = new GestureDetector(mContext, new CalendarGestureListener());
mSelectedDay = new Time();
mSelectedDay.setToNow();
}
/**
* Parse the parameters and set any necessary fields. See
* {@link #WEEK_PARAMS_NUM_WEEKS} for parameter details.
*
* @param params A list of parameters for this adapter
*/
public void updateParams(HashMap<String, Integer> params) {
if (params == null) {
Log.e(TAG, "WeekParameters are null! Cannot update adapter.");
return;
}
if (params.containsKey(WEEK_PARAMS_FOCUS_MONTH)) {
mFocusMonth = params.get(WEEK_PARAMS_FOCUS_MONTH);
}
if (params.containsKey(WEEK_PARAMS_FOCUS_MONTH)) {
mNumWeeks = params.get(WEEK_PARAMS_NUM_WEEKS);
}
if (params.containsKey(WEEK_PARAMS_SHOW_WEEK)) {
mShowWeekNumber = params.get(WEEK_PARAMS_SHOW_WEEK) != 0;
}
if (params.containsKey(WEEK_PARAMS_WEEK_START)) {
mFirstDayOfWeek = params.get(WEEK_PARAMS_WEEK_START);
}
if (params.containsKey(WEEK_PARAMS_JULIAN_DAY)) {
int julianDay = params.get(WEEK_PARAMS_JULIAN_DAY);
mSelectedDay.setJulianDay(julianDay);
mSelectedWeek = Utils.getWeeksSinceEpochFromJulianDay(julianDay, mFirstDayOfWeek);
}
if (params.containsKey(WEEK_PARAMS_DAYS_PER_WEEK)) {
mDaysPerWeek = params.get(WEEK_PARAMS_DAYS_PER_WEEK);
}
refresh();
}
/**
* Updates the selected day and related parameters.
*
* @param selectedTime The time to highlight
*/
public void setSelectedDay(Time selectedTime) {
mSelectedDay.set(selectedTime);
long millis = mSelectedDay.normalize(true);
mSelectedWeek = Utils.getWeeksSinceEpochFromJulianDay(
Time.getJulianDay(millis, mSelectedDay.gmtoff), mFirstDayOfWeek);
notifyDataSetChanged();
}
/**
* Returns the currently highlighted day
*
* @return
*/
public Time getSelectedDay() {
return mSelectedDay;
}
/**
* updates any config options that may have changed and refreshes the view
*/
protected void refresh() {
notifyDataSetChanged();
}
@Override
public int getCount() {
return WEEK_COUNT;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@SuppressWarnings("unchecked")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
SimpleWeekView v;
HashMap<String, Integer> drawingParams = null;
if (convertView != null) {
v = (SimpleWeekView) convertView;
// We store the drawing parameters in the view so it can be recycled
drawingParams = (HashMap<String, Integer>) v.getTag();
} else {
v = new SimpleWeekView(mContext);
// Set up the new view
LayoutParams params = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
v.setLayoutParams(params);
v.setClickable(true);
v.setOnTouchListener(this);
}
if (drawingParams == null) {
drawingParams = new HashMap<String, Integer>();
}
drawingParams.clear();
int selectedDay = -1;
if (mSelectedWeek == position) {
selectedDay = mSelectedDay.weekDay;
}
// pass in all the view parameters
drawingParams.put(SimpleWeekView.VIEW_PARAMS_HEIGHT,
(parent.getHeight() - WEEK_7_OVERHANG_HEIGHT) / mNumWeeks);
drawingParams.put(SimpleWeekView.VIEW_PARAMS_SELECTED_DAY, selectedDay);
drawingParams.put(SimpleWeekView.VIEW_PARAMS_SHOW_WK_NUM, mShowWeekNumber ? 1 : 0);
drawingParams.put(SimpleWeekView.VIEW_PARAMS_WEEK_START, mFirstDayOfWeek);
drawingParams.put(SimpleWeekView.VIEW_PARAMS_NUM_DAYS, mDaysPerWeek);
drawingParams.put(SimpleWeekView.VIEW_PARAMS_WEEK, position);
drawingParams.put(SimpleWeekView.VIEW_PARAMS_FOCUS_MONTH, mFocusMonth);
v.setWeekParams(drawingParams, mSelectedDay.timezone);
v.invalidate();
return v;
}
/**
* Changes which month is in focus and updates the view.
*
* @param month The month to show as in focus [0-11]
*/
public void updateFocusMonth(int month) {
mFocusMonth = month;
notifyDataSetChanged();
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mGestureDetector.onTouchEvent(event)) {
SimpleWeekView view = (SimpleWeekView) v;
Time day = ((SimpleWeekView)v).getDayFromLocation(event.getX());
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Touched day at Row=" + view.mWeek + " day=" + day.toString());
}
if (day != null) {
onDayTapped(day);
}
return true;
}
return false;
}
/**
* Maintains the same hour/min/sec but moves the day to the tapped day.
*
* @param day The day that was tapped
*/
protected void onDayTapped(Time day) {
day.hour = mSelectedDay.hour;
day.minute = mSelectedDay.minute;
day.second = mSelectedDay.second;
setSelectedDay(day);
}
/**
* This is here so we can identify single tap events and set the selected
* day correctly
*/
protected class CalendarGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
}
ListView mListView;
public void setListView(ListView lv) {
mListView = lv;
}
}