diff options
Diffstat (limited to 'src/com/android/calendar/month/SimpleDayPickerFragment.java')
-rw-r--r-- | src/com/android/calendar/month/SimpleDayPickerFragment.java | 612 |
1 files changed, 0 insertions, 612 deletions
diff --git a/src/com/android/calendar/month/SimpleDayPickerFragment.java b/src/com/android/calendar/month/SimpleDayPickerFragment.java deleted file mode 100644 index 2efae6a9..00000000 --- a/src/com/android/calendar/month/SimpleDayPickerFragment.java +++ /dev/null @@ -1,612 +0,0 @@ -/* - * 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; - -import com.android.calendar.R; -import com.android.calendar.Utils; - -import android.app.Activity; -import android.app.ListFragment; -import android.content.Context; -import android.content.res.Resources; -import android.database.DataSetObserver; -import android.os.Bundle; -import android.os.Handler; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.text.format.Time; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.view.accessibility.AccessibilityEvent; -import android.widget.AbsListView; -import android.widget.AbsListView.OnScrollListener; -import android.widget.ListView; -import android.widget.TextView; - -import java.util.Calendar; -import java.util.HashMap; -import java.util.Locale; - -/** - * <p> - * This displays a titled 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. By - * overriding methods and changing variables this fragment can be customized to - * easily display a month selection component in a given style. - * </p> - */ -public class SimpleDayPickerFragment extends ListFragment implements OnScrollListener { - - private static final String TAG = "MonthFragment"; - private static final String KEY_CURRENT_TIME = "current_time"; - - // Affects when the month selection will change while scrolling up - protected static final int SCROLL_HYST_WEEKS = 2; - // How long the GoTo fling animation should last - protected static final int GOTO_SCROLL_DURATION = 500; - // How long to wait after receiving an onScrollStateChanged notification - // before acting on it - protected static final int SCROLL_CHANGE_DELAY = 40; - // The number of days to display in each week - public static final int DAYS_PER_WEEK = 7; - // The size of the month name displayed above the week list - protected static final int MINI_MONTH_NAME_TEXT_SIZE = 18; - public static int LIST_TOP_OFFSET = -1; // so that the top line will be under the separator - protected int WEEK_MIN_VISIBLE_HEIGHT = 12; - protected int BOTTOM_BUFFER = 20; - protected int mSaturdayColor = 0; - protected int mSundayColor = 0; - protected int mDayNameColor = 0; - - // You can override these numbers to get a different appearance - protected int mNumWeeks = 6; - protected boolean mShowWeekNumber = false; - protected int mDaysPerWeek = 7; - - // These affect the scroll speed and feel - protected float mFriction = 1.0f; - - protected Context mContext; - protected Handler mHandler; - - protected float mMinimumFlingVelocity; - - // highlighted time - protected Time mSelectedDay = new Time(); - protected SimpleWeeksAdapter mAdapter; - protected ListView mListView; - protected ViewGroup mDayNamesHeader; - protected String[] mDayLabels; - - // disposable variable used for time calculations - protected Time mTempTime = new Time(); - - private static float mScale = 0; - // When the week starts; numbered like Time.<WEEKDAY> (e.g. SUNDAY=0). - protected int mFirstDayOfWeek; - // The first day of the focus month - protected Time mFirstDayOfMonth = new Time(); - // The first day that is visible in the view - protected Time mFirstVisibleDay = new Time(); - // The name of the month to display - protected TextView mMonthName; - // The last name announced by accessibility - protected CharSequence mPrevMonthName; - // which month should be displayed/highlighted [0-11] - protected int mCurrentMonthDisplayed; - // used for tracking during a scroll - protected long mPreviousScrollPosition; - // used for tracking which direction the view is scrolling - protected boolean mIsScrollingUp = false; - // used for tracking what state listview is in - protected int mPreviousScrollState = OnScrollListener.SCROLL_STATE_IDLE; - // used for tracking what state listview is in - protected int mCurrentScrollState = OnScrollListener.SCROLL_STATE_IDLE; - - // This causes an update of the view at midnight - protected Runnable mTodayUpdater = new Runnable() { - @Override - public void run() { - Time midnight = new Time(mFirstVisibleDay.timezone); - midnight.setToNow(); - long currentMillis = midnight.toMillis(true); - - midnight.hour = 0; - midnight.minute = 0; - midnight.second = 0; - midnight.monthDay++; - long millisToMidnight = midnight.normalize(true) - currentMillis; - mHandler.postDelayed(this, millisToMidnight); - - if (mAdapter != null) { - mAdapter.notifyDataSetChanged(); - } - } - }; - - // This allows us to update our position when a day is tapped - protected DataSetObserver mObserver = new DataSetObserver() { - @Override - public void onChanged() { - Time day = mAdapter.getSelectedDay(); - if (day.year != mSelectedDay.year || day.yearDay != mSelectedDay.yearDay) { - goTo(day.toMillis(true), true, true, false); - } - } - }; - - public SimpleDayPickerFragment(long initialTime) { - goTo(initialTime, false, true, true); - mHandler = new Handler(); - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - mContext = activity; - String tz = Time.getCurrentTimezone(); - ViewConfiguration viewConfig = ViewConfiguration.get(activity); - mMinimumFlingVelocity = viewConfig.getScaledMinimumFlingVelocity(); - - // Ensure we're in the correct time zone - mSelectedDay.switchTimezone(tz); - mSelectedDay.normalize(true); - mFirstDayOfMonth.timezone = tz; - mFirstDayOfMonth.normalize(true); - mFirstVisibleDay.timezone = tz; - mFirstVisibleDay.normalize(true); - mTempTime.timezone = tz; - - Resources res = activity.getResources(); - mSaturdayColor = res.getColor(R.color.month_saturday); - mSundayColor = res.getColor(R.color.month_sunday); - mDayNameColor = res.getColor(R.color.month_day_names_color); - - // Adjust sizes for screen density - if (mScale == 0) { - mScale = activity.getResources().getDisplayMetrics().density; - if (mScale != 1) { - WEEK_MIN_VISIBLE_HEIGHT *= mScale; - BOTTOM_BUFFER *= mScale; - LIST_TOP_OFFSET *= mScale; - } - } - setUpAdapter(); - setListAdapter(mAdapter); - } - - /** - * Creates a new adapter if necessary and sets up its parameters. Override - * this method to provide a custom adapter. - */ - protected void setUpAdapter() { - HashMap<String, Integer> weekParams = new HashMap<String, Integer>(); - weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_NUM_WEEKS, mNumWeeks); - weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_SHOW_WEEK, mShowWeekNumber ? 1 : 0); - weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_WEEK_START, mFirstDayOfWeek); - weekParams.put(SimpleWeeksAdapter.WEEK_PARAMS_JULIAN_DAY, - Time.getJulianDay(mSelectedDay.toMillis(false), mSelectedDay.gmtoff)); - if (mAdapter == null) { - mAdapter = new SimpleWeeksAdapter(getActivity(), weekParams); - mAdapter.registerDataSetObserver(mObserver); - } else { - mAdapter.updateParams(weekParams); - } - // refresh the view with the new parameters - mAdapter.notifyDataSetChanged(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - setUpListView(); - setUpHeader(); - - mMonthName = (TextView) getView().findViewById(R.id.month_name); - SimpleWeekView child = (SimpleWeekView) mListView.getChildAt(0); - if (child == null) { - return; - } - int julianDay = child.getFirstJulianDay(); - mFirstVisibleDay.setJulianDay(julianDay); - // set the title to the month of the second week - mTempTime.setJulianDay(julianDay + DAYS_PER_WEEK); - setMonthDisplayed(mTempTime, true); - } - - /** - * Sets up the strings to be used by the header. Override this method to use - * different strings or modify the view params. - */ - protected void setUpHeader() { - mDayLabels = new String[7]; - for (int i = Calendar.SUNDAY; i <= Calendar.SATURDAY; i++) { - mDayLabels[i - Calendar.SUNDAY] = DateUtils.getDayOfWeekString(i, - DateUtils.LENGTH_SHORTEST).toUpperCase(); - } - } - - /** - * Sets all the required fields for the list view. Override this method to - * set a different list view behavior. - */ - protected void setUpListView() { - // Configure the listview - mListView = getListView(); - // Transparent background on scroll - mListView.setCacheColorHint(0); - // No dividers - mListView.setDivider(null); - // Items are clickable - mListView.setItemsCanFocus(true); - // The thumb gets in the way, so disable it - mListView.setFastScrollEnabled(false); - mListView.setVerticalScrollBarEnabled(false); - mListView.setOnScrollListener(this); - mListView.setFadingEdgeLength(0); - // Make the scrolling behavior nicer - mListView.setFriction(ViewConfiguration.getScrollFriction() * mFriction); - } - - @Override - public void onResume() { - super.onResume(); - setUpAdapter(); - doResumeUpdates(); - } - - @Override - public void onPause() { - super.onPause(); - mHandler.removeCallbacks(mTodayUpdater); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - outState.putLong(KEY_CURRENT_TIME, mSelectedDay.toMillis(true)); - } - - /** - * Updates the user preference fields. Override this to use a different - * preference space. - */ - protected void doResumeUpdates() { - // Get default week start based on locale, subtracting one for use with android Time. - Calendar cal = Calendar.getInstance(Locale.getDefault()); - mFirstDayOfWeek = cal.getFirstDayOfWeek() - 1; - - mShowWeekNumber = false; - - updateHeader(); - goTo(mSelectedDay.toMillis(true), false, false, false); - mAdapter.setSelectedDay(mSelectedDay); - mTodayUpdater.run(); - } - - /** - * Fixes the day names header to provide correct spacing and updates the - * label text. Override this to set up a custom header. - */ - protected void updateHeader() { - TextView label = (TextView) mDayNamesHeader.findViewById(R.id.wk_label); - if (mShowWeekNumber) { - label.setVisibility(View.VISIBLE); - } else { - label.setVisibility(View.GONE); - } - int offset = mFirstDayOfWeek - 1; - for (int i = 1; i < 8; i++) { - label = (TextView) mDayNamesHeader.getChildAt(i); - if (i < mDaysPerWeek + 1) { - int position = (offset + i) % 7; - label.setText(mDayLabels[position]); - label.setVisibility(View.VISIBLE); - if (position == Time.SATURDAY) { - label.setTextColor(mSaturdayColor); - } else if (position == Time.SUNDAY) { - label.setTextColor(mSundayColor); - } else { - label.setTextColor(mDayNameColor); - } - } else { - label.setVisibility(View.GONE); - } - } - mDayNamesHeader.invalidate(); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View v = inflater.inflate(R.layout.month_by_week, - container, false); - mDayNamesHeader = (ViewGroup) v.findViewById(R.id.day_names); - return v; - } - - /** - * Returns the UTC millis since epoch representation of the currently - * selected time. - * - * @return - */ - public long getSelectedTime() { - return mSelectedDay.toMillis(true); - } - - /** - * This moves to the specified time in the view. If the time is not already - * in range it will move the list so that the first of the month containing - * the time is at the top of the view. If the new time is already in view - * the list will not be scrolled unless forceScroll is true. This time may - * optionally be highlighted as selected as well. - * - * @param time The time to move to - * @param animate Whether to scroll to the given time or just redraw at the - * new location - * @param setSelected Whether to set the given time as selected - * @param forceScroll Whether to recenter even if the time is already - * visible - * @return Whether or not the view animated to the new location - */ - public boolean goTo(long time, boolean animate, boolean setSelected, boolean forceScroll) { - if (time == -1) { - Log.e(TAG, "time is invalid"); - return false; - } - - // Set the selected day - if (setSelected) { - mSelectedDay.set(time); - mSelectedDay.normalize(true); - } - - // If this view isn't returned yet we won't be able to load the lists - // current position, so return after setting the selected day. - if (!isResumed()) { - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "We're not visible yet"); - } - return false; - } - - mTempTime.set(time); - long millis = mTempTime.normalize(true); - // Get the week we're going to - // TODO push Util function into Calendar public api. - int position = Utils.getWeeksSinceEpochFromJulianDay( - Time.getJulianDay(millis, mTempTime.gmtoff), mFirstDayOfWeek); - - View child; - int i = 0; - int top = 0; - // Find a child that's completely in the view - do { - child = mListView.getChildAt(i++); - if (child == null) { - break; - } - top = child.getTop(); - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "child at " + (i-1) + " has top " + top); - } - } while (top < 0); - - // Compute the first and last position visible - int firstPosition; - if (child != null) { - firstPosition = mListView.getPositionForView(child); - } else { - firstPosition = 0; - } - int lastPosition = firstPosition + mNumWeeks - 1; - if (top > BOTTOM_BUFFER) { - lastPosition--; - } - - if (setSelected) { - mAdapter.setSelectedDay(mSelectedDay); - } - - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, "GoTo position " + position); - } - // Check if the selected day is now outside of our visible range - // and if so scroll to the month that contains it - if (position < firstPosition || position > lastPosition || forceScroll) { - mFirstDayOfMonth.set(mTempTime); - mFirstDayOfMonth.monthDay = 1; - millis = mFirstDayOfMonth.normalize(true); - setMonthDisplayed(mFirstDayOfMonth, true); - position = Utils.getWeeksSinceEpochFromJulianDay( - Time.getJulianDay(millis, mFirstDayOfMonth.gmtoff), mFirstDayOfWeek); - - mPreviousScrollState = OnScrollListener.SCROLL_STATE_FLING; - if (animate) { - mListView.smoothScrollToPositionFromTop( - position, LIST_TOP_OFFSET, GOTO_SCROLL_DURATION); - return true; - } else { - mListView.setSelectionFromTop(position, LIST_TOP_OFFSET); - // Perform any after scroll operations that are needed - onScrollStateChanged(mListView, OnScrollListener.SCROLL_STATE_IDLE); - } - } else if (setSelected) { - // Otherwise just set the selection - setMonthDisplayed(mSelectedDay, true); - } - return false; - } - - /** - * Updates the title and selected month if the view has moved to a new - * month. - */ - @Override - public void onScroll( - AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { - SimpleWeekView child = (SimpleWeekView)view.getChildAt(0); - if (child == null) { - return; - } - - // Figure out where we are - long currScroll = view.getFirstVisiblePosition() * child.getHeight() - child.getBottom(); - mFirstVisibleDay.setJulianDay(child.getFirstJulianDay()); - - // If we have moved since our last call update the direction - if (currScroll < mPreviousScrollPosition) { - mIsScrollingUp = true; - } else if (currScroll > mPreviousScrollPosition) { - mIsScrollingUp = false; - } else { - return; - } - - mPreviousScrollPosition = currScroll; - mPreviousScrollState = mCurrentScrollState; - - updateMonthHighlight(mListView); - } - - /** - * Figures out if the month being shown has changed and updates the - * highlight if needed - * - * @param view The ListView containing the weeks - */ - private void updateMonthHighlight(AbsListView view) { - SimpleWeekView child = (SimpleWeekView) view.getChildAt(0); - if (child == null) { - return; - } - - // Figure out where we are - int offset = child.getBottom() < WEEK_MIN_VISIBLE_HEIGHT ? 1 : 0; - // Use some hysteresis for checking which month to highlight. This - // causes the month to transition when two full weeks of a month are - // visible. - child = (SimpleWeekView) view.getChildAt(SCROLL_HYST_WEEKS + offset); - - if (child == null) { - return; - } - - // Find out which month we're moving into - int month; - if (mIsScrollingUp) { - month = child.getFirstMonth(); - } else { - month = child.getLastMonth(); - } - - // And how it relates to our current highlighted month - int monthDiff; - if (mCurrentMonthDisplayed == 11 && month == 0) { - monthDiff = 1; - } else if (mCurrentMonthDisplayed == 0 && month == 11) { - monthDiff = -1; - } else { - monthDiff = month - mCurrentMonthDisplayed; - } - - // Only switch months if we're scrolling away from the currently - // selected month - if (monthDiff != 0) { - int julianDay = child.getFirstJulianDay(); - if (mIsScrollingUp) { - // Takes the start of the week - } else { - // Takes the start of the following week - julianDay += DAYS_PER_WEEK; - } - mTempTime.setJulianDay(julianDay); - setMonthDisplayed(mTempTime, false); - } - } - - /** - * Sets the month displayed at the top of this view based on time. Override - * to add custom events when the title is changed. - * - * @param time A day in the new focus month. - * @param updateHighlight TODO(epastern): - */ - protected void setMonthDisplayed(Time time, boolean updateHighlight) { - CharSequence oldMonth = mMonthName.getText(); - mMonthName.setText(Utils.formatMonthYear(mContext, time)); - mMonthName.invalidate(); - if (!TextUtils.equals(oldMonth, mMonthName.getText())) { - mMonthName.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); - } - mCurrentMonthDisplayed = time.month; - if (updateHighlight) { - mAdapter.updateFocusMonth(mCurrentMonthDisplayed); - } - } - - @Override - public void onScrollStateChanged(AbsListView view, int scrollState) { - // use a post to prevent re-entering onScrollStateChanged before it - // exits - mScrollStateChangedRunnable.doScrollStateChange(view, scrollState); - } - - protected ScrollStateRunnable mScrollStateChangedRunnable = new ScrollStateRunnable(); - - protected class ScrollStateRunnable implements Runnable { - private int mNewState; - - /** - * Sets up the runnable with a short delay in case the scroll state - * immediately changes again. - * - * @param view The list view that changed state - * @param scrollState The new state it changed to - */ - public void doScrollStateChange(AbsListView view, int scrollState) { - mHandler.removeCallbacks(this); - mNewState = scrollState; - mHandler.postDelayed(this, SCROLL_CHANGE_DELAY); - } - - public void run() { - mCurrentScrollState = mNewState; - if (Log.isLoggable(TAG, Log.DEBUG)) { - Log.d(TAG, - "new scroll state: " + mNewState + " old state: " + mPreviousScrollState); - } - // Fix the position after a scroll or a fling ends - if (mNewState == OnScrollListener.SCROLL_STATE_IDLE - && mPreviousScrollState != OnScrollListener.SCROLL_STATE_IDLE) { - mPreviousScrollState = mNewState; - mAdapter.updateFocusMonth(mCurrentMonthDisplayed); - } else { - mPreviousScrollState = mNewState; - } - } - } -} |