Home | History | Annotate | Download | only in dataadapter
      1 /*
      2  * Copyright (C) 2015 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.deskclock.alarms.dataadapter;
     18 
     19 import android.content.Context;
     20 import android.database.Cursor;
     21 import android.os.Bundle;
     22 import android.os.Vibrator;
     23 import android.support.v7.widget.RecyclerView;
     24 import android.view.LayoutInflater;
     25 import android.view.View;
     26 import android.view.ViewGroup;
     27 
     28 import com.android.deskclock.LogUtils;
     29 import com.android.deskclock.R;
     30 import com.android.deskclock.alarms.AlarmTimeClickHandler;
     31 import com.android.deskclock.alarms.ScrollHandler;
     32 import com.android.deskclock.provider.Alarm;
     33 import com.android.deskclock.provider.AlarmInstance;
     34 
     35 /**
     36  * Data adapter for alarm time items.
     37  */
     38 public final class AlarmTimeAdapter extends RecyclerView.Adapter<AlarmTimeViewHolder> {
     39     private static final String TAG = "CwAlarm";
     40     private static final String KEY_EXPANDED_ID = "expandedId";
     41     private static final int VIEW_TYPE_ALARM_TIME_COLLAPSED = R.layout.alarm_time_collapsed;
     42     private static final int VIEW_TYPE_ALARM_TIME_EXPANDED = R.layout.alarm_time_expanded;
     43 
     44     private final Context mContext;
     45     private final LayoutInflater mInflater;
     46 
     47     private final AlarmTimeClickHandler mAlarmTimeClickHandler;
     48     private final ScrollHandler mScrollHandler;
     49 
     50     private final boolean mHasVibrator;
     51     private int mExpandedPosition = -1;
     52     private long mExpandedId = Alarm.INVALID_ID;
     53     private Cursor mCursor;
     54 
     55     public AlarmTimeAdapter(Context context, Bundle savedState,
     56             AlarmTimeClickHandler alarmTimeClickHandler, ScrollHandler smoothScrollController) {
     57         mContext = context;
     58         mInflater = LayoutInflater.from(context);
     59         mScrollHandler = smoothScrollController;
     60         mAlarmTimeClickHandler = alarmTimeClickHandler;
     61         mHasVibrator = ((Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE))
     62                 .hasVibrator();
     63         if (savedState != null) {
     64             mExpandedId = savedState.getLong(KEY_EXPANDED_ID, Alarm.INVALID_ID);
     65         }
     66 
     67         setHasStableIds(true);
     68     }
     69 
     70     @Override
     71     public AlarmTimeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
     72         final View v = mInflater.inflate(viewType, parent, false /* attachToRoot */);
     73         if (viewType == VIEW_TYPE_ALARM_TIME_COLLAPSED) {
     74             return new CollapsedAlarmViewHolder(v, mAlarmTimeClickHandler, this);
     75         } else {
     76             return new ExpandedAlarmViewHolder(v, mHasVibrator, mAlarmTimeClickHandler, this);
     77         }
     78     }
     79 
     80     @Override
     81     public void onViewRecycled(AlarmTimeViewHolder viewHolder) {
     82         super.onViewRecycled(viewHolder);
     83         viewHolder.clearData();
     84     }
     85 
     86     @Override
     87     public void onBindViewHolder(AlarmTimeViewHolder viewHolder, int position) {
     88         if (!mCursor.moveToPosition(position)) {
     89             LogUtils.e(TAG, "Failed to bind alarm " + position);
     90             return;
     91         }
     92         final Alarm alarm = new Alarm(mCursor);
     93         final AlarmInstance alarmInstance = alarm.canPreemptivelyDismiss()
     94                 ? new AlarmInstance(mCursor, true /* joinedTable */) : null;
     95         viewHolder.bindAlarm(mContext, alarm, alarmInstance);
     96     }
     97 
     98     @Override
     99     public int getItemCount() {
    100         return mCursor == null ? 0 : mCursor.getCount();
    101     }
    102 
    103     @Override
    104     public long getItemId(int position) {
    105         if (mCursor == null || !mCursor.moveToPosition(position)) {
    106             return RecyclerView.NO_ID;
    107         }
    108         // TODO: Directly read id instead of instantiating Alarm object.
    109         return new Alarm(mCursor).id;
    110     }
    111 
    112     @Override
    113     public int getItemViewType(int position) {
    114         final long stableId = getItemId(position);
    115         return stableId != RecyclerView.NO_ID && stableId == mExpandedId
    116                 ? VIEW_TYPE_ALARM_TIME_EXPANDED : VIEW_TYPE_ALARM_TIME_COLLAPSED;
    117     }
    118 
    119     public void saveInstance(Bundle outState) {
    120         outState.putLong(KEY_EXPANDED_ID, mExpandedId);
    121     }
    122 
    123     /**
    124      * Request the UI to expand the alarm at selected position and scroll it into view.
    125      */
    126     public void expand(int position) {
    127         final long stableId = getItemId(position);
    128         if (mExpandedId == stableId) {
    129             return;
    130         }
    131         mExpandedId = stableId;
    132         mScrollHandler.smoothScrollTo(position);
    133         if (mExpandedPosition >= 0) {
    134             notifyItemChanged(mExpandedPosition);
    135         }
    136         mExpandedPosition = position;
    137         notifyItemChanged(position);
    138     }
    139 
    140     public void collapse(int position) {
    141         mExpandedId = Alarm.INVALID_ID;
    142         mExpandedPosition = -1;
    143         notifyItemChanged(position);
    144     }
    145 
    146     /**
    147      * Swaps the adapter to a new data source.
    148      *
    149      * @param cursor A cursor generated by Cursor loader from {@link Alarm#getAlarmsCursorLoader}.
    150      */
    151     public void swapCursor(Cursor cursor) {
    152         if (mCursor == cursor) {
    153             return;
    154         }
    155         if (mCursor != null) {
    156             mCursor.close();
    157         }
    158         mCursor = cursor;
    159         notifyDataSetChanged();
    160     }
    161 }
    162