Home | History | Annotate | Download | only in agenda
      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 
     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
    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