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