AgendaByDayAdapter.java revision eedc9fc0631f3c8727df3c0e73474ebcdecd89fe
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;
24980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelsonimport android.content.res.Resources;
25146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor;
26980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelsonimport android.graphics.Color;
272d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelsonimport android.graphics.Typeface;
289a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport android.text.TextUtils;
29146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.DateUtils;
30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.text.format.Time;
31146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.LayoutInflater;
32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View;
33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.ViewGroup;
34146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.BaseAdapter;
35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.TextView;
36146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
37146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.ArrayList;
3813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Formatter;
39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.Iterator;
40146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport java.util.LinkedList;
4113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Locale;
42146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectpublic class AgendaByDayAdapter extends BaseAdapter {
44146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_DAY = 0;
45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static final int TYPE_MEETING = 1;
4613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static final int TYPE_LAST = 2;
47146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
48980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
49980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson    // Events background colors (past events are grayed)
50980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson    private final int mPastBackgroundColor;
51980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson    private final int mBackgroundColor;
52980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
53146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final Context mContext;
54146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final AgendaAdapter mAgendaAdapter;
55146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private final LayoutInflater mInflater;
56146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private ArrayList<RowInfo> mRowInfo;
57146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private int mTodayJulianDay;
589a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private Time mTmpTime;
599a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private String mTimeZone;
6023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    // Note: Formatter is not thread safe. Fine for now as it is only used by the main thread.
6123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    private Formatter mFormatter;
6213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private StringBuilder mStringBuilder;
63146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
6413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static class ViewHolder {
65980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        TextView dayView;
6613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        TextView dateView;
676467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson        int julianDay;
686467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson        boolean grayed;
6913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
7013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
719a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private Runnable mTZUpdater = new Runnable() {
729a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        @Override
739a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        public void run() {
749a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            mTimeZone = Utils.getTimeZone(mContext, this);
759a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            mTmpTime = new Time(mTimeZone);
769a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            notifyDataSetChanged();
779a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        }
789a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    };
799a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
8013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public AgendaByDayAdapter(Context context) {
81146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mContext = context;
8213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaAdapter = new AgendaAdapter(context, R.layout.agenda_item);
8313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
8413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder = new StringBuilder(50);
8513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
869a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTimeZone = Utils.getTimeZone(context, mTZUpdater);
879a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTmpTime = new Time(mTimeZone);
88980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
89980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        // Get events colors
90980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        Resources r = mContext.getResources();
91980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        mPastBackgroundColor = r.getColor(R.color.agenda_past_days_bar_background_color);
92980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        mBackgroundColor = r.getColor(R.color.agenda_day_bar_background_color);
93146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
94146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
9537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
9637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the position of a header of a specific item
9737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderPosition(int position) {
9837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (mRowInfo == null || position >= mRowInfo.size()) {
9937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
10037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
10137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
10237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        for (int i = position; i >=0; i --) {
10337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            RowInfo row = mRowInfo.get(i);
10437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            if (row != null && row.mType == TYPE_DAY)
10537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson                return i;
10637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
10737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
10837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
10937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
11037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the number of items in a section defined by a specific header location
11137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderItemsCount(int position) {
11237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (mRowInfo == null) {
11337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
11437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
11537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        int count = 0;
11637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        for (int i = position +1; i < mRowInfo.size(); i++) {
11737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            if (mRowInfo.get(i).mType != TYPE_MEETING) {
11837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson                return count;
11937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            }
12037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            count ++;
12137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
12237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return count;
12337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
12437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCount() {
126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mRowInfo.size();
128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
129146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getCount();
130146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Object getItem(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) {
136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                return row;
137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
138980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return mAgendaAdapter.getItem(row.mPosition);
139146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
140146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
141146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItem(position);
142146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
143146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
144146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public long getItemId(int position) {
145146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null) {
146146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
147146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
148c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan                return -position;
149146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
150980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return mAgendaAdapter.getItemId(row.mPosition);
151146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
152146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
153146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mAgendaAdapter.getItemId(position);
154146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
155146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
156146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
157146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getViewTypeCount() {
158146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return TYPE_LAST;
159146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
160146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
161146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
162146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getItemViewType(int position) {
163146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return mRowInfo != null && mRowInfo.size() > position ?
164146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mRowInfo.get(position).mType : TYPE_DAY;
165146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
166146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
1672d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public boolean isDayHeaderView(int position) {
1682d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        return (getItemViewType(position) == TYPE_DAY);
1692d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
1702d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
171146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public View getView(int position, View convertView, ViewGroup parent) {
172146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if ((mRowInfo == null) || (position > mRowInfo.size())) {
173146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If we have no row info, mAgendaAdapter returns the view.
174146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return mAgendaAdapter.getView(position, convertView, parent);
175146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
176146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
177146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        RowInfo row = mRowInfo.get(position);
178146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (row.mType == TYPE_DAY) {
17913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            ViewHolder holder = null;
18013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            View agendaDayView = null;
18113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if ((convertView != null) && (convertView.getTag() != null)) {
18213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Listview may get confused and pass in a different type of
18313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // view since we keep shifting data around. Not a big problem.
18413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Object tag = convertView.getTag();
18513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (tag instanceof ViewHolder) {
18613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    agendaDayView = convertView;
18713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    holder = (ViewHolder) tag;
1886467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                    holder.julianDay = row.mDay;
18913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
19013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
19113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
19213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (holder == null) {
193146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Create a new AgendaView with a ViewHolder for fast access to
194146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // views w/o calling findViewById()
195146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder = new ViewHolder();
196146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView = mInflater.inflate(R.layout.agenda_day, parent, false);
197980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                holder.dayView = (TextView) agendaDayView.findViewById(R.id.day);
198146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                holder.dateView = (TextView) agendaDayView.findViewById(R.id.date);
1996467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.julianDay = row.mDay;
2006467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = false;
201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                agendaDayView.setTag(holder);
202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
203146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
2049a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // Re-use the member variable "mTime" which is set to the local
2059a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // time zone.
2069a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // It's difficult to find and update all these adapters when the
2079a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // home tz changes so check it here and update if needed.
2089a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            String tz = Utils.getTimeZone(mContext, mTZUpdater);
2099a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            if (!TextUtils.equals(tz, mTmpTime.timezone)) {
2109a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                mTimeZone = tz;
2119a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                mTmpTime = new Time(tz);
2129a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            }
21313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
214980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Build the text for the day of the week.
215980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Should be yesterday/today/tomorrow (if applicable) + day of the week
216980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
217980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            Time date = mTmpTime;
218980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            long millis = date.setJulianDay(row.mDay);
219980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            int flags = DateUtils.FORMAT_SHOW_WEEKDAY;
22013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mStringBuilder.setLength(0);
221980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
222980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            String dayViewText;
223980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            if (row.mDay == mTodayJulianDay) {
224980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                dayViewText = mContext.getString(R.string.agenda_today, DateUtils.formatDateRange(
2259a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                        mContext, mFormatter, millis, millis, flags, mTimeZone).toString());
226980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            } else if (row.mDay == mTodayJulianDay - 1) {
227980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                dayViewText = mContext.getString(R.string.agenda_yesterday,
228980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                        DateUtils.formatDateRange(mContext, mFormatter, millis, millis, flags,
229980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                                mTimeZone).toString());
230980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            } else if (row.mDay == mTodayJulianDay + 1) {
231980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                dayViewText = mContext.getString(R.string.agenda_tomorrow,
232980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                        DateUtils.formatDateRange(mContext, mFormatter, millis, millis, flags,
233980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                                mTimeZone).toString());
234146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
235980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                dayViewText = DateUtils.formatDateRange(mContext, mFormatter, millis, millis,
2369a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                        flags, mTimeZone).toString();
237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
238980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            dayViewText = dayViewText.toUpperCase();
239980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
240980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Build text for the date
241980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Format should be month day
242980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
243980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mStringBuilder.setLength(0);
244980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            flags = DateUtils.FORMAT_SHOW_DATE;
245980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            String dateViewText = DateUtils.formatDateRange(mContext, mFormatter, millis, millis,
246980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                    flags, mTimeZone).toString();
2473cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
24823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (AgendaWindowAdapter.BASICLOG) {
249980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                dayViewText += " P:" + position;
25023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                dateViewText += " P:" + position;
25123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
252980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            holder.dayView.setText(dayViewText);
25323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            holder.dateView.setText(dateViewText);
2543cfe2e55d8c34849f99f4e8cb847e54076098b8fThe Android Open Source Project
255980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            // Set the background of the view, it is different if it is before today or not
256980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            if (row.mDay >= mTodayJulianDay) {
257eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_primary);
2586467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = false;
259980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            } else {
260eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_secondary);
2616467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = true;
262980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            }
263146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return agendaDayView;
264146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else if (row.mType == TYPE_MEETING) {
265980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            View itemView = mAgendaAdapter.getView(row.mPosition, convertView, parent);
2664d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            AgendaAdapter.ViewHolder holder = ((AgendaAdapter.ViewHolder) itemView.getTag());
2674d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            TextView title = holder.title;
2684d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            long eventEndTime = holder.endTimeMilli;
2694d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            boolean allDay = holder.allDay;
270c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            if (AgendaWindowAdapter.BASICLOG) {
2712d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                title.setText(title.getText() + " P:" + position);
272c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            } else {
2732d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                title.setText(title.getText());
274c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            }
2752d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
2762d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // if event in the past , un-bold the title and set the background
2774d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            if (row.mDay < mTodayJulianDay) {
278eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                itemView.setBackgroundResource(R.drawable.agenda_item_bg_secondary);
2792d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                title.setTypeface(Typeface.DEFAULT);
2806467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = true;
2814d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            } else if (row.mDay == mTodayJulianDay && !allDay &&
2824d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson                    eventEndTime < System.currentTimeMillis()){
283eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                itemView.setBackgroundResource(R.drawable.agenda_item_bg_secondary);
2844d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson                title.setTypeface(Typeface.DEFAULT);
2856467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = true;
2864d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson            } else {
287eedc9fc0631f3c8727df3c0e73474ebcdecd89feRoboErik                itemView.setBackgroundResource(R.drawable.agenda_item_bg_primary);
2884d09b91abf62994cf47ccdbf7e61f60b891f9f61Isaac Katzenelson                title.setTypeface(Typeface.DEFAULT_BOLD);
2896467afce8cd7df7d013028462fa6ddf450238a43Isaac Katzenelson                holder.grayed = false;
290980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            }
291980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            return itemView;
292146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else {
293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Error
294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            throw new IllegalStateException("Unknown event type:" + row.mType);
295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
296146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
297146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
298146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public void clearDayHeaderInfo() {
299146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = null;
300146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
301146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
302dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void changeCursor(DayAdapterInfo info) {
303dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        calculateDays(info);
304dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        mAgendaAdapter.changeCursor(info.cursor);
30513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
30613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
307dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    public void calculateDays(DayAdapterInfo dayAdapterInfo) {
308dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan        Cursor cursor = dayAdapterInfo.cursor;
309146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        ArrayList<RowInfo> rowInfo = new ArrayList<RowInfo>();
310146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int prevStartDay = -1;
3119a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        Time time = new Time(mTimeZone);
312146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long now = System.currentTimeMillis();
313146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        time.set(now);
314146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mTodayJulianDay = Time.getJulianDay(now, time.gmtoff);
315146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        LinkedList<MultipleDayInfo> multipleDayList = new LinkedList<MultipleDayInfo>();
316146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int position = 0; cursor.moveToNext(); position++) {
31713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY);
318146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
319dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
320dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            startDay = Math.max(startDay, dayAdapterInfo.start);
321dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
322146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (startDay != prevStartDay) {
323146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // Check if we skipped over any empty days
324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (prevStartDay == -1) {
325980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                    rowInfo.add(new RowInfo(TYPE_DAY, startDay, 0));
326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                } else {
327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If there are any multiple-day events that span the empty
328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // range of days, then create day headers and events for
329146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // those multiple-day events.
330146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    boolean dayHeaderAdded = false;
331146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    for (int currentDay = prevStartDay + 1; currentDay <= startDay; currentDay++) {
332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = false;
333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
334146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        while (iter.hasNext()) {
335146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            MultipleDayInfo info = iter.next();
336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this event has ended then remove it from the
337146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // list.
338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (info.mEndDay < currentDay) {
339146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                iter.remove();
340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                continue;
341146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // If this is the first event for the day, then
344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            // insert a day header.
345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            if (!dayHeaderAdded) {
346980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                                rowInfo.add(new RowInfo(TYPE_DAY, currentDay, 0));
347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                                dayHeaderAdded = true;
348146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                            }
349980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                            rowInfo.add(new RowInfo(TYPE_MEETING, currentDay, info.mPosition));
350146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        }
351146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
352146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
353146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If the day header was not added for the start day, then
354146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // add it now.
355146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
356980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                        rowInfo.add(new RowInfo(TYPE_DAY, startDay, 0));
357146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
358146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
359146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                prevStartDay = startDay;
360146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
361146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
362146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Add in the event for this cursor position
363980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            rowInfo.add(new RowInfo(TYPE_MEETING, startDay, position));
364146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
365146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // If this event spans multiple days, then add it to the multipleDay
366146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // list.
36713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int endDay = cursor.getInt(AgendaWindowAdapter.INDEX_END_DAY);
368dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan
369dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            // Skip over the days outside of the adapter's range
370dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            endDay = Math.min(endDay, dayAdapterInfo.end);
371146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (endDay > startDay) {
372146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                multipleDayList.add(new MultipleDayInfo(position, endDay));
373146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
374146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
375146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
376146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // There are no more cursor events but we might still have multiple-day
377146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events left.  So create day headers and events for those.
378146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (prevStartDay > 0) {
379dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan            for (int currentDay = prevStartDay + 1; currentDay <= dayAdapterInfo.end;
380dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan                    currentDay++) {
381146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                boolean dayHeaderAdded = false;
382146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                Iterator<MultipleDayInfo> iter = multipleDayList.iterator();
383146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                while (iter.hasNext()) {
384146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    MultipleDayInfo info = iter.next();
385146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this event has ended then remove it from the
386146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // list.
387146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (info.mEndDay < currentDay) {
388146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        iter.remove();
389146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        continue;
390146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
391146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
392146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // If this is the first event for the day, then
393146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    // insert a day header.
394146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    if (!dayHeaderAdded) {
395980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                        rowInfo.add(new RowInfo(TYPE_DAY, currentDay, 0));
396146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                        dayHeaderAdded = true;
397146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    }
398980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                    rowInfo.add(new RowInfo(TYPE_MEETING, currentDay, info.mPosition));
399146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
400146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
401146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
402146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mRowInfo = rowInfo;
403146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
404146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
405146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class RowInfo {
406146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // mType is either a day header (TYPE_DAY) or an event (TYPE_MEETING)
407146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mType;
408146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
409980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        final int mDay;          // Julian day
410980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        final int mPosition;     // cursor position (not used for TYPE_DAY)
4112d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // This is used to mark a day header as the first day with events that is "today"
4122d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // or later. This flag is used by the adapter to create a view with a visual separator
4132d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        // between the past and the present/future
4142d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        boolean mFirstDayAfterYesterday;
415146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
416980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        RowInfo(int type, int julianDay, int position) {
417146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mType = type;
418980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mDay = julianDay;
419980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            mPosition = position;
4202d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            mFirstDayAfterYesterday = false;
421146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
422146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
423146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
424146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private static class MultipleDayInfo {
425146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mPosition;
426146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        final int mEndDay;
427146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
428146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        MultipleDayInfo(int position, int endDay) {
429146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mPosition = position;
430146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mEndDay = endDay;
431146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
432146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
433146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
434146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
435146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Searches for the day that matches the given Time object and returns the
436146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * list position of that day.  If there are no events for that day, then it
437146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * finds the nearest day (before or after) that has events and returns the
438146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * list position for that day.
439146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
440146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param time the date to search for
441146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the cursor position of the first event for that date, or zero
442146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * if no match was found
443146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
444146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findDayPositionNearestTime(Time time) {
445146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null) {
446146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
447146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
448146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        long millis = time.toMillis(false /* use isDst */);
449146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int julianDay = Time.getJulianDay(millis, time.gmtoff);
450146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minDistance = 1000;  // some big number
451146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int minIndex = 0;
452146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
453146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = 0; index < len; index++) {
454146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
455146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
456980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                int distance = Math.abs(julianDay - row.mDay);
457146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (distance == 0) {
458146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    return index;
459146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
460146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                if (distance < minDistance) {
461146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    minDistance = distance;
462146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                    minIndex = index;
463146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                }
464146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
465146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
466146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
467146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // We didn't find an exact match so take the nearest day that had
468146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // events.
469146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return minIndex;
470146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
471146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
472146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
4732d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Returns a flag indicating if this position is the first day after "yesterday" that has
4742d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * events in it.
4752d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     *
4762d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * @return a flag indicating if this is the "first day after yesterday"
4772d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     */
4782d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public boolean isFirstDayAfterYesterday(int position) {
4792d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        int headerPos = getHeaderPosition(position);
4802d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        RowInfo row = mRowInfo.get(headerPos);
4812d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        if (row != null) {
4822d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            return row.mFirstDayAfterYesterday;
4832d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        }
4842d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        return false;
4852d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
4862d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
4872d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    /**
488146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Finds the Julian day containing the event at the given position.
489146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
490146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param position the list position of an event
491146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the Julian day containing that event
492146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
493146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int findJulianDayFromPosition(int position) {
494146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo == null || position < 0) {
495146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return 0;
496146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
497146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
498146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        int len = mRowInfo.size();
499146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (position >= len) return 0;  // no row info at this position
500146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
501146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        for (int index = position; index >= 0; index--) {
502146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(index);
503146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_DAY) {
504980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return row.mDay;
505146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
506146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
507146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return 0;
508146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
509146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
510146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    /**
5112d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Marks the current row as the first day that has events after "yesterday".
5122d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * Used to mark the separation between the past and the present/future
5132d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     *
5142d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     * @param position in the adapter
5152d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson     */
5162d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    public void setAsFirstDayAfterYesterday(int position) {
5172d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        if (mRowInfo == null || position < 0 || position > mRowInfo.size()) {
5182d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            return;
5192d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        }
5202d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        RowInfo row = mRowInfo.get(position);
5212d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson        row.mFirstDayAfterYesterday = true;
5222d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    }
5232d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
5242d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson    /**
525146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * Converts a list position to a cursor position.  The list contains
526146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * day headers as well as events.  The cursor contains only events.
527146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     *
528146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @param listPos the list position of an event
529146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     * @return the corresponding cursor position of that event
530146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project     */
531146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public int getCursorPosition(int listPos) {
532146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && listPos >= 0) {
533146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(listPos);
534146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (row.mType == TYPE_MEETING) {
535980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson                return row.mPosition;
53613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else {
53713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int nextPos = listPos + 1;
53813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (nextPos < mRowInfo.size()) {
53913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    nextPos = getCursorPosition(nextPos);
54013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (nextPos >= 0) {
54113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        return -nextPos;
54213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
54313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
544146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
545146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
54613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return Integer.MIN_VALUE;
547146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
548146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
549146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
550146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean areAllItemsEnabled() {
551146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return false;
552146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
553146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
554146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
555146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isEnabled(int position) {
556146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mRowInfo != null && position < mRowInfo.size()) {
557146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            RowInfo row = mRowInfo.get(position);
558146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return row.mType == TYPE_MEETING;
559146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
560146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return true;
561146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
562146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
563