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
1700b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tangpackage com.android.calendar.agenda;
18146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
19146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context;
20146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor;
212d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelsonimport android.graphics.Typeface;
229a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport android.text.TextUtils;
23146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils;
24146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time;
25146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.LayoutInflater;
26146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View;
27146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewGroup;
28146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.BaseAdapter;
29146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.TextView;
30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
3148bcc4cb015dbf802341698a3a04e28d2cfb2ddcMichael Chanimport com.android.calendar.R;
3248bcc4cb015dbf802341698a3a04e28d2cfb2ddcMichael Chanimport com.android.calendar.Utils;
3348bcc4cb015dbf802341698a3a04e28d2cfb2ddcMichael Chanimport com.android.calendar.agenda.AgendaWindowAdapter.DayAdapterInfo;
3448bcc4cb015dbf802341698a3a04e28d2cfb2ddcMichael Chan
35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList;
3613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Formatter;
37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Iterator;
38146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.LinkedList;
3913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Locale;
40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
41146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class AgendaByDayAdapter extends BaseAdapter {
42146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_DAY = 0;
43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_MEETING = 1;
4413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static final int TYPE_LAST = 2;
45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
46146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final Context mContext;
47146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final AgendaAdapter mAgendaAdapter;
48146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final LayoutInflater mInflater;
49146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private ArrayList<RowInfo> mRowInfo;
50146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mTodayJulianDay;
519a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private Time mTmpTime;
529a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private String mTimeZone;
5323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    // Note: Formatter is not thread safe. Fine for now as it is only used by the main thread.
54e927121ee6406dfcd8bd9f2f650198dd1a76bcfbIsaac Katzenelson    private final Formatter mFormatter;
55e927121ee6406dfcd8bd9f2f650198dd1a76bcfbIsaac Katzenelson    private final StringBuilder mStringBuilder;
56146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
5713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static class ViewHolder {
58980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        TextView dayView;
5913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        TextView dateView;
606467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson        int julianDay;
61783835bceb03a7598678cd6883ba6bddde387302Michael Chan        boolean grayed;
6213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
6313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
64e927121ee6406dfcd8bd9f2f650198dd1a76bcfbIsaac Katzenelson    private final Runnable mTZUpdater = new Runnable() {
659a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        @Override
669a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        public void run() {
679a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            mTimeZone = Utils.getTimeZone(mContext, this);
689a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            mTmpTime = new Time(mTimeZone);
699a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            notifyDataSetChanged();
709a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        }
719a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    };
729a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
7313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public AgendaByDayAdapter(Context context) {
74146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mContext = context;
7513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaAdapter = new AgendaAdapter(context, R.layout.agenda_item);
7613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
7713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder = new StringBuilder(50);
7813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
799a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTimeZone = Utils.getTimeZone(context, mTZUpdater);
809a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTmpTime = new Time(mTimeZone);
81146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
82146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
83c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public long getInstanceId(int position) {
84c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (mRowInfo == null || position >= mRowInfo.size()) {
85c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return -1;
86c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
87c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        return mRowInfo.get(position).mInstanceId;
88c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
8937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
904b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson    public long getStartTime(int position) {
914b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson        if (mRowInfo == null || position >= mRowInfo.size()) {
924b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson            return -1;
934b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson        }
944b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson        return mRowInfo.get(position).mEventStartTimeMilli;
954b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson    }
964b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson
974b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson
9837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the position of a header of a specific item
9937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderPosition(int position) {
10037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (mRowInfo == null || position >= mRowInfo.size()) {
10137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
10237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
10337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
10437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        for (int i = position; i >=0; i --) {
10537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            RowInfo row = mRowInfo.get(i);
10637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            if (row != null && row.mType == TYPE_DAY)
10737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson                return i;
10837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
10937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
11037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
11137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
11237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the number of items in a section defined by a specific header location
11337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderItemsCount(int position) {
11437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (mRowInfo == null) {
11537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
11637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
11737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        int count = 0;
11837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        for (int i = position +1; i < mRowInfo.size(); i++) {
11937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            if (mRowInfo.get(i).mType != TYPE_MEETING) {
12037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson                return count;
12137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            }
12237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            count ++;
12337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
12437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return count;
12537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
12637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
12748bcc4cb015dbf802341698a3a04e28d2cfb2ddcMichael Chan    @Override
128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCount() {
129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mRowInfo.size();
131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getCount();
133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
13548bcc4cb015dbf802341698a3a04e28d2cfb2ddcMichael Chan    @Override
136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Object getItem(int position) {
137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return row;
141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
142980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return mAgendaAdapter.getItem(row.mPosition);
143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItem(position);
146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
14848bcc4cb015dbf802341698a3a04e28d2cfb2ddcMichael Chan    @Override
149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getItemId(int position) {
150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
153c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan                return -position;
154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
155980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return mAgendaAdapter.getItemId(row.mPosition);
156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItemId(position);
159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getViewTypeCount() {
163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return TYPE_LAST;
164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getItemViewType(int position) {
168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mRowInfo != null && mRowInfo.size() > position ?
169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mRowInfo.get(position).mType : TYPE_DAY;
170146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
1722d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public boolean isDayHeaderView(int position) {
1732d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        return (getItemViewType(position) == TYPE_DAY);
1742d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
1752d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
17648bcc4cb015dbf802341698a3a04e28d2cfb2ddcMichael Chan    @Override
177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public View getView(int position, View convertView, ViewGroup parent) {
178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if ((mRowInfo == null) || (position > mRowInfo.size())) {
179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If we have no row info, mAgendaAdapter returns the view.
180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mAgendaAdapter.getView(position, convertView, parent);
181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        RowInfo row = mRowInfo.get(position);
184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (row.mType == TYPE_DAY) {
18513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            ViewHolder holder = null;
18613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            View agendaDayView = null;
18713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if ((convertView != null) && (convertView.getTag() != null)) {
18813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Listview may get confused and pass in a different type of
18913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // view since we keep shifting data around. Not a big problem.
19013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Object tag = convertView.getTag();
19113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (tag instanceof ViewHolder) {
19213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    agendaDayView = convertView;
19313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    holder = (ViewHolder) tag;
1946467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                    holder.julianDay = row.mDay;
19513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
19613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
19713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
19813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (holder == null) {
199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Create a new AgendaView with a ViewHolder for fast access to
200146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // views w/o calling findViewById()
201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder = new ViewHolder();
202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView = mInflater.inflate(R.layout.agenda_day, parent, false);
203980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                holder.dayView = (TextView) agendaDayView.findViewById(R.id.day);
204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder.dateView = (TextView) agendaDayView.findViewById(R.id.date);
2056467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.julianDay = row.mDay;
206783835bceb03a7598678cd6883ba6bddde387302Michael Chan                holder.grayed = false;
207146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView.setTag(holder);
208146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
209146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
2109a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // Re-use the member variable "mTime" which is set to the local
2119a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // time zone.
2129a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // It's difficult to find and update all these adapters when the
2139a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // home tz changes so check it here and update if needed.
2149a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            String tz = Utils.getTimeZone(mContext, mTZUpdater);
2159a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            if (!TextUtils.equals(tz, mTmpTime.timezone)) {
2169a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                mTimeZone = tz;
2179a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                mTmpTime = new Time(tz);
2189a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            }
21913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
220980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Build the text for the day of the week.
221980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Should be yesterday/today/tomorrow (if applicable) + day of the week
222980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
223980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            Time date = mTmpTime;
224980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            long millis = date.setJulianDay(row.mDay);
225980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            int flags = DateUtils.FORMAT_SHOW_WEEKDAY;
22613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mStringBuilder.setLength(0);
227980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
2284eb3432c5b0109376bcce9236da71e6fb4324b90RoboErik            String dayViewText = Utils.getDayOfWeekString(row.mDay, mTodayJulianDay, millis,
2294eb3432c5b0109376bcce9236da71e6fb4324b90RoboErik                    mContext);
230980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
231980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Build text for the date
232980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Format should be month day
233980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
234980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mStringBuilder.setLength(0);
235980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            flags = DateUtils.FORMAT_SHOW_DATE;
236980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            String dateViewText = DateUtils.formatDateRange(mContext, mFormatter, millis, millis,
237980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                    flags, mTimeZone).toString();
2383cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
23923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (AgendaWindowAdapter.BASICLOG) {
240980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                dayViewText += " P:" + position;
24123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                dateViewText += " P:" + position;
24223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
243980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            holder.dayView.setText(dayViewText);
24423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            holder.dateView.setText(dateViewText);
2453cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
246783835bceb03a7598678cd6883ba6bddde387302Michael Chan            // Set the background of the view, it is grayed for day that are in the past and today
247783835bceb03a7598678cd6883ba6bddde387302Michael Chan            if (row.mDay > mTodayJulianDay) {
248783835bceb03a7598678cd6883ba6bddde387302Michael Chan                agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_primary);
249783835bceb03a7598678cd6883ba6bddde387302Michael Chan                holder.grayed = false;
250783835bceb03a7598678cd6883ba6bddde387302Michael Chan            } else {
251783835bceb03a7598678cd6883ba6bddde387302Michael Chan                agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_secondary);
252783835bceb03a7598678cd6883ba6bddde387302Michael Chan                holder.grayed = true;
253783835bceb03a7598678cd6883ba6bddde387302Michael Chan            }
254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return agendaDayView;
255146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else if (row.mType == TYPE_MEETING) {
256980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            View itemView = mAgendaAdapter.getView(row.mPosition, convertView, parent);
2574d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            AgendaAdapter.ViewHolder holder = ((AgendaAdapter.ViewHolder) itemView.getTag());
2584d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            TextView title = holder.title;
259cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            // The holder in the view stores information from the cursor, but the cursor has no
260cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            // notion of multi-day event and the start time of each instance of a multi-day event
261cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            // is the same.  RowInfo has the correct info , so take it from there.
262cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            holder.startTimeMilli = row.mEventStartTimeMilli;
2634d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            boolean allDay = holder.allDay;
264c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            if (AgendaWindowAdapter.BASICLOG) {
2652d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                title.setText(title.getText() + " P:" + position);
266c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            } else {
2672d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                title.setText(title.getText());
268c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            }
2692d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
27031412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            // if event in the past or started already, un-bold the title and set the background
271cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            if ((!allDay && row.mEventStartTimeMilli <= System.currentTimeMillis()) ||
27231412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson                    (allDay && row.mDay <= mTodayJulianDay)) {
273eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                itemView.setBackgroundResource(R.drawable.agenda_item_bg_secondary);
2744d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson                title.setTypeface(Typeface.DEFAULT);
2756467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = true;
2764d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            } else {
277eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                itemView.setBackgroundResource(R.drawable.agenda_item_bg_primary);
2784d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson                title.setTypeface(Typeface.DEFAULT_BOLD);
2796467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = false;
280980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            }
28131412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            holder.julianDay = row.mDay;
282980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            return itemView;
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else {
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Error
285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            throw new IllegalStateException("Unknown event type:" + row.mType);
286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void clearDayHeaderInfo() {
290146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = null;
291146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
293dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void changeCursor(DayAdapterInfo info) {
294dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        calculateDays(info);
295dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        mAgendaAdapter.changeCursor(info.cursor);
29613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
29713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
298dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void calculateDays(DayAdapterInfo dayAdapterInfo) {
299dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        Cursor cursor = dayAdapterInfo.cursor;
300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        ArrayList<RowInfo> rowInfo = new ArrayList<RowInfo>();
301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int prevStartDay = -1;
302c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
303c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        Time tempTime = new Time(mTimeZone);
304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long now = System.currentTimeMillis();
305c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        tempTime.set(now);
306c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        mTodayJulianDay = Time.getJulianDay(now, tempTime.gmtoff);
307c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        LinkedList<MultipleDayInfo> multipleDayList = new LinkedList<MultipleDayInfo>();
309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int position = 0; cursor.moveToNext(); position++) {
31013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY);
311c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            long id = cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID);
312c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            long startTime =  cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN);
313c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            long endTime =  cursor.getLong(AgendaWindowAdapter.INDEX_END);
314c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            long instanceId = cursor.getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID);
315c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            boolean allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0;
316c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (allDay) {
317c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                startTime = Utils.convertAlldayUtcToLocal(tempTime, startTime, mTimeZone);
318c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                endTime = Utils.convertAlldayUtcToLocal(tempTime, endTime, mTimeZone);
319c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
320dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
321dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            startDay = Math.max(startDay, dayAdapterInfo.start);
322e692869cbbc3d7430075bb739f0b0fa83cf91feaIsaac Katzenelson            // Make sure event's start time is not before the start of the day
323e692869cbbc3d7430075bb739f0b0fa83cf91feaIsaac Katzenelson            // (setJulianDay sets the time to 12:00am)
324e692869cbbc3d7430075bb739f0b0fa83cf91feaIsaac Katzenelson            long adapterStartTime = tempTime.setJulianDay(startDay);
325e692869cbbc3d7430075bb739f0b0fa83cf91feaIsaac Katzenelson            startTime = Math.max(startTime, adapterStartTime);
326dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (startDay != prevStartDay) {
328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Check if we skipped over any empty days
329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (prevStartDay == -1) {
330c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    rowInfo.add(new RowInfo(TYPE_DAY, startDay));
331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                } else {
332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If there are any multiple-day events that span the empty
333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // range of days, then create day headers and events for
334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // those multiple-day events.
335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    boolean dayHeaderAdded = false;
336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    for (int currentDay = prevStartDay + 1; currentDay <= startDay; currentDay++) {
337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = false;
338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        while (iter.hasNext()) {
340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            MultipleDayInfo info = iter.next();
341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this event has ended then remove it from the
342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // list.
343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (info.mEndDay < currentDay) {
344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                iter.remove();
345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                continue;
346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this is the first event for the day, then
349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // insert a day header.
350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (!dayHeaderAdded) {
351c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                rowInfo.add(new RowInfo(TYPE_DAY, currentDay));
352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                dayHeaderAdded = true;
353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
354b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                            long nextMidnight = Utils.getNextMidnight(tempTime,
355b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                                    info.mEventStartTimeMilli, mTimeZone);
356b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson
357b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                            long infoEndTime = (info.mEndDay == currentDay) ?
358b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                                    info.mEventEndTimeMilli : nextMidnight;
359c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            rowInfo.add(new RowInfo(TYPE_MEETING, currentDay, info.mPosition,
360c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                    info.mEventId, info.mEventStartTimeMilli,
361c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                    infoEndTime, info.mInstanceId, info.mAllDay));
362c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
363b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                            info.mEventStartTimeMilli = nextMidnight;
364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        }
365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If the day header was not added for the start day, then
368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // add it now.
369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
370c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        rowInfo.add(new RowInfo(TYPE_DAY, startDay));
371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                prevStartDay = startDay;
374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If this event spans multiple days, then add it to the multipleDay
377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // list.
37813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int endDay = cursor.getInt(AgendaWindowAdapter.INDEX_END_DAY);
379dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
380dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
381dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            endDay = Math.min(endDay, dayAdapterInfo.end);
382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endDay > startDay) {
3834b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                long nextMidnight = Utils.getNextMidnight(tempTime, startTime, mTimeZone);
3844b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                multipleDayList.add(new MultipleDayInfo(position, endDay, id, nextMidnight,
385c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        endTime, instanceId, allDay));
3864b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                // Add in the event for this cursor position - since it is the start of a multi-day
3874b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                // event, the end time is midnight
3884b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                rowInfo.add(new RowInfo(TYPE_MEETING, startDay, position, id, startTime,
3894b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                        nextMidnight, instanceId, allDay));
3904b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson            } else {
3914b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                // Add in the event for this cursor position
3924b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                rowInfo.add(new RowInfo(TYPE_MEETING, startDay, position, id, startTime, endTime,
3934b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                        instanceId, allDay));
394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // There are no more cursor events but we might still have multiple-day
398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events left.  So create day headers and events for those.
399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (prevStartDay > 0) {
400dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            for (int currentDay = prevStartDay + 1; currentDay <= dayAdapterInfo.end;
401dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan                    currentDay++) {
402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                boolean dayHeaderAdded = false;
403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                while (iter.hasNext()) {
405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    MultipleDayInfo info = iter.next();
406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this event has ended then remove it from the
407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // list.
408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (info.mEndDay < currentDay) {
409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        iter.remove();
410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        continue;
411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this is the first event for the day, then
414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // insert a day header.
415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
416c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        rowInfo.add(new RowInfo(TYPE_DAY, currentDay));
417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = true;
418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
419c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    long nextMidnight = Utils.getNextMidnight(tempTime, info.mEventStartTimeMilli,
420c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mTimeZone);
421c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    long infoEndTime =
422c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            (info.mEndDay == currentDay) ? info.mEventEndTimeMilli : nextMidnight;
423c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    rowInfo.add(new RowInfo(TYPE_MEETING, currentDay, info.mPosition,
424c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            info.mEventId, info.mEventStartTimeMilli, infoEndTime,
425c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            info.mInstanceId, info.mAllDay));
426c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
427c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    info.mEventStartTimeMilli = nextMidnight;
428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = rowInfo;
432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class RowInfo {
435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // mType is either a day header (TYPE_DAY) or an event (TYPE_MEETING)
436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mType;
437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
438980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        final int mDay;          // Julian day
439980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        final int mPosition;     // cursor position (not used for TYPE_DAY)
4402d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // This is used to mark a day header as the first day with events that is "today"
4412d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // or later. This flag is used by the adapter to create a view with a visual separator
4422d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // between the past and the present/future
4432d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        boolean mFirstDayAfterYesterday;
444c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mEventId;
445c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mEventStartTimeMilli;
446c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mEventEndTimeMilli;
447c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mInstanceId;
448c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final boolean mAllDay;
449c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
450c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        RowInfo(int type, int julianDay, int position, long id, long startTime, long endTime,
451c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                long instanceId, boolean allDay) {
452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mType = type;
453980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mDay = julianDay;
454980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mPosition = position;
455c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventId = id;
456c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventStartTimeMilli = startTime;
457c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventEndTimeMilli = endTime;
4582d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            mFirstDayAfterYesterday = false;
459c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mInstanceId = instanceId;
460c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mAllDay = allDay;
461c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
462c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
463c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        RowInfo(int type, int julianDay) {
464c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mType = type;
465c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mDay = julianDay;
466c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mPosition = 0;
467c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventId = 0;
468c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventStartTimeMilli = 0;
469c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventEndTimeMilli = 0;
470c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mFirstDayAfterYesterday = false;
471c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mInstanceId = -1;
472c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mAllDay = false;
473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class MultipleDayInfo {
477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mPosition;
478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mEndDay;
479c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mEventId;
480c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        long mEventStartTimeMilli;
481c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        long mEventEndTimeMilli;
482c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mInstanceId;
483c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final boolean mAllDay;
484c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
485c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        MultipleDayInfo(int position, int endDay, long id, long startTime, long endTime,
486c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                long instanceId, boolean allDay) {
487146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mPosition = position;
488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mEndDay = endDay;
489c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventId = id;
490c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventStartTimeMilli = startTime;
491c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventEndTimeMilli = endTime;
492c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mInstanceId = instanceId;
493c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mAllDay = allDay;
494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
498c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * Finds the position in the cursor of the event that best matches the time and Id.
499c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * It will try to find the event that has the specified id and start time, if such event
500c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * doesn't exist, it will return the event with a matching id that is closest to the start time.
501c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * If the id doesn't exist, it will return the event with start time closest to the specified
502c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * time.
503c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * @param time - start of event in milliseconds (or any arbitrary time if event id is unknown)
504c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * @param id - Event id (-1 if unknown).
505c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * @return Position of event (if found) or position of nearest event according to the time.
506c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     *         Zero if no event found
507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
508c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public int findEventPositionNearestTime(Time time, long id) {
509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null) {
510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
511146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long millis = time.toMillis(false /* use isDst */);
513c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        long minDistance =  Integer.MAX_VALUE;  // some big number
5144b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson        long idFoundMinDistance =  Integer.MAX_VALUE;  // some big number
515146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minIndex = 0;
516c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int idFoundMinIndex = 0;
517c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int eventInTimeIndex = -1;
518c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int allDayEventInTimeIndex = -1;
519c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int allDayEventDay = 0;
520c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int minDay = 0;
521c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        boolean idFound = false;
522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
523c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
524c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // Loop through the events and find the best match
525c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // 1. Event id and start time matches requested id and time
526c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // 2. Event id matches and closest time
527812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson        // 3. No event id match , time matches a all day event (midnight)
528812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson        // 4. No event id match , time is between event start and end
529812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson        // 5. No event id match , all day event
530812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson        // 6. The closest event to the requested time
531c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = 0; index < len; index++) {
533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
535c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                continue;
536c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
537c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
538c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Found exact match - done
539c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (row.mEventId == id) {
540c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                if (row.mEventStartTimeMilli == millis) {
541146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    return index;
542146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
543c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
544c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // Not an exact match, Save event index if it is the closest to time so far
545c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                long distance = Math.abs(millis - row.mEventStartTimeMilli);
5464b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                if (distance < idFoundMinDistance) {
5474b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                    idFoundMinDistance = distance;
548c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    idFoundMinIndex = index;
549c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                }
550c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                idFound = true;
551c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
552c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (!idFound) {
553c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // Found an event that contains the requested time
554c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                if (millis >= row.mEventStartTimeMilli && millis <= row.mEventEndTimeMilli) {
555c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (row.mAllDay) {
5566bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                        if (allDayEventInTimeIndex == -1) {
5576bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                            allDayEventInTimeIndex = index;
5586bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                            allDayEventDay = row.mDay;
559812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson                        }
5606bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                    } else if (eventInTimeIndex == -1){
561c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        eventInTimeIndex = index;
562c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
5636bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                } else if (eventInTimeIndex == -1){
564c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    // Save event index if it is the closest to time so far
565c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    long distance = Math.abs(millis - row.mEventStartTimeMilli);
566c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (distance < minDistance) {
567c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        minDistance = distance;
568c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        minIndex = index;
569c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        minDay = row.mDay;
570c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
571146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
572146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
573146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
574c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // We didn't find an exact match so take the best matching event
5756bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // Closest event with the same id
576c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (idFound) {
577c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return idFoundMinIndex;
578c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
5796bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // Event which occurs at the searched time
580c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (eventInTimeIndex != -1) {
581c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return eventInTimeIndex;
5826bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // All day event which occurs at the same day of the searched time as long as there is
5836bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // no regular event at the same day
584c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        } else if (allDayEventInTimeIndex != -1 && minDay != allDayEventDay) {
585c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return allDayEventInTimeIndex;
586c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
5876bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // Closest event
588146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return minIndex;
589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
590146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
591c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
592146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
5932d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Returns a flag indicating if this position is the first day after "yesterday" that has
5942d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * events in it.
5952d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     *
5962d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * @return a flag indicating if this is the "first day after yesterday"
5972d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     */
5982d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public boolean isFirstDayAfterYesterday(int position) {
5992d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        int headerPos = getHeaderPosition(position);
6002d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        RowInfo row = mRowInfo.get(headerPos);
6012d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        if (row != null) {
6022d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            return row.mFirstDayAfterYesterday;
6032d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        }
6042d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        return false;
6052d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
6062d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
6072d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    /**
608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Finds the Julian day containing the event at the given position.
609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param position the list position of an event
611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the Julian day containing that event
612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findJulianDayFromPosition(int position) {
614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null || position < 0) {
615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (position >= len) return 0;  // no row info at this position
620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
621146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = position; index >= 0; index--) {
622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
624980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return row.mDay;
625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return 0;
628146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
629146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
630146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
6312d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Marks the current row as the first day that has events after "yesterday".
6322d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Used to mark the separation between the past and the present/future
6332d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     *
6342d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * @param position in the adapter
6352d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     */
6362d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public void setAsFirstDayAfterYesterday(int position) {
6372d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        if (mRowInfo == null || position < 0 || position > mRowInfo.size()) {
6382d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            return;
6392d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        }
6402d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        RowInfo row = mRowInfo.get(position);
6412d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        row.mFirstDayAfterYesterday = true;
6422d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
6432d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
6442d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    /**
645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Converts a list position to a cursor position.  The list contains
646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * day headers as well as events.  The cursor contains only events.
647146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
648146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param listPos the list position of an event
649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the corresponding cursor position of that event
650c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     *         if the position point to day header , it will give the position of the next event
651c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     *         negated.
652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCursorPosition(int listPos) {
654146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && listPos >= 0) {
655146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(listPos);
656146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_MEETING) {
657980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return row.mPosition;
65813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else {
65913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int nextPos = listPos + 1;
66013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (nextPos < mRowInfo.size()) {
66113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    nextPos = getCursorPosition(nextPos);
66213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (nextPos >= 0) {
66313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        return -nextPos;
66413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
66513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
66813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return Integer.MIN_VALUE;
669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
672146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean areAllItemsEnabled() {
673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return false;
674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
675146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
677146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isEnabled(int position) {
678146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && position < mRowInfo.size()) {
679146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return row.mType == TYPE_MEETING;
681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
682146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return true;
683146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
684146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
685