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