AgendaByDayAdapter.java revision dad908b741d7d0a7e4a573030baeb74319ad9411
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
29dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chanimport com.android.calendar.AgendaWindowAdapter.DayAdapterInfo;
30dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
31146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList;
3213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Formatter;
33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Iterator;
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.LinkedList;
3513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Locale;
36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class AgendaByDayAdapter extends BaseAdapter {
38146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_DAY = 0;
39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_MEETING = 1;
4013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static final int TYPE_LAST = 2;
41146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
42146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final Context mContext;
43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final AgendaAdapter mAgendaAdapter;
44146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final LayoutInflater mInflater;
45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private ArrayList<RowInfo> mRowInfo;
46146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mTodayJulianDay;
4713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private Time mTmpTime = new Time();
4823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    // Note: Formatter is not thread safe. Fine for now as it is only used by the main thread.
4923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    private Formatter mFormatter;
5013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private StringBuilder mStringBuilder;
51146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
5213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static class ViewHolder {
5313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        TextView dateView;
5413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
5513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
5613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public AgendaByDayAdapter(Context context) {
57146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mContext = context;
5813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaAdapter = new AgendaAdapter(context, R.layout.agenda_item);
5913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
6013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder = new StringBuilder(50);
6113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
62146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
63146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
64146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCount() {
65146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
66146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mRowInfo.size();
67146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
68146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getCount();
69146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
70146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
71146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Object getItem(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 row;
76146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
77146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return mAgendaAdapter.getItem(row.mData);
78146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
79146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
80146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItem(position);
81146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
82146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
83146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getItemId(int position) {
84146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
85146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
86146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
87146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return position;
88146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
89146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return mAgendaAdapter.getItemId(row.mData);
90146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
91146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
92146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItemId(position);
93146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
94146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
95146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
96146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getViewTypeCount() {
97146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return TYPE_LAST;
98146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
99146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
100146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
101146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getItemViewType(int position) {
102146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mRowInfo != null && mRowInfo.size() > position ?
103146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mRowInfo.get(position).mType : TYPE_DAY;
104146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
105146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
106146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public View getView(int position, View convertView, ViewGroup parent) {
107146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if ((mRowInfo == null) || (position > mRowInfo.size())) {
108146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If we have no row info, mAgendaAdapter returns the view.
109146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mAgendaAdapter.getView(position, convertView, parent);
110146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
111146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
112146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        RowInfo row = mRowInfo.get(position);
113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (row.mType == TYPE_DAY) {
11413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            ViewHolder holder = null;
11513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            View agendaDayView = null;
11613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if ((convertView != null) && (convertView.getTag() != null)) {
11713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Listview may get confused and pass in a different type of
11813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // view since we keep shifting data around. Not a big problem.
11913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Object tag = convertView.getTag();
12013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (tag instanceof ViewHolder) {
12113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    agendaDayView = convertView;
12213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    holder = (ViewHolder) tag;
12313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
12413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
12513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
12613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (holder == null) {
127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Create a new AgendaView with a ViewHolder for fast access to
128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // views w/o calling findViewById()
129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder = new ViewHolder();
130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView = mInflater.inflate(R.layout.agenda_day, parent, false);
131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder.dateView = (TextView) agendaDayView.findViewById(R.id.date);
132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView.setTag(holder);
133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Re-use the member variable "mTime" which is set to the local timezone.
13613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Time date = mTmpTime;
137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            long millis = date.setJulianDay(row.mData);
1383cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project            int flags = DateUtils.FORMAT_SHOW_YEAR
1393cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project                    | DateUtils.FORMAT_SHOW_DATE;
14013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
14113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mStringBuilder.setLength(0);
14223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            String dateViewText;
143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mData == mTodayJulianDay) {
14423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                dateViewText = mContext.getString(R.string.agenda_today, DateUtils.formatDateRange(
14523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        mContext, mFormatter, millis, millis, flags).toString());
146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
1473cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project                flags |= DateUtils.FORMAT_SHOW_WEEKDAY;
14823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                dateViewText = DateUtils.formatDateRange(mContext, mFormatter, millis, millis,
14923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        flags).toString();
150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
1513cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
15223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (AgendaWindowAdapter.BASICLOG) {
15323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                dateViewText += " P:" + position;
15423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
15523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            holder.dateView.setText(dateViewText);
1563cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return agendaDayView;
158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else if (row.mType == TYPE_MEETING) {
15913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            View x = mAgendaAdapter.getView(row.mData, convertView, parent);
16013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            TextView y = ((AgendaAdapter.ViewHolder) x.getTag()).title;
16124ed7b9e8a54f9aea703f62b64c53b119ebf4680Michael Chan            y.setText(y.getText());
16213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return x;
163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else {
164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Error
165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            throw new IllegalStateException("Unknown event type:" + row.mType);
166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void clearDayHeaderInfo() {
170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = null;
171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
173dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void changeCursor(DayAdapterInfo info) {
174dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        calculateDays(info);
175dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        mAgendaAdapter.changeCursor(info.cursor);
17613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
17713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
178dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void calculateDays(DayAdapterInfo dayAdapterInfo) {
179dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        Cursor cursor = dayAdapterInfo.cursor;
180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        ArrayList<RowInfo> rowInfo = new ArrayList<RowInfo>();
181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int prevStartDay = -1;
182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        Time time = new Time();
183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long now = System.currentTimeMillis();
184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        time.set(now);
185146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mTodayJulianDay = Time.getJulianDay(now, time.gmtoff);
186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        LinkedList<MultipleDayInfo> multipleDayList = new LinkedList<MultipleDayInfo>();
187146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int position = 0; cursor.moveToNext(); position++) {
18813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            boolean allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0;
18913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY);
190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
191dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
192dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            startDay = Math.max(startDay, dayAdapterInfo.start);
193dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (startDay != prevStartDay) {
195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Check if we skipped over any empty days
196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (prevStartDay == -1) {
197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    rowInfo.add(new RowInfo(TYPE_DAY, startDay));
198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                } else {
199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If there are any multiple-day events that span the empty
200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // range of days, then create day headers and events for
201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // those multiple-day events.
202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    boolean dayHeaderAdded = false;
203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    for (int currentDay = prevStartDay + 1; currentDay <= startDay; currentDay++) {
204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = false;
205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        while (iter.hasNext()) {
207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            MultipleDayInfo info = iter.next();
208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this event has ended then remove it from the
209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // list.
210146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (info.mEndDay < currentDay) {
211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                iter.remove();
212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                continue;
213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
214146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
215146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this is the first event for the day, then
216146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // insert a day header.
217146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (!dayHeaderAdded) {
218146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                rowInfo.add(new RowInfo(TYPE_DAY, currentDay));
219146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                dayHeaderAdded = true;
220146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
221146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            rowInfo.add(new RowInfo(TYPE_MEETING, info.mPosition));
222146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        }
223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If the day header was not added for the start day, then
226146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // add it now.
227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        rowInfo.add(new RowInfo(TYPE_DAY, startDay));
229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
230146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                prevStartDay = startDay;
232146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
233146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Add in the event for this cursor position
235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            rowInfo.add(new RowInfo(TYPE_MEETING, position));
236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If this event spans multiple days, then add it to the multipleDay
238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // list.
23913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int endDay = cursor.getInt(AgendaWindowAdapter.INDEX_END_DAY);
240dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
241dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
242dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            endDay = Math.min(endDay, dayAdapterInfo.end);
243146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endDay > startDay) {
244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                multipleDayList.add(new MultipleDayInfo(position, endDay));
245146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // There are no more cursor events but we might still have multiple-day
249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events left.  So create day headers and events for those.
250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (prevStartDay > 0) {
251dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            for (int currentDay = prevStartDay + 1; currentDay <= dayAdapterInfo.end;
252dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan                    currentDay++) {
253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                boolean dayHeaderAdded = false;
254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                while (iter.hasNext()) {
256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    MultipleDayInfo info = iter.next();
257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this event has ended then remove it from the
258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // list.
259146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (info.mEndDay < currentDay) {
260146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        iter.remove();
261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        continue;
262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this is the first event for the day, then
265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // insert a day header.
266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        rowInfo.add(new RowInfo(TYPE_DAY, currentDay));
268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = true;
269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    rowInfo.add(new RowInfo(TYPE_MEETING, info.mPosition));
271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
273146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
274146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = rowInfo;
275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class RowInfo {
278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // mType is either a day header (TYPE_DAY) or an event (TYPE_MEETING)
279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mType;
280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // If mType is TYPE_DAY, then mData is the Julian day.  Otherwise
282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // mType is TYPE_MEETING and mData is the cursor position.
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mData;
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        RowInfo(int type, int data) {
286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mType = type;
287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mData = data;
288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class MultipleDayInfo {
292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mPosition;
293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mEndDay;
294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        MultipleDayInfo(int position, int endDay) {
296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mPosition = position;
297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mEndDay = endDay;
298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Searches for the day that matches the given Time object and returns the
303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * list position of that day.  If there are no events for that day, then it
304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * finds the nearest day (before or after) that has events and returns the
305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * list position for that day.
306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param time the date to search for
308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the cursor position of the first event for that date, or zero
309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * if no match was found
310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findDayPositionNearestTime(Time time) {
312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null) {
313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long millis = time.toMillis(false /* use isDst */);
316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int julianDay = Time.getJulianDay(millis, time.gmtoff);
317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minDistance = 1000;  // some big number
318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minIndex = 0;
319146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = 0; index < len; index++) {
321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                int distance = Math.abs(julianDay - row.mData);
324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (distance == 0) {
325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    return index;
326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (distance < minDistance) {
328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    minDistance = distance;
329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    minIndex = index;
330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // We didn't find an exact match so take the nearest day that had
335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events.
336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return minIndex;
337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Finds the Julian day containing the event at the given position.
341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param position the list position of an event
343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the Julian day containing that event
344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findJulianDayFromPosition(int position) {
346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null || position < 0) {
347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (position >= len) return 0;  // no row info at this position
352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = position; index >= 0; index--) {
354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return row.mData;
357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return 0;
360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Converts a list position to a cursor position.  The list contains
364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * day headers as well as events.  The cursor contains only events.
365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param listPos the list position of an event
367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the corresponding cursor position of that event
368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCursorPosition(int listPos) {
370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && listPos >= 0) {
371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(listPos);
372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_MEETING) {
373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return row.mData;
37413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else {
37513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int nextPos = listPos + 1;
37613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (nextPos < mRowInfo.size()) {
37713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    nextPos = getCursorPosition(nextPos);
37813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (nextPos >= 0) {
37913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        return -nextPos;
38013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
38113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
38413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return Integer.MIN_VALUE;
385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean areAllItemsEnabled() {
389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return false;
390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isEnabled(int position) {
394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && position < mRowInfo.size()) {
395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return row.mType == TYPE_MEETING;
397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return true;
399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
401