AgendaByDayAdapter.java revision 31412a0fea756e0da0bcbdf3cdffe4efae21cdbe
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;
29146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.LayoutInflater;
30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View;
31146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewGroup;
32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.BaseAdapter;
33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.TextView;
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
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.
5423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    private Formatter mFormatter;
5513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private StringBuilder mStringBuilder;
56146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
5713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static class ViewHolder {
58980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        TextView dayView;
5913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        TextView dateView;
606467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson        int julianDay;
616467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson        boolean grayed;
6213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
6313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
649a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private 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
8337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
8437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the position of a header of a specific item
8537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderPosition(int position) {
8637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (mRowInfo == null || position >= mRowInfo.size()) {
8737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
8837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
8937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
9037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        for (int i = position; i >=0; i --) {
9137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            RowInfo row = mRowInfo.get(i);
9237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            if (row != null && row.mType == TYPE_DAY)
9337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson                return i;
9437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
9537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
9637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
9737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
9837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the number of items in a section defined by a specific header location
9937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderItemsCount(int position) {
10037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (mRowInfo == null) {
10137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
10237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
10337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        int count = 0;
10437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        for (int i = position +1; i < mRowInfo.size(); i++) {
10537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            if (mRowInfo.get(i).mType != TYPE_MEETING) {
10637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson                return count;
10737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            }
10837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            count ++;
10937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
11037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return count;
11137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
11237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
113146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCount() {
114146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
115146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mRowInfo.size();
116146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
117146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getCount();
118146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
119146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
120146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Object getItem(int position) {
121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return row;
125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
126980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return mAgendaAdapter.getItem(row.mPosition);
127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItem(position);
130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getItemId(int position) {
133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
136c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan                return -position;
137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
138980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return mAgendaAdapter.getItemId(row.mPosition);
139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItemId(position);
142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getViewTypeCount() {
146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return TYPE_LAST;
147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
148146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
150146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getItemViewType(int position) {
151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mRowInfo != null && mRowInfo.size() > position ?
152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mRowInfo.get(position).mType : TYPE_DAY;
153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
1552d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public boolean isDayHeaderView(int position) {
1562d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        return (getItemViewType(position) == TYPE_DAY);
1572d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
1582d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public View getView(int position, View convertView, ViewGroup parent) {
160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if ((mRowInfo == null) || (position > mRowInfo.size())) {
161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If we have no row info, mAgendaAdapter returns the view.
162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mAgendaAdapter.getView(position, convertView, parent);
163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        RowInfo row = mRowInfo.get(position);
166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (row.mType == TYPE_DAY) {
16713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            ViewHolder holder = null;
16813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            View agendaDayView = null;
16913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if ((convertView != null) && (convertView.getTag() != null)) {
17013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Listview may get confused and pass in a different type of
17113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // view since we keep shifting data around. Not a big problem.
17213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Object tag = convertView.getTag();
17313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (tag instanceof ViewHolder) {
17413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    agendaDayView = convertView;
17513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    holder = (ViewHolder) tag;
1766467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                    holder.julianDay = row.mDay;
17713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
17813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
17913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
18013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (holder == null) {
181146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Create a new AgendaView with a ViewHolder for fast access to
182146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // views w/o calling findViewById()
183146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder = new ViewHolder();
184146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView = mInflater.inflate(R.layout.agenda_day, parent, false);
185980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                holder.dayView = (TextView) agendaDayView.findViewById(R.id.day);
186146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder.dateView = (TextView) agendaDayView.findViewById(R.id.date);
1876467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.julianDay = row.mDay;
1886467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = false;
189146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView.setTag(holder);
190146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
191146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
1929a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // Re-use the member variable "mTime" which is set to the local
1939a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // time zone.
1949a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // It's difficult to find and update all these adapters when the
1959a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // home tz changes so check it here and update if needed.
1969a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            String tz = Utils.getTimeZone(mContext, mTZUpdater);
1979a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            if (!TextUtils.equals(tz, mTmpTime.timezone)) {
1989a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                mTimeZone = tz;
1999a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                mTmpTime = new Time(tz);
2009a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            }
20113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
202980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Build the text for the day of the week.
203980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Should be yesterday/today/tomorrow (if applicable) + day of the week
204980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
205980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            Time date = mTmpTime;
206980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            long millis = date.setJulianDay(row.mDay);
207980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            int flags = DateUtils.FORMAT_SHOW_WEEKDAY;
20813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mStringBuilder.setLength(0);
209980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
2104eb3432c5b0109376bcce9236da71e6fb4324b90RoboErik            String dayViewText = Utils.getDayOfWeekString(row.mDay, mTodayJulianDay, millis,
2114eb3432c5b0109376bcce9236da71e6fb4324b90RoboErik                    mContext);
212980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
213980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Build text for the date
214980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Format should be month day
215980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
216980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mStringBuilder.setLength(0);
217980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            flags = DateUtils.FORMAT_SHOW_DATE;
218980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            String dateViewText = DateUtils.formatDateRange(mContext, mFormatter, millis, millis,
219980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                    flags, mTimeZone).toString();
2203cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
22123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (AgendaWindowAdapter.BASICLOG) {
222980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                dayViewText += " P:" + position;
22323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                dateViewText += " P:" + position;
22423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
225980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            holder.dayView.setText(dayViewText);
22623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            holder.dateView.setText(dateViewText);
2273cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
22831412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            // Set the background of the view, it is grayed for day that are in the past and today
22931412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            if (row.mDay > mTodayJulianDay) {
230eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_primary);
2316467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = false;
232980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            } else {
233eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_secondary);
2346467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = true;
235980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            }
236146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return agendaDayView;
237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else if (row.mType == TYPE_MEETING) {
238980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            View itemView = mAgendaAdapter.getView(row.mPosition, convertView, parent);
2394d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            AgendaAdapter.ViewHolder holder = ((AgendaAdapter.ViewHolder) itemView.getTag());
2404d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            TextView title = holder.title;
24131412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            long eventStartTime = holder.startTimeMilli;
2424d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            boolean allDay = holder.allDay;
243c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            if (AgendaWindowAdapter.BASICLOG) {
2442d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                title.setText(title.getText() + " P:" + position);
245c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            } else {
2462d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                title.setText(title.getText());
247c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            }
2482d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
24931412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            // if event in the past or started already, un-bold the title and set the background
25031412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            if ((!allDay && eventStartTime <= System.currentTimeMillis()) ||
25131412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson                    (allDay && row.mDay <= mTodayJulianDay)) {
252eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                itemView.setBackgroundResource(R.drawable.agenda_item_bg_secondary);
2534d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson                title.setTypeface(Typeface.DEFAULT);
2546467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = true;
2554d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            } else {
256eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                itemView.setBackgroundResource(R.drawable.agenda_item_bg_primary);
2574d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson                title.setTypeface(Typeface.DEFAULT_BOLD);
2586467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = false;
259980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            }
26031412a0fea756e0da0bcbdf3cdffe4efae21cdbeIsaac Katzenelson            holder.julianDay = row.mDay;
261980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            return itemView;
262146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else {
263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Error
264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            throw new IllegalStateException("Unknown event type:" + row.mType);
265146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
266146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void clearDayHeaderInfo() {
269146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = null;
270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
272dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void changeCursor(DayAdapterInfo info) {
273dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        calculateDays(info);
274dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        mAgendaAdapter.changeCursor(info.cursor);
27513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
27613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
277dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void calculateDays(DayAdapterInfo dayAdapterInfo) {
278dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        Cursor cursor = dayAdapterInfo.cursor;
279146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        ArrayList<RowInfo> rowInfo = new ArrayList<RowInfo>();
280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int prevStartDay = -1;
2819a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        Time time = new Time(mTimeZone);
282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long now = System.currentTimeMillis();
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        time.set(now);
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mTodayJulianDay = Time.getJulianDay(now, time.gmtoff);
285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        LinkedList<MultipleDayInfo> multipleDayList = new LinkedList<MultipleDayInfo>();
286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int position = 0; cursor.moveToNext(); position++) {
28713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY);
288146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
289dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
290dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            startDay = Math.max(startDay, dayAdapterInfo.start);
291dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (startDay != prevStartDay) {
293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Check if we skipped over any empty days
294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (prevStartDay == -1) {
295980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                    rowInfo.add(new RowInfo(TYPE_DAY, startDay, 0));
296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                } else {
297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If there are any multiple-day events that span the empty
298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // range of days, then create day headers and events for
299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // those multiple-day events.
300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    boolean dayHeaderAdded = false;
301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    for (int currentDay = prevStartDay + 1; currentDay <= startDay; currentDay++) {
302146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = false;
303146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
304146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        while (iter.hasNext()) {
305146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            MultipleDayInfo info = iter.next();
306146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this event has ended then remove it from the
307146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // list.
308146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (info.mEndDay < currentDay) {
309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                iter.remove();
310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                continue;
311146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this is the first event for the day, then
314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // insert a day header.
315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (!dayHeaderAdded) {
316980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                                rowInfo.add(new RowInfo(TYPE_DAY, currentDay, 0));
317146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                dayHeaderAdded = true;
318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
319980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                            rowInfo.add(new RowInfo(TYPE_MEETING, currentDay, info.mPosition));
320146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        }
321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If the day header was not added for the start day, then
324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // add it now.
325146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
326980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                        rowInfo.add(new RowInfo(TYPE_DAY, startDay, 0));
327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                prevStartDay = startDay;
330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Add in the event for this cursor position
333980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            rowInfo.add(new RowInfo(TYPE_MEETING, startDay, position));
334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If this event spans multiple days, then add it to the multipleDay
336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // list.
33713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int endDay = cursor.getInt(AgendaWindowAdapter.INDEX_END_DAY);
338dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
339dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
340dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            endDay = Math.min(endDay, dayAdapterInfo.end);
341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endDay > startDay) {
342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                multipleDayList.add(new MultipleDayInfo(position, endDay));
343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // There are no more cursor events but we might still have multiple-day
347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events left.  So create day headers and events for those.
348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (prevStartDay > 0) {
349dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            for (int currentDay = prevStartDay + 1; currentDay <= dayAdapterInfo.end;
350dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan                    currentDay++) {
351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                boolean dayHeaderAdded = false;
352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                while (iter.hasNext()) {
354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    MultipleDayInfo info = iter.next();
355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this event has ended then remove it from the
356146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // list.
357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (info.mEndDay < currentDay) {
358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        iter.remove();
359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        continue;
360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this is the first event for the day, then
363146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // insert a day header.
364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
365980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                        rowInfo.add(new RowInfo(TYPE_DAY, currentDay, 0));
366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = true;
367146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
368980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                    rowInfo.add(new RowInfo(TYPE_MEETING, currentDay, info.mPosition));
369146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
370146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = rowInfo;
373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class RowInfo {
376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // mType is either a day header (TYPE_DAY) or an event (TYPE_MEETING)
377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mType;
378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
379980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        final int mDay;          // Julian day
380980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        final int mPosition;     // cursor position (not used for TYPE_DAY)
3812d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // This is used to mark a day header as the first day with events that is "today"
3822d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // or later. This flag is used by the adapter to create a view with a visual separator
3832d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // between the past and the present/future
3842d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        boolean mFirstDayAfterYesterday;
385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
386980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        RowInfo(int type, int julianDay, int position) {
387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mType = type;
388980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mDay = julianDay;
389980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mPosition = position;
3902d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            mFirstDayAfterYesterday = false;
391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class MultipleDayInfo {
395146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mPosition;
396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mEndDay;
397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
398146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        MultipleDayInfo(int position, int endDay) {
399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mPosition = position;
400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mEndDay = endDay;
401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Searches for the day that matches the given Time object and returns the
406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * list position of that day.  If there are no events for that day, then it
407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * finds the nearest day (before or after) that has events and returns the
408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * list position for that day.
409146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
410146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param time the date to search for
411146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the cursor position of the first event for that date, or zero
412146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * if no match was found
413146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
414146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findDayPositionNearestTime(Time time) {
415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null) {
416146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
418146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long millis = time.toMillis(false /* use isDst */);
419146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int julianDay = Time.getJulianDay(millis, time.gmtoff);
420146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minDistance = 1000;  // some big number
421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minIndex = 0;
422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = 0; index < len; index++) {
424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
426980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                int distance = Math.abs(julianDay - row.mDay);
427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (distance == 0) {
428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    return index;
429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (distance < minDistance) {
431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    minDistance = distance;
432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    minIndex = index;
433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // We didn't find an exact match so take the nearest day that had
438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events.
439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return minIndex;
440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
4432d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Returns a flag indicating if this position is the first day after "yesterday" that has
4442d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * events in it.
4452d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     *
4462d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * @return a flag indicating if this is the "first day after yesterday"
4472d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     */
4482d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public boolean isFirstDayAfterYesterday(int position) {
4492d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        int headerPos = getHeaderPosition(position);
4502d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        RowInfo row = mRowInfo.get(headerPos);
4512d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        if (row != null) {
4522d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            return row.mFirstDayAfterYesterday;
4532d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        }
4542d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        return false;
4552d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
4562d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
4572d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    /**
458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Finds the Julian day containing the event at the given position.
459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param position the list position of an event
461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the Julian day containing that event
462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findJulianDayFromPosition(int position) {
464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null || position < 0) {
465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (position >= len) return 0;  // no row info at this position
470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = position; index >= 0; index--) {
472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
473146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
474980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return row.mDay;
475146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
476146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
477146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return 0;
478146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
479146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
480146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
4812d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Marks the current row as the first day that has events after "yesterday".
4822d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Used to mark the separation between the past and the present/future
4832d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     *
4842d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * @param position in the adapter
4852d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     */
4862d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public void setAsFirstDayAfterYesterday(int position) {
4872d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        if (mRowInfo == null || position < 0 || position > mRowInfo.size()) {
4882d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            return;
4892d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        }
4902d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        RowInfo row = mRowInfo.get(position);
4912d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        row.mFirstDayAfterYesterday = true;
4922d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
4932d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
4942d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    /**
495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Converts a list position to a cursor position.  The list contains
496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * day headers as well as events.  The cursor contains only events.
497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param listPos the list position of an event
499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the corresponding cursor position of that event
500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
501146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCursorPosition(int listPos) {
502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && listPos >= 0) {
503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(listPos);
504146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_MEETING) {
505980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return row.mPosition;
50613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else {
50713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int nextPos = listPos + 1;
50813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (nextPos < mRowInfo.size()) {
50913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    nextPos = getCursorPosition(nextPos);
51013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (nextPos >= 0) {
51113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        return -nextPos;
51213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
51313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
514146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
515146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
51613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return Integer.MIN_VALUE;
517146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
518146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
519146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
520146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean areAllItemsEnabled() {
521146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return false;
522146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
523146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
524146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isEnabled(int position) {
526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && position < mRowInfo.size()) {
527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return row.mType == TYPE_MEETING;
529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return true;
531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
533