Home | History | Annotate | Download | only in selectcalendars
      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.selectcalendars;
     18 
     19 import android.app.FragmentManager;
     20 import android.content.Context;
     21 import android.content.res.Resources;
     22 import android.database.Cursor;
     23 import android.graphics.Rect;
     24 import android.graphics.drawable.shapes.RectShape;
     25 import android.provider.CalendarContract.Calendars;
     26 import android.text.TextUtils;
     27 import android.view.LayoutInflater;
     28 import android.view.TouchDelegate;
     29 import android.view.View;
     30 import android.view.View.OnClickListener;
     31 import android.view.ViewGroup;
     32 import android.widget.AdapterView;
     33 import android.widget.BaseAdapter;
     34 import android.widget.CheckBox;
     35 import android.widget.ListAdapter;
     36 import android.widget.TextView;
     37 
     38 import com.android.calendar.CalendarColorPickerDialog;
     39 import com.android.calendar.R;
     40 import com.android.calendar.Utils;
     41 import com.android.calendar.selectcalendars.CalendarColorCache.OnCalendarColorsLoadedListener;
     42 
     43 import java.util.HashMap;
     44 
     45 public class SelectCalendarsSyncAdapter extends BaseAdapter
     46         implements ListAdapter, AdapterView.OnItemClickListener, OnCalendarColorsLoadedListener {
     47     private static final String TAG = "SelCalsAdapter";
     48     private static final String COLOR_PICKER_DIALOG_TAG = "ColorPickerDialog";
     49 
     50     private static int COLOR_CHIP_SIZE = 30;
     51     private RectShape r = new RectShape();
     52 
     53     private CalendarColorPickerDialog mColorPickerDialog;
     54     private CalendarColorCache mCache;
     55 
     56     private LayoutInflater mInflater;
     57     private static final int LAYOUT = R.layout.calendar_sync_item;
     58     private CalendarRow[] mData;
     59     private HashMap<Long, CalendarRow> mChanges = new HashMap<Long, CalendarRow>();
     60     private int mRowCount = 0;
     61 
     62     private int mIdColumn;
     63     private int mNameColumn;
     64     private int mColorColumn;
     65     private int mSyncedColumn;
     66     private int mAccountNameColumn;
     67     private int mAccountTypeColumn;
     68 
     69     private boolean mIsTablet;
     70     private FragmentManager mFragmentManager;
     71     private int mColorViewTouchAreaIncrease;
     72 
     73 
     74     private final String mSyncedString;
     75     private final String mNotSyncedString;
     76 
     77     public class CalendarRow {
     78         long id;
     79         String displayName;
     80         int color;
     81         boolean synced;
     82         boolean originalSynced;
     83         String accountName;
     84         String accountType;
     85     }
     86 
     87     public SelectCalendarsSyncAdapter(Context context, Cursor c, FragmentManager manager) {
     88         super();
     89         initData(c);
     90         mCache = new CalendarColorCache(context, this);
     91         mFragmentManager = manager;
     92         mColorPickerDialog = (CalendarColorPickerDialog)
     93                 manager.findFragmentByTag(COLOR_PICKER_DIALOG_TAG);
     94         mColorViewTouchAreaIncrease = context.getResources()
     95                 .getDimensionPixelSize(R.dimen.color_view_touch_area_increase);
     96         mIsTablet = Utils.getConfigBool(context, R.bool.tablet_config);
     97         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
     98         COLOR_CHIP_SIZE *= context.getResources().getDisplayMetrics().density;
     99         r.resize(COLOR_CHIP_SIZE, COLOR_CHIP_SIZE);
    100         Resources res = context.getResources();
    101         mSyncedString = res.getString(R.string.synced);
    102         mNotSyncedString = res.getString(R.string.not_synced);
    103     }
    104 
    105     private void initData(Cursor c) {
    106         if (c == null) {
    107             mRowCount = 0;
    108             mData = null;
    109             return;
    110         }
    111 
    112         mIdColumn = c.getColumnIndexOrThrow(Calendars._ID);
    113         mNameColumn = c.getColumnIndexOrThrow(Calendars.CALENDAR_DISPLAY_NAME);
    114         mColorColumn = c.getColumnIndexOrThrow(Calendars.CALENDAR_COLOR);
    115         mSyncedColumn = c.getColumnIndexOrThrow(Calendars.SYNC_EVENTS);
    116         mAccountNameColumn = c.getColumnIndexOrThrow(Calendars.ACCOUNT_NAME);
    117         mAccountTypeColumn = c.getColumnIndexOrThrow(Calendars.ACCOUNT_TYPE);
    118 
    119         mRowCount = c.getCount();
    120         mData = new CalendarRow[mRowCount];
    121         c.moveToPosition(-1);
    122         int p = 0;
    123         while (c.moveToNext()) {
    124             long id = c.getLong(mIdColumn);
    125             mData[p] = new CalendarRow();
    126             mData[p].id = id;
    127             mData[p].displayName = c.getString(mNameColumn);
    128             mData[p].color = c.getInt(mColorColumn);
    129             mData[p].originalSynced = c.getInt(mSyncedColumn) != 0;
    130             mData[p].accountName = c.getString(mAccountNameColumn);
    131             mData[p].accountType = c.getString(mAccountTypeColumn);
    132             if (mChanges.containsKey(id)) {
    133                 mData[p].synced = mChanges.get(id).synced;
    134             } else {
    135                 mData[p].synced = mData[p].originalSynced;
    136             }
    137             p++;
    138         }
    139     }
    140 
    141     public void changeCursor(Cursor c) {
    142         initData(c);
    143         notifyDataSetChanged();
    144     }
    145 
    146     @Override
    147     public View getView(final int position, View convertView, ViewGroup parent) {
    148         if (position >= mRowCount) {
    149             return null;
    150         }
    151         String name = mData[position].displayName;
    152         boolean selected = mData[position].synced;
    153         int color = Utils.getDisplayColorFromColor(mData[position].color);
    154         View view;
    155         if (convertView == null) {
    156             view = mInflater.inflate(LAYOUT, parent, false);
    157             final View delegate = view.findViewById(R.id.color);
    158             final View delegateParent = (View) delegate.getParent();
    159             delegateParent.post(new Runnable() {
    160 
    161                 @Override
    162                 public void run() {
    163                     final Rect r = new Rect();
    164                     delegate.getHitRect(r);
    165                     r.top -= mColorViewTouchAreaIncrease;
    166                     r.bottom += mColorViewTouchAreaIncrease;
    167                     r.left -= mColorViewTouchAreaIncrease;
    168                     r.right += mColorViewTouchAreaIncrease;
    169                     delegateParent.setTouchDelegate(new TouchDelegate(r, delegate));
    170                 }
    171             });
    172         } else {
    173             view = convertView;
    174         }
    175 
    176         view.setTag(mData[position]);
    177 
    178         CheckBox cb = (CheckBox) view.findViewById(R.id.sync);
    179         cb.setChecked(selected);
    180 
    181         if (selected) {
    182             setText(view, R.id.status, mSyncedString);
    183         } else {
    184             setText(view, R.id.status, mNotSyncedString);
    185         }
    186 
    187         View colorView = view.findViewById(R.id.color);
    188         colorView.setEnabled(hasMoreColors(position));
    189         colorView.setBackgroundColor(color);
    190         colorView.setOnClickListener(new OnClickListener() {
    191 
    192             @Override
    193             public void onClick(View v) {
    194                 // Purely for sanity check--view should be disabled if account has no more colors
    195                 if (!hasMoreColors(position)) {
    196                     return;
    197                 }
    198 
    199                 if (mColorPickerDialog == null) {
    200                     mColorPickerDialog = CalendarColorPickerDialog.newInstance(mData[position].id,
    201                             mIsTablet);
    202                 } else {
    203                     mColorPickerDialog.setCalendarId(mData[position].id);
    204                 }
    205                 mFragmentManager.executePendingTransactions();
    206                 if (!mColorPickerDialog.isAdded()) {
    207                     mColorPickerDialog.show(mFragmentManager, COLOR_PICKER_DIALOG_TAG);
    208                 }
    209             }
    210         });
    211 
    212         setText(view, R.id.calendar, name);
    213         return view;
    214     }
    215 
    216     private boolean hasMoreColors(int position) {
    217         return mCache.hasColors(mData[position].accountName, mData[position].accountType);
    218     }
    219 
    220     private static void setText(View view, int id, String text) {
    221         if (TextUtils.isEmpty(text)) {
    222             return;
    223         }
    224         TextView textView = (TextView) view.findViewById(id);
    225         textView.setText(text);
    226     }
    227 
    228     @Override
    229     public int getCount() {
    230         return mRowCount;
    231     }
    232 
    233     @Override
    234     public Object getItem(int position) {
    235         if (position >= mRowCount) {
    236             return null;
    237         }
    238         CalendarRow item = mData[position];
    239         return item;
    240     }
    241 
    242     @Override
    243     public long getItemId(int position) {
    244         if (position >= mRowCount) {
    245             return 0;
    246         }
    247         return mData[position].id;
    248     }
    249 
    250     @Override
    251     public boolean hasStableIds() {
    252         return true;
    253     }
    254 
    255     public int getSynced(int position) {
    256         return mData[position].synced ? 1 : 0;
    257     }
    258 
    259     @Override
    260     public void onItemClick(AdapterView<?> parent, View view, int position, long id)  {
    261         CalendarRow row = (CalendarRow) view.getTag();
    262         row.synced = !row.synced;
    263 
    264         String status;
    265         if (row.synced) {
    266             status = mSyncedString;
    267         } else {
    268             status = mNotSyncedString;
    269         }
    270         setText(view, R.id.status, status);
    271 
    272         CheckBox cb = (CheckBox) view.findViewById(R.id.sync);
    273         cb.setChecked(row.synced);
    274 
    275         // There is some data loss in long -> int, but we should never see it in
    276         // practice regarding calendar ids.
    277         mChanges.put(row.id, row);
    278     }
    279 
    280     public HashMap<Long, CalendarRow> getChanges() {
    281         return mChanges;
    282     }
    283 
    284     @Override
    285     public void onCalendarColorsLoaded() {
    286         notifyDataSetChanged();
    287     }
    288 }
    289