Home | History | Annotate | Download | only in date
      1 /*
      2  * Copyright (C) 2013 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.datetimepicker.date;
     18 
     19 import android.annotation.SuppressLint;
     20 import android.content.Context;
     21 import android.text.format.Time;
     22 import android.view.View;
     23 import android.view.ViewGroup;
     24 import android.widget.AbsListView.LayoutParams;
     25 import android.widget.BaseAdapter;
     26 
     27 import com.android.datetimepicker.date.MonthView.OnDayClickListener;
     28 
     29 import java.util.Calendar;
     30 import java.util.HashMap;
     31 
     32 /**
     33  * An adapter for a list of {@link MonthView} items.
     34  */
     35 public abstract class MonthAdapter extends BaseAdapter implements OnDayClickListener {
     36 
     37     private static final String TAG = "SimpleMonthAdapter";
     38 
     39     private final Context mContext;
     40     protected final DatePickerController mController;
     41 
     42     private CalendarDay mSelectedDay;
     43 
     44     protected static int WEEK_7_OVERHANG_HEIGHT = 7;
     45     protected static final int MONTHS_IN_YEAR = 12;
     46 
     47     /**
     48      * A convenience class to represent a specific date.
     49      */
     50     public static class CalendarDay {
     51         private Calendar calendar;
     52         private Time time;
     53         int year;
     54         int month;
     55         int day;
     56 
     57         public CalendarDay() {
     58             setTime(System.currentTimeMillis());
     59         }
     60 
     61         public CalendarDay(long timeInMillis) {
     62             setTime(timeInMillis);
     63         }
     64 
     65         public CalendarDay(Calendar calendar) {
     66             year = calendar.get(Calendar.YEAR);
     67             month = calendar.get(Calendar.MONTH);
     68             day = calendar.get(Calendar.DAY_OF_MONTH);
     69         }
     70 
     71         public CalendarDay(int year, int month, int day) {
     72             setDay(year, month, day);
     73         }
     74 
     75         public void set(CalendarDay date) {
     76             year = date.year;
     77             month = date.month;
     78             day = date.day;
     79         }
     80 
     81         public void setDay(int year, int month, int day) {
     82             this.year = year;
     83             this.month = month;
     84             this.day = day;
     85         }
     86 
     87         public synchronized void setJulianDay(int julianDay) {
     88             if (time == null) {
     89                 time = new Time();
     90             }
     91             time.setJulianDay(julianDay);
     92             setTime(time.toMillis(false));
     93         }
     94 
     95         private void setTime(long timeInMillis) {
     96             if (calendar == null) {
     97                 calendar = Calendar.getInstance();
     98             }
     99             calendar.setTimeInMillis(timeInMillis);
    100             month = calendar.get(Calendar.MONTH);
    101             year = calendar.get(Calendar.YEAR);
    102             day = calendar.get(Calendar.DAY_OF_MONTH);
    103         }
    104 
    105         public int getYear() {
    106             return year;
    107         }
    108 
    109         public int getMonth() {
    110             return month;
    111         }
    112 
    113         public int getDay() {
    114             return day;
    115         }
    116     }
    117 
    118     public MonthAdapter(Context context,
    119             DatePickerController controller) {
    120         mContext = context;
    121         mController = controller;
    122         init();
    123         setSelectedDay(mController.getSelectedDay());
    124     }
    125 
    126     /**
    127      * Updates the selected day and related parameters.
    128      *
    129      * @param day The day to highlight
    130      */
    131     public void setSelectedDay(CalendarDay day) {
    132         mSelectedDay = day;
    133         notifyDataSetChanged();
    134     }
    135 
    136     public CalendarDay getSelectedDay() {
    137         return mSelectedDay;
    138     }
    139 
    140     /**
    141      * Set up the gesture detector and selected time
    142      */
    143     protected void init() {
    144         mSelectedDay = new CalendarDay(System.currentTimeMillis());
    145     }
    146 
    147     @Override
    148     public int getCount() {
    149         return ((mController.getMaxYear() - mController.getMinYear()) + 1) * MONTHS_IN_YEAR;
    150     }
    151 
    152     @Override
    153     public Object getItem(int position) {
    154         return null;
    155     }
    156 
    157     @Override
    158     public long getItemId(int position) {
    159         return position;
    160     }
    161 
    162     @Override
    163     public boolean hasStableIds() {
    164         return true;
    165     }
    166 
    167     @SuppressLint("NewApi")
    168     @SuppressWarnings("unchecked")
    169     @Override
    170     public View getView(int position, View convertView, ViewGroup parent) {
    171         MonthView v;
    172         HashMap<String, Integer> drawingParams = null;
    173         if (convertView != null) {
    174             v = (MonthView) convertView;
    175             // We store the drawing parameters in the view so it can be recycled
    176             drawingParams = (HashMap<String, Integer>) v.getTag();
    177         } else {
    178             v = createMonthView(mContext);
    179             // Set up the new view
    180             LayoutParams params = new LayoutParams(
    181                     LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    182             v.setLayoutParams(params);
    183             v.setClickable(true);
    184             v.setOnDayClickListener(this);
    185         }
    186         if (drawingParams == null) {
    187             drawingParams = new HashMap<String, Integer>();
    188         }
    189         drawingParams.clear();
    190 
    191         final int month = position % MONTHS_IN_YEAR;
    192         final int year = position / MONTHS_IN_YEAR + mController.getMinYear();
    193 
    194         int selectedDay = -1;
    195         if (isSelectedDayInMonth(year, month)) {
    196             selectedDay = mSelectedDay.day;
    197         }
    198 
    199         // Invokes requestLayout() to ensure that the recycled view is set with the appropriate
    200         // height/number of weeks before being displayed.
    201         v.reuse();
    202 
    203         drawingParams.put(MonthView.VIEW_PARAMS_SELECTED_DAY, selectedDay);
    204         drawingParams.put(MonthView.VIEW_PARAMS_YEAR, year);
    205         drawingParams.put(MonthView.VIEW_PARAMS_MONTH, month);
    206         drawingParams.put(MonthView.VIEW_PARAMS_WEEK_START, mController.getFirstDayOfWeek());
    207         v.setMonthParams(drawingParams);
    208         v.invalidate();
    209         return v;
    210     }
    211 
    212     public abstract MonthView createMonthView(Context context);
    213 
    214     private boolean isSelectedDayInMonth(int year, int month) {
    215         return mSelectedDay.year == year && mSelectedDay.month == month;
    216     }
    217 
    218 
    219     @Override
    220     public void onDayClick(MonthView view, CalendarDay day) {
    221         if (day != null) {
    222             onDayTapped(day);
    223         }
    224     }
    225 
    226     /**
    227      * Maintains the same hour/min/sec but moves the day to the tapped day.
    228      *
    229      * @param day The day that was tapped
    230      */
    231     protected void onDayTapped(CalendarDay day) {
    232         mController.tryVibrate();
    233         mController.onDayOfMonthSelected(day.year, day.month, day.day);
    234         setSelectedDay(day);
    235     }
    236 }
    237