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