AgendaByDayAdapter.java revision 146de36083f6ce8b7e8a1f974d3990594a36bfec
1146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/*
2146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
4146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * you may not use this file except in compliance with the License.
6146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * You may obtain a copy of the License at
7146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
8146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
10146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * See the License for the specific language governing permissions and
14146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * limitations under the License.
15146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */
16146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
17146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpackage com.android.calendar;
18146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
19146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context;
20146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor;
21146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils;
22146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time;
23146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.LayoutInflater;
24146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View;
25146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewGroup;
26146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.BaseAdapter;
27146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.TextView;
28146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
29146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList;
30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Calendar;
31146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Iterator;
32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.LinkedList;
33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class AgendaByDayAdapter extends BaseAdapter {
35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_DAY = 0;
36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_MEETING = 1;
37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_LAST = 2;
38146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final Context mContext;
40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final AgendaAdapter mAgendaAdapter;
41146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final LayoutInflater mInflater;
42146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private ArrayList<RowInfo> mRowInfo;
43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mTodayJulianDay;
44146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private Time mTime = new Time();
45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
46146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public AgendaByDayAdapter(Context context, AgendaAdapter agendaAdapter) {
47146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mContext = context;
48146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mAgendaAdapter = agendaAdapter;
49146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
50146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
51146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
52146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCount() {
53146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
54146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mRowInfo.size();
55146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
56146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getCount();
57146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
58146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
59146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Object getItem(int position) {
60146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
61146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
62146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
63146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return row;
64146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
65146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return mAgendaAdapter.getItem(row.mData);
66146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
67146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
68146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItem(position);
69146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
70146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
71146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getItemId(int position) {
72146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
73146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
74146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
75146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return position;
76146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
77146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return mAgendaAdapter.getItemId(row.mData);
78146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
79146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
80146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItemId(position);
81146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
82146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
83146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
84146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getViewTypeCount() {
85146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return TYPE_LAST;
86146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
87146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
88146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
89146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getItemViewType(int position) {
90146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mRowInfo != null && mRowInfo.size() > position ?
91146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mRowInfo.get(position).mType : TYPE_DAY;
92146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
93146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
94146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class ViewHolder {
95146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        TextView dateView;
96146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        TextView dayOfWeekView;
97146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
98146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
99146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public View getView(int position, View convertView, ViewGroup parent) {
100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if ((mRowInfo == null) || (position > mRowInfo.size())) {
101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If we have no row info, mAgendaAdapter returns the view.
102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mAgendaAdapter.getView(position, convertView, parent);
103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        RowInfo row = mRowInfo.get(position);
106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (row.mType == TYPE_DAY) {
107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            ViewHolder holder;
108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            View agendaDayView;
109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if ((convertView == null) || (convertView.getTag() == null)) {
110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Create a new AgendaView with a ViewHolder for fast access to
111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // views w/o calling findViewById()
112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder = new ViewHolder();
113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView = mInflater.inflate(R.layout.agenda_day, parent, false);
114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder.dateView = (TextView) agendaDayView.findViewById(R.id.date);
115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder.dayOfWeekView = (TextView) agendaDayView.findViewById(R.id.day_of_week);
116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView.setTag(holder);
117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView = convertView;
119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder = (ViewHolder) convertView.getTag();
120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Re-use the member variable "mTime" which is set to the local timezone.
123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Time date = mTime;
124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            long millis = date.setJulianDay(row.mData);
125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int flags = DateUtils.FORMAT_NUMERIC_DATE;
126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            holder.dateView.setText(DateUtils.formatDateRange(mContext, millis, millis, flags));
127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mData == mTodayJulianDay) {
129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder.dayOfWeekView.setText(R.string.agenda_today);
130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                int weekDay = date.weekDay + Calendar.SUNDAY;
132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder.dayOfWeekView.setText(DateUtils.getDayOfWeekString(weekDay,
133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        DateUtils.LENGTH_LONG));
134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return agendaDayView;
136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else if (row.mType == TYPE_MEETING) {
137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mAgendaAdapter.getView(row.mData, convertView, parent);
138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else {
139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Error
140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            throw new IllegalStateException("Unknown event type:" + row.mType);
141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void clearDayHeaderInfo() {
145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = null;
146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void calculateDays(Cursor cursor) {
149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        ArrayList<RowInfo> rowInfo = new ArrayList<RowInfo>();
150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int prevStartDay = -1;
151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Time time = new Time();
152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long now = System.currentTimeMillis();
153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        time.set(now);
154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mTodayJulianDay = Time.getJulianDay(now, time.gmtoff);
155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        LinkedList<MultipleDayInfo> multipleDayList = new LinkedList<MultipleDayInfo>();
156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int position = 0; cursor.moveToNext(); position++) {
157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            boolean allDay = cursor.getInt(AgendaActivity.INDEX_ALL_DAY) != 0;
158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int startDay = cursor.getInt(AgendaActivity.INDEX_START_DAY);
159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (startDay != prevStartDay) {
161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Check if we skipped over any empty days
162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (prevStartDay == -1) {
163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    rowInfo.add(new RowInfo(TYPE_DAY, startDay));
164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                } else {
165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If there are any multiple-day events that span the empty
166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // range of days, then create day headers and events for
167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // those multiple-day events.
168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    boolean dayHeaderAdded = false;
169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    for (int currentDay = prevStartDay + 1; currentDay <= startDay; currentDay++) {
170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = false;
171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        while (iter.hasNext()) {
173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            MultipleDayInfo info = iter.next();
174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this event has ended then remove it from the
175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // list.
176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (info.mEndDay < currentDay) {
177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                iter.remove();
178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                continue;
179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this is the first event for the day, then
182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // insert a day header.
183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (!dayHeaderAdded) {
184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                rowInfo.add(new RowInfo(TYPE_DAY, currentDay));
185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                dayHeaderAdded = true;
186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            rowInfo.add(new RowInfo(TYPE_MEETING, info.mPosition));
188146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        }
189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If the day header was not added for the start day, then
192146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // add it now.
193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        rowInfo.add(new RowInfo(TYPE_DAY, startDay));
195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                prevStartDay = startDay;
198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Add in the event for this cursor position
201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            rowInfo.add(new RowInfo(TYPE_MEETING, position));
202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If this event spans multiple days, then add it to the multipleDay
204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // list.
205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int endDay = cursor.getInt(AgendaActivity.INDEX_END_DAY);
206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endDay > startDay) {
207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                multipleDayList.add(new MultipleDayInfo(position, endDay));
208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // There are no more cursor events but we might still have multiple-day
212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events left.  So create day headers and events for those.
213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (prevStartDay > 0) {
214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Get the Julian day for the last day of this month.  To do that,
215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // we set the date to one less than the first day of the next month,
216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // and then normalize.
217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            time.setJulianDay(prevStartDay);
218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            time.month += 1;
219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            time.monthDay = 0;  // monthDay starts with 1, so this is the previous day
220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            long millis = time.normalize(true /* ignore isDst */);
221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            int lastDayOfMonth = Time.getJulianDay(millis, time.gmtoff);
222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            for (int currentDay = prevStartDay + 1; currentDay <= lastDayOfMonth; currentDay++) {
224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                boolean dayHeaderAdded = false;
225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                while (iter.hasNext()) {
227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    MultipleDayInfo info = iter.next();
228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this event has ended then remove it from the
229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // list.
230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (info.mEndDay < currentDay) {
231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        iter.remove();
232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        continue;
233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this is the first event for the day, then
236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // insert a day header.
237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        rowInfo.add(new RowInfo(TYPE_DAY, currentDay));
239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = true;
240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
241146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    rowInfo.add(new RowInfo(TYPE_MEETING, info.mPosition));
242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = rowInfo;
246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class RowInfo {
249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // mType is either a day header (TYPE_DAY) or an event (TYPE_MEETING)
250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mType;
251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // If mType is TYPE_DAY, then mData is the Julian day.  Otherwise
253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // mType is TYPE_MEETING and mData is the cursor position.
254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mData;
255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        RowInfo(int type, int data) {
257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mType = type;
258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mData = data;
259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class MultipleDayInfo {
263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mPosition;
264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mEndDay;
265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        MultipleDayInfo(int position, int endDay) {
267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mPosition = position;
268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mEndDay = endDay;
269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Searches for the day that matches the given Time object and returns the
274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * list position of that day.  If there are no events for that day, then it
275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * finds the nearest day (before or after) that has events and returns the
276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * list position for that day.
277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param time the date to search for
279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the cursor position of the first event for that date, or zero
280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * if no match was found
281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findDayPositionNearestTime(Time time) {
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null) {
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long millis = time.toMillis(false /* use isDst */);
287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int julianDay = Time.getJulianDay(millis, time.gmtoff);
288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minDistance = 1000;  // some big number
289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minIndex = 0;
290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = 0; index < len; index++) {
292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                int distance = Math.abs(julianDay - row.mData);
295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (distance == 0) {
296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    return index;
297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (distance < minDistance) {
299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    minDistance = distance;
300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    minIndex = index;
301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // We didn't find an exact match so take the nearest day that had
306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events.
307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return minIndex;
308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Finds the Julian day containing the event at the given position.
312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param position the list position of an event
314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the Julian day containing that event
315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findJulianDayFromPosition(int position) {
317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null || position < 0) {
318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (position >= len) return 0;  // no row info at this position
323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = position; index >= 0; index--) {
325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return row.mData;
328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return 0;
331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Converts a list position to a cursor position.  The list contains
335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * day headers as well as events.  The cursor contains only events.
336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param listPos the list position of an event
338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the corresponding cursor position of that event
339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCursorPosition(int listPos) {
341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && listPos >= 0) {
342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(listPos);
343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_MEETING) {
344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return row.mData;
345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return listPos;
348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean areAllItemsEnabled() {
352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return false;
353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isEnabled(int position) {
357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && position < mRowInfo.size()) {
358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return row.mType == TYPE_MEETING;
360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return true;
362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
365