1 /* 2 * Copyright (C) 2007 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.agenda; 18 19 import com.android.calendar.ColorChipView; 20 import com.android.calendar.R; 21 import com.android.calendar.Utils; 22 23 import android.content.Context; 24 import android.content.res.Resources; 25 import android.database.Cursor; 26 import android.provider.CalendarContract.Attendees; 27 import android.text.TextUtils; 28 import android.text.format.DateFormat; 29 import android.text.format.DateUtils; 30 import android.text.format.Time; 31 import android.view.View; 32 import android.view.ViewGroup; 33 import android.widget.ResourceCursorAdapter; 34 import android.widget.TextView; 35 36 import java.util.Formatter; 37 import java.util.Locale; 38 import java.util.TimeZone; 39 40 public class AgendaAdapter extends ResourceCursorAdapter { 41 private String mNoTitleLabel; 42 private Resources mResources; 43 private int mDeclinedColor; 44 private int mStandardColor; 45 private int mWhereColor; 46 private int mWhereDeclinedColor; 47 // Note: Formatter is not thread safe. Fine for now as it is only used by the main thread. 48 private Formatter mFormatter; 49 private StringBuilder mStringBuilder; 50 private float mScale; 51 52 private int COLOR_CHIP_ALL_DAY_HEIGHT; 53 private int COLOR_CHIP_HEIGHT; 54 55 private Runnable mTZUpdater = new Runnable() { 56 @Override 57 public void run() { 58 notifyDataSetChanged(); 59 } 60 }; 61 62 static class ViewHolder { 63 64 public static final int DECLINED_RESPONSE = 0; 65 public static final int TENTATIVE_RESPONSE = 1; 66 public static final int ACCEPTED_RESPONSE = 2; 67 68 /* Event */ 69 TextView title; 70 TextView when; 71 TextView where; 72 View selectedMarker; 73 long instanceId; 74 ColorChipView colorChip; 75 long startTimeMilli; 76 boolean allDay; 77 boolean grayed; 78 int julianDay; 79 } 80 81 public AgendaAdapter(Context context, int resource) { 82 super(context, resource, null); 83 84 mResources = context.getResources(); 85 mNoTitleLabel = mResources.getString(R.string.no_title_label); 86 mDeclinedColor = mResources.getColor(R.color.agenda_item_declined_color); 87 mStandardColor = mResources.getColor(R.color.agenda_item_standard_color); 88 mWhereDeclinedColor = mResources.getColor(R.color.agenda_item_where_declined_text_color); 89 mWhereColor = mResources.getColor(R.color.agenda_item_where_text_color); 90 mStringBuilder = new StringBuilder(50); 91 mFormatter = new Formatter(mStringBuilder, Locale.getDefault()); 92 93 COLOR_CHIP_ALL_DAY_HEIGHT = mResources.getInteger(R.integer.color_chip_all_day_height); 94 COLOR_CHIP_HEIGHT = mResources.getInteger(R.integer.color_chip_height); 95 if (mScale == 0) { 96 mScale = mResources.getDisplayMetrics().density; 97 if (mScale != 1) { 98 COLOR_CHIP_ALL_DAY_HEIGHT *= mScale; 99 COLOR_CHIP_HEIGHT *= mScale; 100 } 101 } 102 103 } 104 105 @Override 106 public void bindView(View view, Context context, Cursor cursor) { 107 ViewHolder holder = null; 108 109 // Listview may get confused and pass in a different type of view since 110 // we keep shifting data around. Not a big problem. 111 Object tag = view.getTag(); 112 if (tag instanceof ViewHolder) { 113 holder = (ViewHolder) view.getTag(); 114 } 115 116 if (holder == null) { 117 holder = new ViewHolder(); 118 view.setTag(holder); 119 holder.title = (TextView) view.findViewById(R.id.title); 120 holder.when = (TextView) view.findViewById(R.id.when); 121 holder.where = (TextView) view.findViewById(R.id.where); 122 holder.selectedMarker = view.findViewById(R.id.selected_marker); 123 holder.colorChip = (ColorChipView)view.findViewById(R.id.agenda_item_color); 124 } 125 126 holder.startTimeMilli = cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN); 127 // Fade text if event was declined and set the color chip mode (response 128 boolean allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0; 129 holder.allDay = allDay; 130 int selfAttendeeStatus = cursor.getInt(AgendaWindowAdapter.INDEX_SELF_ATTENDEE_STATUS); 131 if (selfAttendeeStatus == Attendees.ATTENDEE_STATUS_DECLINED) { 132 holder.title.setTextColor(mDeclinedColor); 133 holder.when.setTextColor(mWhereDeclinedColor); 134 holder.where.setTextColor(mWhereDeclinedColor); 135 holder.colorChip.setDrawStyle(ColorChipView.DRAW_FADED); 136 } else { 137 holder.title.setTextColor(mStandardColor); 138 holder.when.setTextColor(mWhereColor); 139 holder.where.setTextColor(mWhereColor); 140 if (selfAttendeeStatus == Attendees.ATTENDEE_STATUS_INVITED) { 141 holder.colorChip.setDrawStyle(ColorChipView.DRAW_BORDER); 142 } else { 143 holder.colorChip.setDrawStyle(ColorChipView.DRAW_FULL); 144 } 145 } 146 147 // Set the size of the color chip 148 ViewGroup.LayoutParams params = holder.colorChip.getLayoutParams(); 149 if (allDay) { 150 params.height = COLOR_CHIP_ALL_DAY_HEIGHT; 151 } else { 152 params.height = COLOR_CHIP_HEIGHT; 153 154 } 155 holder.colorChip.setLayoutParams(params); 156 157 // Deal with exchange events that the owner cannot respond to 158 int canRespond = cursor.getInt(AgendaWindowAdapter.INDEX_CAN_ORGANIZER_RESPOND); 159 if (canRespond == 0) { 160 String owner = cursor.getString(AgendaWindowAdapter.INDEX_OWNER_ACCOUNT); 161 String organizer = cursor.getString(AgendaWindowAdapter.INDEX_ORGANIZER); 162 if (owner.equals(organizer)) { 163 holder.colorChip.setDrawStyle(ColorChipView.DRAW_FULL); 164 holder.title.setTextColor(mStandardColor); 165 holder.when.setTextColor(mStandardColor); 166 holder.where.setTextColor(mStandardColor); 167 } 168 } 169 170 TextView title = holder.title; 171 TextView when = holder.when; 172 TextView where = holder.where; 173 174 holder.instanceId = cursor.getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID); 175 176 /* Calendar Color */ 177 int color = Utils.getDisplayColorFromColor(cursor.getInt(AgendaWindowAdapter.INDEX_COLOR)); 178 holder.colorChip.setColor(color); 179 180 // What 181 String titleString = cursor.getString(AgendaWindowAdapter.INDEX_TITLE); 182 if (titleString == null || titleString.length() == 0) { 183 titleString = mNoTitleLabel; 184 } 185 title.setText(titleString); 186 187 // When 188 long begin = cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN); 189 long end = cursor.getLong(AgendaWindowAdapter.INDEX_END); 190 String eventTz = cursor.getString(AgendaWindowAdapter.INDEX_TIME_ZONE); 191 int flags = 0; 192 String whenString; 193 // It's difficult to update all the adapters so just query this each 194 // time we need to build the view. 195 String tzString = Utils.getTimeZone(context, mTZUpdater); 196 if (allDay) { 197 tzString = Time.TIMEZONE_UTC; 198 } else { 199 flags = DateUtils.FORMAT_SHOW_TIME; 200 } 201 if (DateFormat.is24HourFormat(context)) { 202 flags |= DateUtils.FORMAT_24HOUR; 203 } 204 mStringBuilder.setLength(0); 205 whenString = DateUtils.formatDateRange(context, mFormatter, begin, end, flags, tzString) 206 .toString(); 207 if (!allDay && !TextUtils.equals(tzString, eventTz)) { 208 String displayName; 209 // Figure out if this is in DST 210 Time date = new Time(tzString); 211 date.set(begin); 212 213 TimeZone tz = TimeZone.getTimeZone(tzString); 214 if (tz == null || tz.getID().equals("GMT")) { 215 displayName = tzString; 216 } else { 217 displayName = tz.getDisplayName(date.isDst != 0, TimeZone.SHORT); 218 } 219 whenString += " (" + displayName + ")"; 220 } 221 when.setText(whenString); 222 223 /* Recurring event icon is removed 224 String rrule = cursor.getString(AgendaWindowAdapter.INDEX_RRULE); 225 if (!TextUtils.isEmpty(rrule)) { 226 when.setCompoundDrawablesWithIntrinsicBounds(null, null, 227 context.getResources().getDrawable(R.drawable.ic_repeat_dark), null); 228 when.setCompoundDrawablePadding(5); 229 } else { 230 when.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); 231 } */ 232 233 /* 234 // Repeating info 235 View repeatContainer = view.findViewById(R.id.repeat_icon); 236 String rrule = cursor.getString(AgendaWindowAdapter.INDEX_RRULE); 237 if (!TextUtils.isEmpty(rrule)) { 238 repeatContainer.setVisibility(View.VISIBLE); 239 } else { 240 repeatContainer.setVisibility(View.GONE); 241 } 242 */ 243 244 /* 245 // Reminder 246 boolean hasAlarm = cursor.getInt(AgendaWindowAdapter.INDEX_HAS_ALARM) != 0; 247 if (hasAlarm) { 248 updateReminder(view, context, begin, cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID)); 249 } 250 */ 251 252 // Where 253 String whereString = cursor.getString(AgendaWindowAdapter.INDEX_EVENT_LOCATION); 254 if (whereString != null && whereString.length() > 0) { 255 where.setVisibility(View.VISIBLE); 256 where.setText(whereString); 257 } else { 258 where.setVisibility(View.GONE); 259 } 260 } 261 262 /* 263 public static void updateReminder(View view, Context context, long begin, long eventId) { 264 ContentResolver cr = context.getContentResolver(); 265 Uri uri = Reminders.CONTENT_URI; 266 String where = String.format(REMINDERS_WHERE, eventId); 267 268 Cursor remindersCursor = cr.query(uri, REMINDERS_PROJECTION, where, null, null); 269 if (remindersCursor != null) { 270 LayoutInflater inflater = 271 (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 272 LinearLayout parent = (LinearLayout) view.findViewById(R.id.reminders_container); 273 parent.removeAllViews(); 274 while (remindersCursor.moveToNext()) { 275 int alarm = remindersCursor.getInt(REMINDERS_INDEX_MINUTES); 276 String before = EditEvent.constructReminderLabel(context, alarm, true); 277 LinearLayout reminderItem = (LinearLayout) 278 inflater.inflate(R.layout.agenda_reminder_item, null); 279 TextView reminderItemText = (TextView) reminderItem.findViewById(R.id.reminder); 280 reminderItemText.setText(before); 281 parent.addView(reminderItem); 282 } 283 } 284 remindersCursor.close(); 285 } 286 */ 287 } 288 289