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