• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Configuration;
22 import android.content.res.Resources;
23 import android.database.Cursor;
24 import android.graphics.Rect;
25 import android.graphics.drawable.Drawable;
26 import android.provider.CalendarContract.Calendars;
27 import android.text.TextUtils;
28 import android.view.LayoutInflater;
29 import android.view.TouchDelegate;
30 import android.view.View;
31 import android.view.View.OnClickListener;
32 import android.view.ViewGroup;
33 import android.view.ViewGroup.LayoutParams;
34 import android.widget.BaseAdapter;
35 import android.widget.CheckBox;
36 import android.widget.ListAdapter;
37 import android.widget.TextView;
38 
39 import com.android.calendar.CalendarColorPickerDialog;
40 import com.android.calendar.R;
41 import com.android.calendar.Utils;
42 import com.android.calendar.selectcalendars.CalendarColorCache.OnCalendarColorsLoadedListener;
43 
44 public class SelectCalendarsSimpleAdapter extends BaseAdapter implements ListAdapter,
45     OnCalendarColorsLoadedListener {
46     private static final String TAG = "SelectCalendarsAdapter";
47     private static final String COLOR_PICKER_DIALOG_TAG = "ColorPickerDialog";
48 
49     private static int BOTTOM_ITEM_HEIGHT = 64;
50     private static int NORMAL_ITEM_HEIGHT = 48;
51 
52     private static final int IS_SELECTED = 1 << 0;
53     private static final int IS_TOP = 1 << 1;
54     private static final int IS_BOTTOM = 1 << 2;
55     private static final int IS_BELOW_SELECTED = 1 << 3;
56 
57     private CalendarColorPickerDialog mColorPickerDialog;
58 
59     private LayoutInflater mInflater;
60     Resources mRes;
61     private int mLayout;
62     private int mOrientation;
63     private CalendarRow[] mData;
64     private Cursor mCursor;
65     private int mRowCount = 0;
66 
67     private FragmentManager mFragmentManager;
68     private boolean mIsTablet;
69     private int mColorViewTouchAreaIncrease;
70 
71     private int mIdColumn;
72     private int mNameColumn;
73     private int mColorColumn;
74     private int mVisibleColumn;
75     private int mOwnerAccountColumn;
76     private int mAccountNameColumn;
77     private int mAccountTypeColumn;
78     private static float mScale = 0;
79     private int mColorCalendarVisible;
80     private int mColorCalendarHidden;
81     private int mColorCalendarSecondaryVisible;
82     private int mColorCalendarSecondaryHidden;
83 
84     private CalendarColorCache mCache;
85 
86     private class CalendarRow {
87         long id;
88         String displayName;
89         String ownerAccount;
90         String accountName;
91         String accountType;
92         int color;
93         boolean selected;
94     }
95 
SelectCalendarsSimpleAdapter(Context context, int layout, Cursor c, FragmentManager fm)96     public SelectCalendarsSimpleAdapter(Context context, int layout, Cursor c, FragmentManager fm) {
97         super();
98         mLayout = layout;
99         mOrientation = context.getResources().getConfiguration().orientation;
100         initData(c);
101         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
102         mRes = context.getResources();
103         mColorCalendarVisible = mRes.getColor(R.color.calendar_visible);
104         mColorCalendarHidden = mRes.getColor(R.color.calendar_hidden);
105         mColorCalendarSecondaryVisible = mRes.getColor(R.color.calendar_secondary_visible);
106         mColorCalendarSecondaryHidden = mRes.getColor(R.color.calendar_secondary_hidden);
107 
108         if (mScale == 0) {
109             mScale = mRes.getDisplayMetrics().density;
110             BOTTOM_ITEM_HEIGHT *= mScale;
111             NORMAL_ITEM_HEIGHT *= mScale;
112         }
113 
114         mCache = new CalendarColorCache(context, this);
115 
116         mFragmentManager = fm;
117         mColorPickerDialog = (CalendarColorPickerDialog)
118                 fm.findFragmentByTag(COLOR_PICKER_DIALOG_TAG);
119         mIsTablet = Utils.getConfigBool(context, R.bool.tablet_config);
120         mColorViewTouchAreaIncrease = context.getResources()
121                 .getDimensionPixelSize(R.dimen.color_view_touch_area_increase);
122     }
123 
124     private static class TabletCalendarItemBackgrounds {
125         static private int[] mBackgrounds = null;
126 
127         /**
128          * Sets up the background drawables for the calendars list
129          *
130          * @param res The context's resources
131          */
getBackgrounds()132         static int[] getBackgrounds() {
133             // Not thread safe. Ok if called only from main thread
134             if (mBackgrounds != null) {
135                 return mBackgrounds;
136             }
137 
138             mBackgrounds = new int[16];
139 
140             mBackgrounds[0] = R.drawable.calname_unselected;
141 
142             mBackgrounds[IS_SELECTED] = R.drawable.calname_select_underunselected;
143 
144             mBackgrounds[IS_SELECTED | IS_BOTTOM] =
145                     R.drawable.calname_bottom_select_underunselected;
146 
147             mBackgrounds[IS_SELECTED | IS_BOTTOM | IS_BELOW_SELECTED] =
148                     R.drawable.calname_bottom_select_underselect;
149             mBackgrounds[IS_SELECTED | IS_TOP | IS_BOTTOM | IS_BELOW_SELECTED] = mBackgrounds[
150                     IS_SELECTED | IS_BOTTOM | IS_BELOW_SELECTED];
151             mBackgrounds[IS_SELECTED | IS_TOP | IS_BOTTOM] = mBackgrounds[IS_SELECTED | IS_BOTTOM
152                     | IS_BELOW_SELECTED];
153 
154             mBackgrounds[IS_SELECTED | IS_BELOW_SELECTED] = R.drawable.calname_select_underselect;
155             mBackgrounds[IS_SELECTED | IS_TOP | IS_BELOW_SELECTED] = mBackgrounds[IS_SELECTED
156                     | IS_BELOW_SELECTED];
157             mBackgrounds[IS_SELECTED | IS_TOP] = mBackgrounds[IS_SELECTED | IS_BELOW_SELECTED];
158 
159             mBackgrounds[IS_BOTTOM] = R.drawable.calname_bottom_unselected;
160 
161             mBackgrounds[IS_BOTTOM | IS_BELOW_SELECTED] =
162                     R.drawable.calname_bottom_unselected_underselect;
163             mBackgrounds[IS_TOP | IS_BOTTOM | IS_BELOW_SELECTED] = mBackgrounds[IS_BOTTOM
164                     | IS_BELOW_SELECTED];
165             mBackgrounds[IS_TOP | IS_BOTTOM] = mBackgrounds[IS_BOTTOM | IS_BELOW_SELECTED];
166 
167             mBackgrounds[IS_BELOW_SELECTED] = R.drawable.calname_unselected_underselect;
168             mBackgrounds[IS_TOP | IS_BELOW_SELECTED] = mBackgrounds[IS_BELOW_SELECTED];
169             mBackgrounds[IS_TOP] = mBackgrounds[IS_BELOW_SELECTED];
170             return mBackgrounds;
171         }
172     }
173 
initData(Cursor c)174     private void initData(Cursor c) {
175         if (mCursor != null && c != mCursor) {
176             mCursor.close();
177         }
178         if (c == null) {
179             mCursor = c;
180             mRowCount = 0;
181             mData = null;
182             return;
183         }
184         // TODO create a broadcast listener for ACTION_PROVIDER_CHANGED to update the cursor
185         mCursor = c;
186         mIdColumn = c.getColumnIndexOrThrow(Calendars._ID);
187         mNameColumn = c.getColumnIndexOrThrow(Calendars.CALENDAR_DISPLAY_NAME);
188         mColorColumn = c.getColumnIndexOrThrow(Calendars.CALENDAR_COLOR);
189         mVisibleColumn = c.getColumnIndexOrThrow(Calendars.VISIBLE);
190         mOwnerAccountColumn = c.getColumnIndexOrThrow(Calendars.OWNER_ACCOUNT);
191         mAccountNameColumn = c.getColumnIndexOrThrow(Calendars.ACCOUNT_NAME);
192         mAccountTypeColumn = c.getColumnIndexOrThrow(Calendars.ACCOUNT_TYPE);
193 
194         mRowCount = c.getCount();
195         mData = new CalendarRow[(c.getCount())];
196         c.moveToPosition(-1);
197         int p = 0;
198         while (c.moveToNext()) {
199             mData[p] = new CalendarRow();
200             mData[p].id = c.getLong(mIdColumn);
201             mData[p].displayName = c.getString(mNameColumn);
202             mData[p].color = c.getInt(mColorColumn);
203             mData[p].selected = c.getInt(mVisibleColumn) != 0;
204             mData[p].ownerAccount = c.getString(mOwnerAccountColumn);
205             mData[p].accountName = c.getString(mAccountNameColumn);
206             mData[p].accountType = c.getString(mAccountTypeColumn);
207             p++;
208         }
209     }
210 
changeCursor(Cursor c)211     public void changeCursor(Cursor c) {
212         initData(c);
213         notifyDataSetChanged();
214     }
215 
216     @Override
getView(final int position, View convertView, ViewGroup parent)217     public View getView(final int position, View convertView, ViewGroup parent) {
218         if (position >= mRowCount) {
219             return null;
220         }
221         String name = mData[position].displayName;
222         boolean selected = mData[position].selected;
223 
224         int color = Utils.getDisplayColorFromColor(mData[position].color);
225         View view;
226         if (convertView == null) {
227             view = mInflater.inflate(mLayout, parent, false);
228             final View delegate = view.findViewById(R.id.color);
229             final View delegateParent = (View) delegate.getParent();
230             delegateParent.post(new Runnable() {
231 
232                 @Override
233                 public void run() {
234                     final Rect r = new Rect();
235                     delegate.getHitRect(r);
236                     r.top -= mColorViewTouchAreaIncrease;
237                     r.bottom += mColorViewTouchAreaIncrease;
238                     r.left -= mColorViewTouchAreaIncrease;
239                     r.right += mColorViewTouchAreaIncrease;
240                     delegateParent.setTouchDelegate(new TouchDelegate(r, delegate));
241                 }
242             });
243         } else {
244             view = convertView;
245         }
246 
247         TextView calendarName = (TextView) view.findViewById(R.id.calendar);
248         calendarName.setText(name);
249 
250         View colorView = view.findViewById(R.id.color);
251         colorView.setBackgroundColor(color);
252         colorView.setOnClickListener(new OnClickListener() {
253             @Override
254             public void onClick(View v) {
255                 // Purely for sanity check--view should be disabled if account has no more colors
256                 if (!hasMoreColors(position)) {
257                     return;
258                 }
259 
260                 if (mColorPickerDialog == null) {
261                     mColorPickerDialog = CalendarColorPickerDialog.newInstance(mData[position].id,
262                             mIsTablet);
263                 } else {
264                     mColorPickerDialog.setCalendarId(mData[position].id);
265                 }
266                 mFragmentManager.executePendingTransactions();
267                 if (!mColorPickerDialog.isAdded()) {
268                     mColorPickerDialog.show(mFragmentManager, COLOR_PICKER_DIALOG_TAG);
269                 }
270             }
271         });
272 
273         int textColor;
274         if (selected) {
275             textColor = mColorCalendarVisible;
276         } else {
277             textColor = mColorCalendarHidden;
278         }
279         calendarName.setTextColor(textColor);
280 
281         CheckBox syncCheckBox = (CheckBox) view.findViewById(R.id.sync);
282         if (syncCheckBox != null) {
283 
284             // Full screen layout
285             syncCheckBox.setChecked(selected);
286 
287             colorView.setEnabled(hasMoreColors(position));
288             LayoutParams layoutParam = calendarName.getLayoutParams();
289             TextView secondaryText = (TextView) view.findViewById(R.id.status);
290             if (!TextUtils.isEmpty(mData[position].ownerAccount)
291                     && !mData[position].ownerAccount.equals(name)
292                     && !mData[position].ownerAccount.endsWith("calendar.google.com")) {
293                 int secondaryColor;
294                 if (selected) {
295                     secondaryColor = mColorCalendarSecondaryVisible;
296                 } else {
297                     secondaryColor = mColorCalendarSecondaryHidden;
298                 }
299                 secondaryText.setText(mData[position].ownerAccount);
300                 secondaryText.setTextColor(secondaryColor);
301                 secondaryText.setVisibility(View.VISIBLE);
302                 layoutParam.height = LayoutParams.WRAP_CONTENT;
303             } else {
304                 secondaryText.setVisibility(View.GONE);
305                 layoutParam.height = LayoutParams.MATCH_PARENT;
306             }
307 
308             calendarName.setLayoutParams(layoutParam);
309 
310         } else {
311             // Tablet layout
312             view.findViewById(R.id.color).setEnabled(selected && hasMoreColors(position));
313             view.setBackgroundDrawable(getBackground(position, selected));
314             ViewGroup.LayoutParams newParams = view.getLayoutParams();
315             if (position == mData.length - 1) {
316                 newParams.height = BOTTOM_ITEM_HEIGHT;
317             } else {
318                 newParams.height = NORMAL_ITEM_HEIGHT;
319             }
320             view.setLayoutParams(newParams);
321             CheckBox visibleCheckBox = (CheckBox) view.findViewById(R.id.visible_check_box);
322             if (visibleCheckBox != null) {
323                 visibleCheckBox.setChecked(selected);
324             }
325         }
326         view.invalidate();
327         return view;
328     }
329 
hasMoreColors(int position)330     private boolean hasMoreColors(int position) {
331         return mCache.hasColors(mData[position].accountName, mData[position].accountType);
332     }
333 
334     /**
335      * @param position position of the calendar item
336      * @param selected whether it is selected or not
337      * @return the drawable to use for this view
338      */
getBackground(int position, boolean selected)339     protected Drawable getBackground(int position, boolean selected) {
340         int bg;
341         bg = selected ? IS_SELECTED : 0;
342         bg |= (position == 0 && mOrientation == Configuration.ORIENTATION_LANDSCAPE) ? IS_TOP : 0;
343         bg |= position == mData.length - 1 ? IS_BOTTOM : 0;
344         bg |= (position > 0 && mData[position - 1].selected) ? IS_BELOW_SELECTED : 0;
345         return mRes.getDrawable(TabletCalendarItemBackgrounds.getBackgrounds()[bg]);
346     }
347 
348     @Override
getCount()349     public int getCount() {
350         return mRowCount;
351     }
352 
353     @Override
getItem(int position)354     public Object getItem(int position) {
355         if (position >= mRowCount) {
356             return null;
357         }
358         CalendarRow item = mData[position];
359         return item;
360     }
361 
362     @Override
getItemId(int position)363     public long getItemId(int position) {
364         if (position >= mRowCount) {
365             return 0;
366         }
367         return mData[position].id;
368     }
369 
setVisible(int position, int visible)370     public void setVisible(int position, int visible) {
371         mData[position].selected = visible != 0;
372         notifyDataSetChanged();
373     }
374 
getVisible(int position)375     public int getVisible(int position) {
376         return mData[position].selected ? 1 : 0;
377     }
378 
379     @Override
hasStableIds()380     public boolean hasStableIds() {
381         return true;
382     }
383 
384     @Override
onCalendarColorsLoaded()385     public void onCalendarColorsLoaded() {
386         notifyDataSetChanged();
387     }
388 }
389