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
199a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport com.android.calendar.R;
209a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport com.android.calendar.Utils;
219a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport com.android.calendar.agenda.AgendaWindowAdapter.DayAdapterInfo;
229a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
23146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context;
24146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor;
252d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelsonimport android.graphics.Typeface;
269a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport android.text.TextUtils;
27146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils;
28146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time;
29e692869cbbc3d7430075bb739f0b0fa83cf91feaIsaac Katzenelsonimport android.util.Log;
30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.LayoutInflater;
31146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View;
32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewGroup;
33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.BaseAdapter;
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.TextView;
35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList;
3713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Formatter;
38146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Iterator;
39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.LinkedList;
4013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Locale;
41146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
42146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class AgendaByDayAdapter extends BaseAdapter {
43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_DAY = 0;
44146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_MEETING = 1;
4513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static final int TYPE_LAST = 2;
46146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
47146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final Context mContext;
48146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final AgendaAdapter mAgendaAdapter;
49146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final LayoutInflater mInflater;
50146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private ArrayList<RowInfo> mRowInfo;
51146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mTodayJulianDay;
529a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private Time mTmpTime;
539a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private String mTimeZone;
5423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    // Note: Formatter is not thread safe. Fine for now as it is only used by the main thread.
55e927121ee6406dfcd8bd9f2f650198dd1a76bcfbIsaac Katzenelson    private final Formatter mFormatter;
56e927121ee6406dfcd8bd9f2f650198dd1a76bcfbIsaac Katzenelson    private final StringBuilder mStringBuilder;
57146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
5813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static class ViewHolder {
59980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        TextView dayView;
6013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        TextView dateView;
616467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson        int julianDay;
62783835bceb03a7598678cd6883ba6bddde387302Michael Chan        boolean grayed;
6313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
6413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
65e927121ee6406dfcd8bd9f2f650198dd1a76bcfbIsaac Katzenelson    private final Runnable mTZUpdater = new Runnable() {
669a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        @Override
679a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        public void run() {
689a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            mTimeZone = Utils.getTimeZone(mContext, this);
699a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            mTmpTime = new Time(mTimeZone);
709a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            notifyDataSetChanged();
719a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        }
729a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    };
739a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
7413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public AgendaByDayAdapter(Context context) {
75146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mContext = context;
7613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaAdapter = new AgendaAdapter(context, R.layout.agenda_item);
7713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
7813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder = new StringBuilder(50);
7913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
809a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTimeZone = Utils.getTimeZone(context, mTZUpdater);
819a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTmpTime = new Time(mTimeZone);
82146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
83146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
84c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public long getInstanceId(int position) {
85c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (mRowInfo == null || position >= mRowInfo.size()) {
86c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return -1;
87c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
88c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        return mRowInfo.get(position).mInstanceId;
89c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
9037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
914b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson    public long getStartTime(int position) {
924b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson        if (mRowInfo == null || position >= mRowInfo.size()) {
934b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson            return -1;
944b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson        }
954b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson        return mRowInfo.get(position).mEventStartTimeMilli;
964b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson    }
974b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson
984b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson
9937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the position of a header of a specific item
10037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderPosition(int position) {
10137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (mRowInfo == null || position >= mRowInfo.size()) {
10237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
10337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
10437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
10537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        for (int i = position; i >=0; i --) {
10637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            RowInfo row = mRowInfo.get(i);
10737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            if (row != null && row.mType == TYPE_DAY)
10837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson                return i;
10937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
11037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
11137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
11237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
11337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the number of items in a section defined by a specific header location
11437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderItemsCount(int position) {
11537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (mRowInfo == null) {
11637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
11737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
11837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        int count = 0;
11937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        for (int i = position +1; i < mRowInfo.size(); i++) {
12037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            if (mRowInfo.get(i).mType != TYPE_MEETING) {
12137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson                return count;
12237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            }
12337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            count ++;
12437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
12537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return count;
12637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
12737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
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
135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Object getItem(int position) {
136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
138146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return row;
140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
141980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return mAgendaAdapter.getItem(row.mPosition);
142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItem(position);
145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getItemId(int position) {
148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
151c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan                return -position;
152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
153980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return mAgendaAdapter.getItemId(row.mPosition);
154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItemId(position);
157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getViewTypeCount() {
161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return TYPE_LAST;
162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getItemViewType(int position) {
166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mRowInfo != null && mRowInfo.size() > position ?
167146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mRowInfo.get(position).mType : TYPE_DAY;
168146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
169146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
1702d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public boolean isDayHeaderView(int position) {
1712d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        return (getItemViewType(position) == TYPE_DAY);
1722d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
1732d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public View getView(int position, View convertView, ViewGroup parent) {
175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if ((mRowInfo == null) || (position > mRowInfo.size())) {
176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If we have no row info, mAgendaAdapter returns the view.
177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mAgendaAdapter.getView(position, convertView, parent);
178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
179146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
180146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        RowInfo row = mRowInfo.get(position);
181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (row.mType == TYPE_DAY) {
18213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            ViewHolder holder = null;
18313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            View agendaDayView = null;
18413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if ((convertView != null) && (convertView.getTag() != null)) {
18513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Listview may get confused and pass in a different type of
18613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // view since we keep shifting data around. Not a big problem.
18713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Object tag = convertView.getTag();
18813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (tag instanceof ViewHolder) {
18913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    agendaDayView = convertView;
19013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    holder = (ViewHolder) tag;
1916467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                    holder.julianDay = row.mDay;
19213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
19313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
19413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
19513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (holder == null) {
196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Create a new AgendaView with a ViewHolder for fast access to
197146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // views w/o calling findViewById()
198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder = new ViewHolder();
199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView = mInflater.inflate(R.layout.agenda_day, parent, false);
200980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                holder.dayView = (TextView) agendaDayView.findViewById(R.id.day);
201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder.dateView = (TextView) agendaDayView.findViewById(R.id.date);
2026467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.julianDay = row.mDay;
203783835bceb03a7598678cd6883ba6bddde387302Michael Chan                holder.grayed = false;
204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView.setTag(holder);
205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
2079a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // Re-use the member variable "mTime" which is set to the local
2089a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // time zone.
2099a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // It's difficult to find and update all these adapters when the
2109a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // home tz changes so check it here and update if needed.
2119a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            String tz = Utils.getTimeZone(mContext, mTZUpdater);
2129a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            if (!TextUtils.equals(tz, mTmpTime.timezone)) {
2139a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                mTimeZone = tz;
2149a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                mTmpTime = new Time(tz);
2159a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            }
21613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
217980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Build the text for the day of the week.
218980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Should be yesterday/today/tomorrow (if applicable) + day of the week
219980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
220980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            Time date = mTmpTime;
221980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            long millis = date.setJulianDay(row.mDay);
222980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            int flags = DateUtils.FORMAT_SHOW_WEEKDAY;
22313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mStringBuilder.setLength(0);
224980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
2254eb3432c5b0109376bcce9236da71e6fb4324b90RoboErik            String dayViewText = Utils.getDayOfWeekString(row.mDay, mTodayJulianDay, millis,
2264eb3432c5b0109376bcce9236da71e6fb4324b90RoboErik                    mContext);
227980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
228980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Build text for the date
229980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Format should be month day
230980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
231980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mStringBuilder.setLength(0);
232980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            flags = DateUtils.FORMAT_SHOW_DATE;
233980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            String dateViewText = DateUtils.formatDateRange(mContext, mFormatter, millis, millis,
234980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                    flags, mTimeZone).toString();
2353cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
23623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (AgendaWindowAdapter.BASICLOG) {
237980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                dayViewText += " P:" + position;
23823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                dateViewText += " P:" + position;
23923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
240980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            holder.dayView.setText(dayViewText);
24123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            holder.dateView.setText(dateViewText);
2423cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
243783835bceb03a7598678cd6883ba6bddde387302Michael Chan            // Set the background of the view, it is grayed for day that are in the past and today
244783835bceb03a7598678cd6883ba6bddde387302Michael Chan            if (row.mDay > mTodayJulianDay) {
245783835bceb03a7598678cd6883ba6bddde387302Michael Chan                agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_primary);
246783835bceb03a7598678cd6883ba6bddde387302Michael Chan                holder.grayed = false;
247783835bceb03a7598678cd6883ba6bddde387302Michael Chan            } else {
248783835bceb03a7598678cd6883ba6bddde387302Michael Chan                agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_secondary);
249783835bceb03a7598678cd6883ba6bddde387302Michael Chan                holder.grayed = true;
250783835bceb03a7598678cd6883ba6bddde387302Michael Chan            }
251146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return agendaDayView;
252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else if (row.mType == TYPE_MEETING) {
253980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            View itemView = mAgendaAdapter.getView(row.mPosition, convertView, parent);
2544d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            AgendaAdapter.ViewHolder holder = ((AgendaAdapter.ViewHolder) itemView.getTag());
2554d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            TextView title = holder.title;
256cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            // The holder in the view stores information from the cursor, but the cursor has no
257cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            // notion of multi-day event and the start time of each instance of a multi-day event
258cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            // is the same.  RowInfo has the correct info , so take it from there.
259cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            holder.startTimeMilli = row.mEventStartTimeMilli;
2604d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            boolean allDay = holder.allDay;
261c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            if (AgendaWindowAdapter.BASICLOG) {
2622d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                title.setText(title.getText() + " P:" + position);
263c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            } else {
2642d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                title.setText(title.getText());
265c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            }
2662d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
26731412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            // if event in the past or started already, un-bold the title and set the background
268cba765c540df848c75e986de8f10ced46e500151Isaac Katzenelson            if ((!allDay && row.mEventStartTimeMilli <= System.currentTimeMillis()) ||
26931412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson                    (allDay && row.mDay <= mTodayJulianDay)) {
270eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                itemView.setBackgroundResource(R.drawable.agenda_item_bg_secondary);
2714d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson                title.setTypeface(Typeface.DEFAULT);
2726467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = true;
2734d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            } else {
274eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                itemView.setBackgroundResource(R.drawable.agenda_item_bg_primary);
2754d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson                title.setTypeface(Typeface.DEFAULT_BOLD);
2766467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = false;
277980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            }
27831412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            holder.julianDay = row.mDay;
279980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            return itemView;
280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else {
281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Error
282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            throw new IllegalStateException("Unknown event type:" + row.mType);
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void clearDayHeaderInfo() {
287146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = null;
288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
289146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
290dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void changeCursor(DayAdapterInfo info) {
291dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        calculateDays(info);
292dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        mAgendaAdapter.changeCursor(info.cursor);
29313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
29413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
295dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void calculateDays(DayAdapterInfo dayAdapterInfo) {
296dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        Cursor cursor = dayAdapterInfo.cursor;
297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        ArrayList<RowInfo> rowInfo = new ArrayList<RowInfo>();
298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int prevStartDay = -1;
299c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
300c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        Time tempTime = new Time(mTimeZone);
301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long now = System.currentTimeMillis();
302c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        tempTime.set(now);
303c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        mTodayJulianDay = Time.getJulianDay(now, tempTime.gmtoff);
304c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        LinkedList<MultipleDayInfo> multipleDayList = new LinkedList<MultipleDayInfo>();
306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int position = 0; cursor.moveToNext(); position++) {
30713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY);
308c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            long id = cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID);
309c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            long startTime =  cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN);
310c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            long endTime =  cursor.getLong(AgendaWindowAdapter.INDEX_END);
311c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            long instanceId = cursor.getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID);
312c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            boolean allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0;
313c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (allDay) {
314c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                startTime = Utils.convertAlldayUtcToLocal(tempTime, startTime, mTimeZone);
315c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                endTime = Utils.convertAlldayUtcToLocal(tempTime, endTime, mTimeZone);
316c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
317dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
318dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            startDay = Math.max(startDay, dayAdapterInfo.start);
319e692869cbbc3d7430075bb739f0b0fa83cf91feaIsaac Katzenelson            // Make sure event's start time is not before the start of the day
320e692869cbbc3d7430075bb739f0b0fa83cf91feaIsaac Katzenelson            // (setJulianDay sets the time to 12:00am)
321e692869cbbc3d7430075bb739f0b0fa83cf91feaIsaac Katzenelson            long adapterStartTime = tempTime.setJulianDay(startDay);
322e692869cbbc3d7430075bb739f0b0fa83cf91feaIsaac Katzenelson            startTime = Math.max(startTime, adapterStartTime);
323dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (startDay != prevStartDay) {
325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Check if we skipped over any empty days
326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (prevStartDay == -1) {
327c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    rowInfo.add(new RowInfo(TYPE_DAY, startDay));
328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                } else {
329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If there are any multiple-day events that span the empty
330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // range of days, then create day headers and events for
331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // those multiple-day events.
332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    boolean dayHeaderAdded = false;
333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    for (int currentDay = prevStartDay + 1; currentDay <= startDay; currentDay++) {
334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = false;
335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        while (iter.hasNext()) {
337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            MultipleDayInfo info = iter.next();
338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this event has ended then remove it from the
339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // list.
340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (info.mEndDay < currentDay) {
341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                iter.remove();
342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                continue;
343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this is the first event for the day, then
346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // insert a day header.
347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (!dayHeaderAdded) {
348c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                rowInfo.add(new RowInfo(TYPE_DAY, currentDay));
349146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                dayHeaderAdded = true;
350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
351b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                            long nextMidnight = Utils.getNextMidnight(tempTime,
352b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                                    info.mEventStartTimeMilli, mTimeZone);
353b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson
354b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                            long infoEndTime = (info.mEndDay == currentDay) ?
355b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                                    info.mEventEndTimeMilli : nextMidnight;
356c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            rowInfo.add(new RowInfo(TYPE_MEETING, currentDay, info.mPosition,
357c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                    info.mEventId, info.mEventStartTimeMilli,
358c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                    infoEndTime, info.mInstanceId, info.mAllDay));
359c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
360b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                            info.mEventStartTimeMilli = nextMidnight;
361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        }
362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If the day header was not added for the start day, then
365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // add it now.
366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
367c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        rowInfo.add(new RowInfo(TYPE_DAY, startDay));
368146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                prevStartDay = startDay;
371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If this event spans multiple days, then add it to the multipleDay
374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // list.
37513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int endDay = cursor.getInt(AgendaWindowAdapter.INDEX_END_DAY);
376dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
377dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
378dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            endDay = Math.min(endDay, dayAdapterInfo.end);
379146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endDay > startDay) {
3804b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                long nextMidnight = Utils.getNextMidnight(tempTime, startTime, mTimeZone);
3814b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                multipleDayList.add(new MultipleDayInfo(position, endDay, id, nextMidnight,
382c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        endTime, instanceId, allDay));
3834b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                // Add in the event for this cursor position - since it is the start of a multi-day
3844b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                // event, the end time is midnight
3854b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                rowInfo.add(new RowInfo(TYPE_MEETING, startDay, position, id, startTime,
3864b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                        nextMidnight, instanceId, allDay));
3874b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson            } else {
3884b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                // Add in the event for this cursor position
3894b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                rowInfo.add(new RowInfo(TYPE_MEETING, startDay, position, id, startTime, endTime,
3904b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                        instanceId, allDay));
391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // There are no more cursor events but we might still have multiple-day
395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events left.  So create day headers and events for those.
396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (prevStartDay > 0) {
397dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            for (int currentDay = prevStartDay + 1; currentDay <= dayAdapterInfo.end;
398dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan                    currentDay++) {
399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                boolean dayHeaderAdded = false;
400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                while (iter.hasNext()) {
402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    MultipleDayInfo info = iter.next();
403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this event has ended then remove it from the
404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // list.
405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (info.mEndDay < currentDay) {
406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        iter.remove();
407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        continue;
408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this is the first event for the day, then
411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // insert a day header.
412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
413c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        rowInfo.add(new RowInfo(TYPE_DAY, currentDay));
414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = true;
415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
416c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    long nextMidnight = Utils.getNextMidnight(tempTime, info.mEventStartTimeMilli,
417c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mTimeZone);
418c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    long infoEndTime =
419c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            (info.mEndDay == currentDay) ? info.mEventEndTimeMilli : nextMidnight;
420c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    rowInfo.add(new RowInfo(TYPE_MEETING, currentDay, info.mPosition,
421c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            info.mEventId, info.mEventStartTimeMilli, infoEndTime,
422c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            info.mInstanceId, info.mAllDay));
423c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
424c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    info.mEventStartTimeMilli = nextMidnight;
425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = rowInfo;
429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class RowInfo {
432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // mType is either a day header (TYPE_DAY) or an event (TYPE_MEETING)
433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mType;
434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
435980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        final int mDay;          // Julian day
436980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        final int mPosition;     // cursor position (not used for TYPE_DAY)
4372d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // This is used to mark a day header as the first day with events that is "today"
4382d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // or later. This flag is used by the adapter to create a view with a visual separator
4392d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // between the past and the present/future
4402d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        boolean mFirstDayAfterYesterday;
441c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mEventId;
442c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mEventStartTimeMilli;
443c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mEventEndTimeMilli;
444c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mInstanceId;
445c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final boolean mAllDay;
446c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
447c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        RowInfo(int type, int julianDay, int position, long id, long startTime, long endTime,
448c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                long instanceId, boolean allDay) {
449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mType = type;
450980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mDay = julianDay;
451980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mPosition = position;
452c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventId = id;
453c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventStartTimeMilli = startTime;
454c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventEndTimeMilli = endTime;
4552d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            mFirstDayAfterYesterday = false;
456c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mInstanceId = instanceId;
457c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mAllDay = allDay;
458c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
459c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
460c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        RowInfo(int type, int julianDay) {
461c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mType = type;
462c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mDay = julianDay;
463c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mPosition = 0;
464c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventId = 0;
465c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventStartTimeMilli = 0;
466c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventEndTimeMilli = 0;
467c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mFirstDayAfterYesterday = false;
468c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mInstanceId = -1;
469c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mAllDay = false;
470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class MultipleDayInfo {
474146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mPosition;
475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mEndDay;
476c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mEventId;
477c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        long mEventStartTimeMilli;
478c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        long mEventEndTimeMilli;
479c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final long mInstanceId;
480c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        final boolean mAllDay;
481c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
482c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        MultipleDayInfo(int position, int endDay, long id, long startTime, long endTime,
483c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                long instanceId, boolean allDay) {
484146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mPosition = position;
485146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mEndDay = endDay;
486c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventId = id;
487c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventStartTimeMilli = startTime;
488c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mEventEndTimeMilli = endTime;
489c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mInstanceId = instanceId;
490c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mAllDay = allDay;
491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
495c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * Finds the position in the cursor of the event that best matches the time and Id.
496c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * It will try to find the event that has the specified id and start time, if such event
497c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * doesn't exist, it will return the event with a matching id that is closest to the start time.
498c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * If the id doesn't exist, it will return the event with start time closest to the specified
499c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * time.
500c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * @param time - start of event in milliseconds (or any arbitrary time if event id is unknown)
501c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * @param id - Event id (-1 if unknown).
502c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     * @return Position of event (if found) or position of nearest event according to the time.
503c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     *         Zero if no event found
504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
505c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public int findEventPositionNearestTime(Time time, long id) {
506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null) {
507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
508146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long millis = time.toMillis(false /* use isDst */);
510c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        long minDistance =  Integer.MAX_VALUE;  // some big number
5114b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson        long idFoundMinDistance =  Integer.MAX_VALUE;  // some big number
512146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minIndex = 0;
513c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int idFoundMinIndex = 0;
514c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int eventInTimeIndex = -1;
515c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int allDayEventInTimeIndex = -1;
516c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int allDayEventDay = 0;
517c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        int minDay = 0;
518c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        boolean idFound = false;
519146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
520c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
521c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // Loop through the events and find the best match
522c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // 1. Event id and start time matches requested id and time
523c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // 2. Event id matches and closest time
524812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson        // 3. No event id match , time matches a all day event (midnight)
525812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson        // 4. No event id match , time is between event start and end
526812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson        // 5. No event id match , all day event
527812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson        // 6. The closest event to the requested time
528c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = 0; index < len; index++) {
530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
532c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                continue;
533c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
534c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
535c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Found exact match - done
536c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (row.mEventId == id) {
537c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                if (row.mEventStartTimeMilli == millis) {
538146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    return index;
539146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
540c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
541c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // Not an exact match, Save event index if it is the closest to time so far
542c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                long distance = Math.abs(millis - row.mEventStartTimeMilli);
5434b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                if (distance < idFoundMinDistance) {
5444b46839d81e351314da1bdf7cad1f111dd6d671cIsaac Katzenelson                    idFoundMinDistance = distance;
545c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    idFoundMinIndex = index;
546c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                }
547c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                idFound = true;
548c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
549c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (!idFound) {
550c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // Found an event that contains the requested time
551c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                if (millis >= row.mEventStartTimeMilli && millis <= row.mEventEndTimeMilli) {
552c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (row.mAllDay) {
5536bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                        if (allDayEventInTimeIndex == -1) {
5546bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                            allDayEventInTimeIndex = index;
5556bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                            allDayEventDay = row.mDay;
556812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson                        }
5576bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                    } else if (eventInTimeIndex == -1){
558c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        eventInTimeIndex = index;
559c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
5606bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                } else if (eventInTimeIndex == -1){
561c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    // Save event index if it is the closest to time so far
562c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    long distance = Math.abs(millis - row.mEventStartTimeMilli);
563c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (distance < minDistance) {
564c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        minDistance = distance;
565c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        minIndex = index;
566c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        minDay = row.mDay;
567c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
568146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
569146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
570146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
571c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // We didn't find an exact match so take the best matching event
5726bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // Closest event with the same id
573c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (idFound) {
574c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return idFoundMinIndex;
575c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
5766bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // Event which occurs at the searched time
577c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (eventInTimeIndex != -1) {
578c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return eventInTimeIndex;
5796bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // All day event which occurs at the same day of the searched time as long as there is
5806bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // no regular event at the same day
581c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        } else if (allDayEventInTimeIndex != -1 && minDay != allDayEventDay) {
582c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return allDayEventInTimeIndex;
583c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
5846bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson        // Closest event
585146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return minIndex;
586146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
587146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
588c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
589146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
5902d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Returns a flag indicating if this position is the first day after "yesterday" that has
5912d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * events in it.
5922d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     *
5932d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * @return a flag indicating if this is the "first day after yesterday"
5942d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     */
5952d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public boolean isFirstDayAfterYesterday(int position) {
5962d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        int headerPos = getHeaderPosition(position);
5972d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        RowInfo row = mRowInfo.get(headerPos);
5982d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        if (row != null) {
5992d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            return row.mFirstDayAfterYesterday;
6002d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        }
6012d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        return false;
6022d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
6032d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
6042d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    /**
605146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Finds the Julian day containing the event at the given position.
606146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
607146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param position the list position of an event
608146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the Julian day containing that event
609146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
610146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findJulianDayFromPosition(int position) {
611146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null || position < 0) {
612146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
613146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
614146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
615146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
616146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (position >= len) return 0;  // no row info at this position
617146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
618146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = position; index >= 0; index--) {
619146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
620146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
621980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return row.mDay;
622146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
623146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
624146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return 0;
625146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
626146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
627146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
6282d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Marks the current row as the first day that has events after "yesterday".
6292d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Used to mark the separation between the past and the present/future
6302d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     *
6312d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * @param position in the adapter
6322d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     */
6332d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public void setAsFirstDayAfterYesterday(int position) {
6342d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        if (mRowInfo == null || position < 0 || position > mRowInfo.size()) {
6352d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            return;
6362d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        }
6372d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        RowInfo row = mRowInfo.get(position);
6382d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        row.mFirstDayAfterYesterday = true;
6392d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
6402d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
6412d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    /**
642146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Converts a list position to a cursor position.  The list contains
643146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * day headers as well as events.  The cursor contains only events.
644146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
645146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param listPos the list position of an event
646146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the corresponding cursor position of that event
647c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     *         if the position point to day header , it will give the position of the next event
648c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson     *         negated.
649146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
650146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCursorPosition(int listPos) {
651146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && listPos >= 0) {
652146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(listPos);
653146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_MEETING) {
654980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return row.mPosition;
65513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else {
65613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int nextPos = listPos + 1;
65713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (nextPos < mRowInfo.size()) {
65813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    nextPos = getCursorPosition(nextPos);
65913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (nextPos >= 0) {
66013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        return -nextPos;
66113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
66213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
663146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
664146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
66513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return Integer.MIN_VALUE;
666146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
667146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
668146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
669146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean areAllItemsEnabled() {
670146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return false;
671146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
672146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
673146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
674146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isEnabled(int position) {
675146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && position < mRowInfo.size()) {
676146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
677146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return row.mType == TYPE_MEETING;
678146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
679146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return true;
680146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
681146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
682