AgendaWindowAdapter.java revision 96d6163c524b338307b01d25916ccffd495e2f29
113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan/*
213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * Copyright (C) 2009 The Android Open Source Project
313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan *
413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * Licensed under the Apache License, Version 2.0 (the "License");
513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * you may not use this file except in compliance with the License.
613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * You may obtain a copy of the License at
713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan *
813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan *      http://www.apache.org/licenses/LICENSE-2.0
913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan *
1013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * Unless required by applicable law or agreed to in writing, software
1113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * distributed under the License is distributed on an "AS IS" BASIS,
1213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * See the License for the specific language governing permissions and
1413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * limitations under the License.
1513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */
1613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1700b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tangpackage com.android.calendar.agenda;
1800b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang
19ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chanimport com.android.calendar.CalendarController;
2000b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tangimport com.android.calendar.R;
2100b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tangimport com.android.calendar.Utils;
22ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chanimport com.android.calendar.CalendarController.EventType;
23e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErikimport com.android.calendar.CalendarController.ViewType;
2437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport com.android.calendar.StickyHeaderListView;
2513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
2613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.AsyncQueryHandler;
2713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.ContentResolver;
289138ce8a14924612c014da2b6e727b4117ba1a92Mason Tangimport android.content.ContentUris;
2913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.Context;
30a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawaimport android.content.res.Resources;
3113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.database.Cursor;
3213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.net.Uri;
33a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract;
34a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees;
35a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Calendars;
36a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Instances;
3713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.DateUtils;
3813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.Time;
3913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.util.Log;
4013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.LayoutInflater;
4113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View;
4213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View.OnClickListener;
439a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport android.view.ViewGroup;
4413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.BaseAdapter;
4513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.TextView;
4613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
4713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Formatter;
4813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Iterator;
4913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.LinkedList;
5013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Locale;
5113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.concurrent.ConcurrentLinkedQueue;
5213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
5313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan/*
5413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanBugs Bugs Bugs:
5513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- At rotation and launch time, the initial position is not set properly. This code is calling
5613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan listview.setSelection() in 2 rapid secessions but it dropped or didn't process the first one.
5713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Scroll using trackball isn't repositioning properly after a new adapter is added.
5823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan- Track ball clicks at the header/footer doesn't work.
5913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Potential ping pong effect if the prefetch window is big and data is limited
6013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Add index in calendar provider
6113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
6213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanToDo ToDo ToDo:
6313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanGet design of header and footer from designer
6413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
6513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanMake scrolling smoother.
6613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanTest for correctness
6713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanLoading speed
6813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanCheck for leaks and excessive allocations
6913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */
7013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
7137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonpublic class AgendaWindowAdapter extends BaseAdapter
7237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    implements StickyHeaderListView.HeaderIndexer{
7313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
7423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    static final boolean BASICLOG = false;
7592c6688283442c800b4de0ca76c0e05a089f84c3RoboErik    static final boolean DEBUGLOG = false;
76a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    private static final String TAG = "AgendaWindowAdapter";
7713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
789138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private static final String AGENDA_SORT_ORDER =
79a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErik            CalendarContract.Instances.START_DAY + " ASC, " +
80a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErik            CalendarContract.Instances.BEGIN + " ASC, " +
81a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErik            CalendarContract.Events.TITLE + " ASC";
829138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
83ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public static final int INDEX_INSTANCE_ID = 0;
8413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_TITLE = 1;
8513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_EVENT_LOCATION = 2;
8613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_ALL_DAY = 3;
8713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_HAS_ALARM = 4;
8813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_COLOR = 5;
8913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_RRULE = 6;
9013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_BEGIN = 7;
9113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_END = 8;
9213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_EVENT_ID = 9;
9313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_START_DAY = 10;
9413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_END_DAY = 11;
9513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_SELF_ATTENDEE_STATUS = 12;
96056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson    public static final int INDEX_ORGANIZER = 13;
97056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson    public static final int INDEX_OWNER_ACCOUNT = 14;
98056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson    public static final int INDEX_CAN_ORGANIZER_RESPOND= 15;
991121e409c5f504e8df75982475d8cc607d5f0dfaRoboErik    public static final int INDEX_TIME_ZONE = 16;
10013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
10113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final String[] PROJECTION = new String[] {
10213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances._ID, // 0
10313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.TITLE, // 1
10413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.EVENT_LOCATION, // 2
10513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.ALL_DAY, // 3
10613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.HAS_ALARM, // 4
1070e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik            Instances.CALENDAR_COLOR, // 5
10813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.RRULE, // 6
10913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.BEGIN, // 7
11013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.END, // 8
11113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.EVENT_ID, // 9
11213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.START_DAY, // 10 Julian start day
11313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.END_DAY, // 11 Julian end day
11413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.SELF_ATTENDEE_STATUS, // 12
115056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson            Instances.ORGANIZER, // 13
116056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson            Instances.OWNER_ACCOUNT, // 14
117056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson            Instances.CAN_ORGANIZER_RESPOND, // 15
1181121e409c5f504e8df75982475d8cc607d5f0dfaRoboErik            Instances.EVENT_TIMEZONE, // 16
11913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    };
12013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
12113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Listview may have a bug where the index/position is not consistent when there's a header.
122a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    // position == positionInListView - OFF_BY_ONE_BUG
12313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // TODO Need to look into this.
12413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int OFF_BY_ONE_BUG = 1;
12513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int MAX_NUM_OF_ADAPTERS = 5;
12613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int IDEAL_NUM_OF_EVENTS = 50;
12713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int MIN_QUERY_DURATION = 7; // days
12813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int MAX_QUERY_DURATION = 60; // days
12913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int PREFETCH_BOUNDARY = 1;
13013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1319138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** Times to auto-expand/retry query after getting no data */
1329138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private static final int RETRIES_ON_NO_DATA = 1;
13313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
13413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private Context mContext;
135a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    private Resources mResources;
13613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private QueryHandler mQueryHandler;
13713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private AgendaListView mAgendaListView;
13813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1399138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** The sum of the rows in all the adapters */
1409138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private int mRowCount;
14113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1429138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** The number of times we have queried and gotten no results back */
14313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mEmptyCursorCount;
14413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1459138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** Cached value of the last used adapter */
1469138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private DayAdapterInfo mLastUsedInfo;
14713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
148a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    private final LinkedList<DayAdapterInfo> mAdapterInfos =
149a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa            new LinkedList<DayAdapterInfo>();
150a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    private final ConcurrentLinkedQueue<QuerySpec> mQueryQueue =
151a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa            new ConcurrentLinkedQueue<QuerySpec>();
15213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private TextView mHeaderView;
15313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private TextView mFooterView;
15413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean mDoneSettingUpHeaderFooter = false;
15513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
156980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson    private final boolean mIsTabletConfig;
157cf6a46c5c81334f7c960ecc5fd354a14f1c4037cMichael Chan    private final int mSkipDateHeader;
158980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
1599138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /**
16013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * When the user scrolled to the top, a query will be made for older events
16113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * and this will be incremented. Don't make more requests if
16213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * mOlderRequests > mOlderRequestsProcessed.
16313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     */
16413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mOlderRequests;
16513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1669138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** Number of "older" query that has been processed. */
16713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mOlderRequestsProcessed;
16813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1699138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /**
17013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * When the user scrolled to the bottom, a query will be made for newer
17113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * events and this will be incremented. Don't make more requests if
17213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * mNewerRequests > mNewerRequestsProcessed.
17313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     */
17413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mNewerRequests;
17513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1769138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** Number of "newer" query that has been processed. */
17713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mNewerRequestsProcessed;
17813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
17923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    // Note: Formatter is not thread safe. Fine for now as it is only used by the main thread.
18023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    private Formatter mFormatter;
18113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private StringBuilder mStringBuilder;
1829a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private String mTimeZone;
1839a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
18496a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson    // defines if to pop-up the current event when the agenda is first shown
18596a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson    private boolean mShowEventOnStart;
18696a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson
1879a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private Runnable mTZUpdater = new Runnable() {
1889a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        @Override
1899a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        public void run() {
1909a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            mTimeZone = Utils.getTimeZone(mContext, this);
1919a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            notifyDataSetChanged();
1929a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        }
1939a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    };
19413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
19513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean mShuttingDown;
19613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean mHideDeclined;
19713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1989138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** The current search query, or null if none */
1999138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private String mSearchQuery;
2009138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
201ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    private long mSelectedInstanceId = -1;
202a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
203163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan    private final int mSelectedItemBackgroundColor;
204163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan    private final int mSelectedItemTextColor;
205a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
20613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Types of Query
20713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int QUERY_TYPE_OLDER = 0; // Query for older events
20813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int QUERY_TYPE_NEWER = 1; // Query for newer events
20913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int QUERY_TYPE_CLEAN = 2; // Delete everything and query around a date
21013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
21113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static class QuerySpec {
21213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long queryStartMillis;
21313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Time goToTime;
21413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int start;
21513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int end;
2169138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        String searchQuery;
21713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int queryType;
21813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
21913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public QuerySpec(int queryType) {
22013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            this.queryType = queryType;
22113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
22223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan
22323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        @Override
22423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        public int hashCode() {
22523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            final int prime = 31;
22623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            int result = 1;
22723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + end;
22823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + (int) (queryStartMillis ^ (queryStartMillis >>> 32));
22923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + queryType;
23023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + start;
2319138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang            result = prime * result + searchQuery.hashCode();
23223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (goToTime != null) {
23323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                long goToTimeMillis = goToTime.toMillis(false);
23423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                result = prime * result + (int) (goToTimeMillis ^ (goToTimeMillis >>> 32));
23523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
23623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            return result;
23723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        }
23823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan
23923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        @Override
24023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        public boolean equals(Object obj) {
24123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (this == obj) return true;
24223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (obj == null) return false;
24323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (getClass() != obj.getClass()) return false;
24423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            QuerySpec other = (QuerySpec) obj;
24523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (end != other.end || queryStartMillis != other.queryStartMillis
2469138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                    || queryType != other.queryType || start != other.start
2479138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                    || Utils.equals(searchQuery, other.searchQuery)) {
24823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                return false;
24923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
2509138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
25123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (goToTime != null) {
25223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                if (goToTime.toMillis(false) != other.goToTime.toMillis(false)) {
25323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    return false;
25423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                }
25523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            } else {
25623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                if (other.goToTime != null) {
25723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    return false;
25823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                }
25923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
26023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            return true;
26123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        }
26213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
26313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
26413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static class EventInfo {
26513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long begin;
26613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long end;
26713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long id;
268ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        int startDay;
26913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
27013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
271dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    static class DayAdapterInfo {
27213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Cursor cursor;
27313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        AgendaByDayAdapter dayAdapter;
27413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int start; // start day of the cursor's coverage
27513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int end; // end day of the cursor's coverage
27613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int offset; // offset in position in the list view
27713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int size; // dayAdapter.getCount()
27813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
27913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public DayAdapterInfo(Context context) {
28013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            dayAdapter = new AgendaByDayAdapter(context);
28113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
28213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
28313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        @Override
28413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public String toString() {
2859a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // Static class, so the time in this toString will not reflect the
2869a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // home tz settings. This should only affect debugging.
28713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Time time = new Time();
28813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            StringBuilder sb = new StringBuilder();
28913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.setJulianDay(start);
29013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.normalize(false);
29113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append("Start:").append(time.toString());
29213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.setJulianDay(end);
29313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.normalize(false);
29413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append(" End:").append(time.toString());
29513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append(" Offset:").append(offset);
29613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append(" Size:").append(size);
29713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return sb.toString();
29813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
29913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
30013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
3019138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    public AgendaWindowAdapter(Context context,
30296a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson            AgendaListView agendaListView, boolean showEventOnStart) {
3039138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mContext = context;
304a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        mResources = context.getResources();
305163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan        mSelectedItemBackgroundColor = mResources
306163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                .getColor(R.color.agenda_selected_background_color);
307163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan        mSelectedItemTextColor = mResources.getColor(R.color.agenda_selected_text_color);
308980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        mIsTabletConfig = Utils.getConfigBool(mContext, R.bool.tablet_config);
309cf6a46c5c81334f7c960ecc5fd354a14f1c4037cMichael Chan        mSkipDateHeader = mIsTabletConfig ? 0 : 1;
310a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
3119a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTimeZone = Utils.getTimeZone(context, mTZUpdater);
31213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaListView = agendaListView;
3139138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mQueryHandler = new QueryHandler(context.getContentResolver());
31413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
31513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder = new StringBuilder(50);
31613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
31713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
31896a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson        mShowEventOnStart = showEventOnStart;
31996a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson
3209138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mSearchQuery = null;
3219138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
3229138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        LayoutInflater inflater = (LayoutInflater) context
32313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
32413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHeaderView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null);
32513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFooterView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null);
32613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHeaderView.setText(R.string.loading);
32713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaListView.addHeaderView(mHeaderView);
32813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
32913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
33013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in Adapter
33113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
33213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public int getViewTypeCount() {
33313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return AgendaByDayAdapter.TYPE_LAST;
33413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
33513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
33613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in BaseAdapter
33713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
33813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public boolean areAllItemsEnabled() {
33913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return false;
34013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
34113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
34213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in Adapter
34313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
34413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public int getItemViewType(int position) {
34513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
34613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
34713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.dayAdapter.getItemViewType(position - info.offset);
34813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
34913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return -1;
35013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
35113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
35213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
35313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in BaseAdapter
35413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
35513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public boolean isEnabled(int position) {
35613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
35713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
35813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.dayAdapter.isEnabled(position - info.offset);
35913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
36013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return false;
36113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
36213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
36313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
36413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
36513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public int getCount() {
36613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return mRowCount;
36713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
36813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
36913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
37013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public Object getItem(int position) {
37113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
37213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
37313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.dayAdapter.getItem(position - info.offset);
37413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
37513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return null;
37613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
37713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
37813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
379c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    // Method in BaseAdapter
380c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    @Override
381c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    public boolean hasStableIds() {
382c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan        return true;
383c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    }
384c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan
38513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
38613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public long getItemId(int position) {
38713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
38813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
389c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan            return ((position - info.offset) << 20) + info.start ;
39013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
39113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return -1;
39213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
39313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
39413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
39513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
39613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public View getView(int position, View convertView, ViewGroup parent) {
39713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (position >= (mRowCount - PREFETCH_BOUNDARY)
39813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                && mNewerRequests <= mNewerRequestsProcessed) {
39913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (DEBUGLOG) Log.e(TAG, "queryForNewerEvents: ");
40013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mNewerRequests++;
40113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queueQuery(new QuerySpec(QUERY_TYPE_NEWER));
40213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
40313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
40413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (position < PREFETCH_BOUNDARY
40513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                && mOlderRequests <= mOlderRequestsProcessed) {
40613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (DEBUGLOG) Log.e(TAG, "queryForOlderEvents: ");
40713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mOlderRequests++;
40813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queueQuery(new QuerySpec(QUERY_TYPE_OLDER));
40913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
41013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
411a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        final View v;
41213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
41313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
4142d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            int offset = position - info.offset;
4152d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            v = info.dayAdapter.getView(offset, convertView,
41613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    parent);
4172d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
4182d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // Turn on the past/present separator if the view is a day header
4192d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // and it is the first day with events after yesterday.
4202d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            if (info.dayAdapter.isDayHeaderView(offset)) {
4212d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                View simpleDivider = v.findViewById(R.id.top_divider_simple);
4222d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                View pastPresentDivider = v.findViewById(R.id.top_divider_past_present);
4232d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                if (info.dayAdapter.isFirstDayAfterYesterday(offset)) {
4242d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    if (simpleDivider != null && pastPresentDivider != null) {
4252d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        simpleDivider.setVisibility(View.GONE);
4262d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        pastPresentDivider.setVisibility(View.VISIBLE);
4272d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    }
4282d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                } else if (simpleDivider != null && pastPresentDivider != null) {
4292d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    simpleDivider.setVisibility(View.VISIBLE);
4302d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    pastPresentDivider.setVisibility(View.GONE);
4312d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                }
4322d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            }
43313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
4342d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // TODO
43513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Log.e(TAG, "BUG: getAdapterInfoByPosition returned null!!! " + position);
43613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            TextView tv = new TextView(mContext);
43713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            tv.setText("Bug! " + position);
43813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            v = tv;
43913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
44013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
44133de4c48430262a0509ffe50fc376b87520cb938RoboErik        // If this is not a tablet config don't do selection highlighting
44233de4c48430262a0509ffe50fc376b87520cb938RoboErik        if (!mIsTabletConfig) {
44333de4c48430262a0509ffe50fc376b87520cb938RoboErik            return v;
44433de4c48430262a0509ffe50fc376b87520cb938RoboErik        }
445ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        // Show selected marker if this is item is selected
446ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        boolean selected = false;
447ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        Object yy = v.getTag();
448ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (yy instanceof AgendaAdapter.ViewHolder) {
449ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            AgendaAdapter.ViewHolder vh = (AgendaAdapter.ViewHolder) yy;
450ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            selected = mSelectedInstanceId == vh.instanceId;
45196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson            vh.selectedMarker.setVisibility((selected && mShowEventOnStart) ?
45296a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                    View.VISIBLE : View.GONE);
453ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            if (selected) {
454163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                v.setBackgroundColor(mSelectedItemBackgroundColor);
455163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                vh.title.setTextColor(mSelectedItemTextColor);
456163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                vh.when.setTextColor(mSelectedItemTextColor);
457163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                vh.where.setTextColor(mSelectedItemTextColor);
458ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            }
459a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        }
460a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
46113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (DEBUGLOG) {
46213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Log.e(TAG, "getView " + position + " = " + getViewTitle(v));
46313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
46413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return v;
46513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
46613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
46713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int findDayPositionNearestTime(Time time) {
46813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (DEBUGLOG) Log.e(TAG, "findDayPositionNearestTime " + time);
46913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
47013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByTime(time);
47113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
47213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.offset + info.dayAdapter.findDayPositionNearestTime(time);
47313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
47413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return -1;
47513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
47613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
47713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
4789a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    protected DayAdapterInfo getAdapterInfoByPosition(int position) {
47913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
48013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (mLastUsedInfo != null && mLastUsedInfo.offset <= position
48113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    && position < (mLastUsedInfo.offset + mLastUsedInfo.size)) {
48213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return mLastUsedInfo;
48313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
48413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            for (DayAdapterInfo info : mAdapterInfos) {
48513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (info.offset <= position
48613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        && position < (info.offset + info.size)) {
48713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mLastUsedInfo = info;
48813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    return info;
48913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
49013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
49113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
49213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return null;
49313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
49413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
49513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private DayAdapterInfo getAdapterInfoByTime(Time time) {
49613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (DEBUGLOG) Log.e(TAG, "getAdapterInfoByTime " + time.toString());
49713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
49813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Time tmpTime = new Time(time);
49913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long timeInMillis = tmpTime.normalize(true);
50013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int day = Time.getJulianDay(timeInMillis, tmpTime.gmtoff);
50113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
50213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            for (DayAdapterInfo info : mAdapterInfos) {
50313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (info.start <= day && day < info.end) {
50413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    return info;
50513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
50613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
50713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
50813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return null;
50913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
51013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
511a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    public EventInfo getEventByPosition(final int positionInListView) {
51296d6163c524b338307b01d25916ccffd495e2f29Michael Chan        return getEventByPosition(positionInListView, true);
51396d6163c524b338307b01d25916ccffd495e2f29Michael Chan    }
51496d6163c524b338307b01d25916ccffd495e2f29Michael Chan
51596d6163c524b338307b01d25916ccffd495e2f29Michael Chan    /**
51696d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * Return the event info for a given position in the adapter
51796d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * @param positionInListView
51896d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * @param returnEventStartDay If true, return actual event startday. Otherwise
51996d6163c524b338307b01d25916ccffd495e2f29Michael Chan     *        return agenda date-header date as the startDay.
52096d6163c524b338307b01d25916ccffd495e2f29Michael Chan     *        The two will differ for multi-day events after the first day.
52196d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * @return
52296d6163c524b338307b01d25916ccffd495e2f29Michael Chan     */
52396d6163c524b338307b01d25916ccffd495e2f29Michael Chan    public EventInfo getEventByPosition(final int positionInListView,
52496d6163c524b338307b01d25916ccffd495e2f29Michael Chan            boolean returnEventStartDay) {
525a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (DEBUGLOG) Log.e(TAG, "getEventByPosition " + positionInListView);
52613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
527a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        final int positionInAdapter = positionInListView - OFF_BY_ONE_BUG;
528a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        DayAdapterInfo info = getAdapterInfoByPosition(positionInAdapter);
52913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info == null) {
53013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return null;
53113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
53213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
533a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        int cursorPosition = info.dayAdapter.getCursorPosition(positionInAdapter - info.offset);
534a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (cursorPosition == Integer.MIN_VALUE) {
53513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return null;
53613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
53713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
53813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        boolean isDayHeader = false;
539a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (cursorPosition < 0) {
540a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa            cursorPosition = -cursorPosition;
54113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            isDayHeader = true;
54213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
54313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
544a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (cursorPosition < info.cursor.getCount()) {
545a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa            info.cursor.moveToPosition(cursorPosition);
54696d6163c524b338307b01d25916ccffd495e2f29Michael Chan            EventInfo ei = buildEventInfoFromCursor(info.cursor, isDayHeader);
54796d6163c524b338307b01d25916ccffd495e2f29Michael Chan            if (!returnEventStartDay && !isDayHeader) {
54896d6163c524b338307b01d25916ccffd495e2f29Michael Chan                ei.startDay = info.dayAdapter.findJulianDayFromPosition(cursorPosition);
54996d6163c524b338307b01d25916ccffd495e2f29Michael Chan            }
55096d6163c524b338307b01d25916ccffd495e2f29Michael Chan            return ei;
55113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
55213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return null;
55313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
55413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
555ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    private EventInfo buildEventInfoFromCursor(final Cursor cursor, boolean isDayHeader) {
556ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        EventInfo event = new EventInfo();
557ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        event.begin = cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN);
558f836d4af478310abc9b63f1afa6ab964e2478fedRoboErik        event.end = cursor.getLong(AgendaWindowAdapter.INDEX_END);
559ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        event.startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY);
560ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
561ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        boolean allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0;
562ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (allDay) { // UTC
563ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            Time time = new Time(mTimeZone);
564ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.setJulianDay(Time.getJulianDay(event.begin, 0));
565ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            event.begin = time.toMillis(false /* use isDst */);
566ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        } else if (isDayHeader) { // Trim to midnight.
567ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            Time time = new Time(mTimeZone);
568ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.set(event.begin);
569ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.hour = 0;
570ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.minute = 0;
571ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.second = 0;
572ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            event.begin = time.toMillis(false /* use isDst */);
573ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        }
574ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
575ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (!isDayHeader) {
576ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            if (allDay) {
577ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                Time time = new Time(mTimeZone);
578ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                time.setJulianDay(Time.getJulianDay(event.end, 0));
579ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                event.end = time.toMillis(false /* use isDst */);
580ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            } else {
581ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                event.end = cursor.getLong(AgendaWindowAdapter.INDEX_END);
582ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            }
583ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson
584ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            event.id = cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID);
585ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        }
586ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        return event;
587ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    }
588ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
589ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson    public void refresh(Time goToTime, long id, String searchQuery, boolean forced) {
5904003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        if (searchQuery != null) {
5914003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            mSearchQuery = searchQuery;
5924003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        }
5934003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang
594c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan        if (DEBUGLOG) {
595f836d4af478310abc9b63f1afa6ab964e2478fedRoboErik            Log.e(TAG, this + ": refresh " + goToTime.toString()
596f836d4af478310abc9b63f1afa6ab964e2478fedRoboErik                    + (forced ? " forced" : " not forced"));
597c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan        }
5987278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik
59923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        int startDay = Time.getJulianDay(goToTime.toMillis(false), goToTime.gmtoff);
60013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
60113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (!forced && isInRange(startDay, startDay)) {
602ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            // No need to re-query
603ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            if (!mAgendaListView.isEventVisible(goToTime, id)) {
604cf6a46c5c81334f7c960ecc5fd354a14f1c4037cMichael Chan                mAgendaListView.setSelection(findDayPositionNearestTime(goToTime) + OFF_BY_ONE_BUG
605cf6a46c5c81334f7c960ecc5fd354a14f1c4037cMichael Chan                        + mSkipDateHeader);
606e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                Time actualTime = new Time(mTimeZone);
607e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                actualTime.set(mAgendaListView.getFirstVisibleTime());
608e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                CalendarController.getInstance(mContext).sendEvent(this, EventType.UPDATE_TITLE,
609e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        actualTime, actualTime, -1, ViewType.CURRENT);
610ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            }
61113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return;
61213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
61313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
614088a7d0d8c4d0652a42b8bbeb940421cea5ad8dcMichael Chan        // Query for a total of MIN_QUERY_DURATION days
61513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int endDay = startDay + MIN_QUERY_DURATION;
61613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
6179138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        queueQuery(startDay, endDay, goToTime, searchQuery, QUERY_TYPE_CLEAN);
61813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
61913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
62013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public void close() {
62113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mShuttingDown = true;
62213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        pruneAdapterInfo(QUERY_TYPE_CLEAN);
62313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (mQueryHandler != null) {
62413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mQueryHandler.cancelOperation(0);
62513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
62613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
62713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
62813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private DayAdapterInfo pruneAdapterInfo(int queryType) {
62913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
63013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            DayAdapterInfo recycleMe = null;
63113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (!mAdapterInfos.isEmpty()) {
63213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (mAdapterInfos.size() >= MAX_NUM_OF_ADAPTERS) {
63313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (queryType == QUERY_TYPE_NEWER) {
63413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe = mAdapterInfos.removeFirst();
63513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } else if (queryType == QUERY_TYPE_OLDER) {
63613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe = mAdapterInfos.removeLast();
63713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Keep the size only if the oldest items are removed.
63813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe.size = 0;
63913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
64013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (recycleMe != null) {
64113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (recycleMe.cursor != null) {
64213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            recycleMe.cursor.close();
64313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
64413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        return recycleMe;
64513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
64613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
64713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
64813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (mRowCount == 0 || queryType == QUERY_TYPE_CLEAN) {
64913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mRowCount = 0;
65013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    int deletedRows = 0;
65113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    DayAdapterInfo info;
65213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    do {
65313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        info = mAdapterInfos.poll();
65413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (info != null) {
655bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                            // TODO the following causes ANR's. Do this in a thread.
65613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            info.cursor.close();
65713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            deletedRows += info.size;
65813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            recycleMe = info;
65913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
66013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } while (info != null);
66113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
66213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (recycleMe != null) {
66313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe.cursor = null;
66413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe.size = deletedRows;
66513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
66613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
66713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
66813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return recycleMe;
66913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
67013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
67113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
67213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private String buildQuerySelection() {
67313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        // Respect the preference to show/hide declined events
67413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
67513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (mHideDeclined) {
676950e8a615f3dcca0b61b2eb8f8de72ecf6825d4bAndy McFadden            return Calendars.VISIBLE + "=1 AND "
67713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    + Instances.SELF_ATTENDEE_STATUS + "!="
67813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    + Attendees.ATTENDEE_STATUS_DECLINED;
67913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
680950e8a615f3dcca0b61b2eb8f8de72ecf6825d4bAndy McFadden            return Calendars.VISIBLE + "=1";
68113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
68213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
68313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
6849138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private Uri buildQueryUri(int start, int end, String searchQuery) {
6859138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        Uri rootUri = searchQuery == null ?
6869138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                Instances.CONTENT_BY_DAY_URI :
6879138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                Instances.CONTENT_SEARCH_BY_DAY_URI;
6889138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        Uri.Builder builder = rootUri.buildUpon();
6899138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        ContentUris.appendId(builder, start);
6909138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        ContentUris.appendId(builder, end);
6919138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        if (searchQuery != null) {
6929138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang            builder.appendPath(searchQuery);
6939138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        }
6949138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        return builder.build();
69513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
69613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
69713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean isInRange(int start, int end) {
69813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
69913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (mAdapterInfos.isEmpty()) {
70013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return false;
70113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
70213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return mAdapterInfos.getFirst().start <= start && end <= mAdapterInfos.getLast().end;
70313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
70413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
70513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
70613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int calculateQueryDuration(int start, int end) {
70713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int queryDuration = MAX_QUERY_DURATION;
70813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (mRowCount != 0) {
70913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queryDuration = IDEAL_NUM_OF_EVENTS * (end - start + 1) / mRowCount;
71013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
71113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
71213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (queryDuration > MAX_QUERY_DURATION) {
71313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queryDuration = MAX_QUERY_DURATION;
71413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else if (queryDuration < MIN_QUERY_DURATION) {
71513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queryDuration = MIN_QUERY_DURATION;
71613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
71713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
71813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return queryDuration;
71913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
72013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
7219138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private boolean queueQuery(int start, int end, Time goToTime,
7229138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang            String searchQuery, int queryType) {
72313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        QuerySpec queryData = new QuerySpec(queryType);
72413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        queryData.goToTime = goToTime;
72513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        queryData.start = start;
72613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        queryData.end = end;
7279138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        queryData.searchQuery = searchQuery;
72813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return queueQuery(queryData);
72913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
73013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
73113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean queueQuery(QuerySpec queryData) {
7329138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        queryData.searchQuery = mSearchQuery;
73313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Boolean queuedQuery;
73413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mQueryQueue) {
73513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queuedQuery = false;
73613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Boolean doQueryNow = mQueryQueue.isEmpty();
73723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            mQueryQueue.add(queryData);
73823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            queuedQuery = true;
73923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (doQueryNow) {
74023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                doQuery(queryData);
74113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
74213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
74313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return queuedQuery;
74413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
74513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
74613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private void doQuery(QuerySpec queryData) {
74713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (!mAdapterInfos.isEmpty()) {
74813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int start = mAdapterInfos.getFirst().start;
74913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int end = mAdapterInfos.getLast().end;
75013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int queryDuration = calculateQueryDuration(start, end);
75113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            switch(queryData.queryType) {
75213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                case QUERY_TYPE_OLDER:
75313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.end = start - 1;
75413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.start = queryData.end - queryDuration;
75513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    break;
75613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                case QUERY_TYPE_NEWER:
75713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.start = end + 1;
75813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.end = queryData.start + queryDuration;
75913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    break;
76013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
76113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
76213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
76313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (BASICLOG) {
7649a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            Time time = new Time(mTimeZone);
76513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.setJulianDay(queryData.start);
7669a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            Time time2 = new Time(mTimeZone);
76713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time2.setJulianDay(queryData.end);
76813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Log.v(TAG, "startQuery: " + time.toString() + " to "
76913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    + time2.toString() + " then go to " + queryData.goToTime);
77013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
77113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
77213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mQueryHandler.cancelOperation(0);
77313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (BASICLOG) queryData.queryStartMillis = System.nanoTime();
7749138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
7759138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        Uri queryUri = buildQueryUri(
7769138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                queryData.start, queryData.end, queryData.searchQuery);
7779138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mQueryHandler.startQuery(0, queryData, queryUri,
7789138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                PROJECTION, buildQuerySelection(), null,
7799138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                AGENDA_SORT_ORDER);
78013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
78113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
78213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private String formatDateString(int julianDay) {
7839a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        Time time = new Time(mTimeZone);
78413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        time.setJulianDay(julianDay);
78513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long millis = time.toMillis(false);
78613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder.setLength(0);
78713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return DateUtils.formatDateRange(mContext, mFormatter, millis, millis,
78813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE
7899a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                        | DateUtils.FORMAT_ABBREV_MONTH, mTimeZone).toString();
79013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
79113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
79213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private void updateHeaderFooter(final int start, final int end) {
79313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHeaderView.setText(mContext.getString(R.string.show_older_events,
79413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                formatDateString(start)));
79513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFooterView.setText(mContext.getString(R.string.show_newer_events,
79613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                formatDateString(end)));
79713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
79813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
79913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private class QueryHandler extends AsyncQueryHandler {
80013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
80113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public QueryHandler(ContentResolver cr) {
80213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            super(cr);
80313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
80413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
80513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        @Override
80613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
80713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            QuerySpec data = (QuerySpec)cookie;
80813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (BASICLOG) {
80913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                long queryEndMillis = System.nanoTime();
81013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Log.e(TAG, "Query time(ms): "
81113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        + (queryEndMillis - data.queryStartMillis) / 1000000
81213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        + " Count: " + cursor.getCount());
81313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
81413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
81513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (mShuttingDown) {
81613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                cursor.close();
81713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return;
81813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
81913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
82013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            // Notify Listview of changes and update position
82113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int cursorSize = cursor.getCount();
8227278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik            if (cursorSize > 0 || mAdapterInfos.isEmpty() || data.queryType == QUERY_TYPE_CLEAN) {
82313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                final int listPositionOffset = processNewCursor(data, cursor);
82413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (data.goToTime == null) { // Typical Scrolling type query
82513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    notifyDataSetChanged();
82613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (listPositionOffset != 0) {
82713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        mAgendaListView.shiftSelection(listPositionOffset);
82813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
82913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else { // refresh() called. Go to the designated position
83013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    final Time goToTime = data.goToTime;
83113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    notifyDataSetChanged();
83213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    int newPosition = findDayPositionNearestTime(goToTime);
83313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (newPosition >= 0) {
834cf6a46c5c81334f7c960ecc5fd354a14f1c4037cMichael Chan                        mAgendaListView.setSelection(newPosition + OFF_BY_ONE_BUG
835cf6a46c5c81334f7c960ecc5fd354a14f1c4037cMichael Chan                                + mSkipDateHeader);
836e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        Time actualTime = new Time(mTimeZone);
837e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        actualTime.set(mAgendaListView.getFirstVisibleTime());
838e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        CalendarController.getInstance(mContext).sendEvent(this,
839e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                                EventType.UPDATE_TITLE, actualTime, actualTime, -1,
840e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                                ViewType.CURRENT);
84113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
8427278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik                    if (DEBUGLOG) {
84313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        Log.e(TAG, "Setting listview to " +
8447278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik                                "findDayPositionNearestTime: " + (newPosition + OFF_BY_ONE_BUG));
8457278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik                    }
84613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
847ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
84892ea39440681f86205ad10771f1770c550552320Michael Chan                // size == 1 means a fresh query. Possibly after the data changed.
84992ea39440681f86205ad10771f1770c550552320Michael Chan                // Let's check whether mSelectedInstanceId is still valid.
85092ea39440681f86205ad10771f1770c550552320Michael Chan                if (mAdapterInfos.size() == 1 && mSelectedInstanceId != -1) {
85192ea39440681f86205ad10771f1770c550552320Michael Chan                    boolean found = false;
85292ea39440681f86205ad10771f1770c550552320Michael Chan                    cursor.moveToPosition(-1);
85392ea39440681f86205ad10771f1770c550552320Michael Chan                    while (cursor.moveToNext()) {
85492ea39440681f86205ad10771f1770c550552320Michael Chan                        if (mSelectedInstanceId == cursor
85592ea39440681f86205ad10771f1770c550552320Michael Chan                                .getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID)) {
85692ea39440681f86205ad10771f1770c550552320Michael Chan                            found = true;
85792ea39440681f86205ad10771f1770c550552320Michael Chan                            break;
85892ea39440681f86205ad10771f1770c550552320Michael Chan                        }
85992ea39440681f86205ad10771f1770c550552320Michael Chan                    };
86092ea39440681f86205ad10771f1770c550552320Michael Chan
86192ea39440681f86205ad10771f1770c550552320Michael Chan                    if (!found) {
86292ea39440681f86205ad10771f1770c550552320Michael Chan                        mSelectedInstanceId = -1;
86392ea39440681f86205ad10771f1770c550552320Michael Chan                    }
86492ea39440681f86205ad10771f1770c550552320Michael Chan                }
86592ea39440681f86205ad10771f1770c550552320Michael Chan
866ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan                if (mSelectedInstanceId == -1 && cursor.moveToFirst()) {
867ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan                    mSelectedInstanceId = cursor.getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID);
868ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
869ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan                    EventInfo event = buildEventInfoFromCursor(cursor, false);
87096a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                    if (mShowEventOnStart) {
87196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                        CalendarController.getInstance(mContext).sendEventRelatedEvent(this,
87296a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                                EventType.VIEW_EVENT, event.id, event.begin, event.end, 0, 0, -1);
87396a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                    }
874ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan                }
87513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else {
87613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                cursor.close();
87713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
87813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
87913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            // Update header and footer
88013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (!mDoneSettingUpHeaderFooter) {
88113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                OnClickListener headerFooterOnClickListener = new OnClickListener() {
88213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    public void onClick(View v) {
88313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (v == mHeaderView) {
88413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            queueQuery(new QuerySpec(QUERY_TYPE_OLDER));
88513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        } else {
88613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            queueQuery(new QuerySpec(QUERY_TYPE_NEWER));
88713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
88813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }};
88913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mHeaderView.setOnClickListener(headerFooterOnClickListener);
89013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mFooterView.setOnClickListener(headerFooterOnClickListener);
89113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mAgendaListView.addFooterView(mFooterView);
89213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mDoneSettingUpHeaderFooter = true;
89313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
89413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            synchronized (mQueryQueue) {
89513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int totalAgendaRangeStart = -1;
89613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int totalAgendaRangeEnd = -1;
89713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
89813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (cursorSize != 0) {
89913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // Remove the query that just completed
90013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    QuerySpec x = mQueryQueue.poll();
90123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    if (BASICLOG && !x.equals(data)) {
90223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        Log.e(TAG, "onQueryComplete - cookie != head of queue");
90323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    }
90413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mEmptyCursorCount = 0;
90523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    if (data.queryType == QUERY_TYPE_NEWER) {
90623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        mNewerRequestsProcessed++;
90723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    } else if (data.queryType == QUERY_TYPE_OLDER) {
90823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        mOlderRequestsProcessed++;
90923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    }
91013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
91113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    totalAgendaRangeStart = mAdapterInfos.getFirst().start;
91213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    totalAgendaRangeEnd = mAdapterInfos.getLast().end;
91313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else { // CursorSize == 0
91413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    QuerySpec querySpec = mQueryQueue.peek();
91513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
91613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // Update Adapter Info with new start and end date range
91713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (!mAdapterInfos.isEmpty()) {
91813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        DayAdapterInfo first = mAdapterInfos.getFirst();
91913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        DayAdapterInfo last = mAdapterInfos.getLast();
92013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
92113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (first.start - 1 <= querySpec.end && querySpec.start < first.start) {
92213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            first.start = querySpec.start;
92313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
92413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
92513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (querySpec.start <= last.end + 1 && last.end < querySpec.end) {
92613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            last.end = querySpec.end;
92713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
92813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
92913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeStart = first.start;
93013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeEnd = last.end;
93113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } else {
93213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeStart = querySpec.start;
93313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeEnd = querySpec.end;
93413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
93513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
93613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // Update query specification with expanded search range
93713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // and maybe rerun query
93813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    switch (querySpec.queryType) {
93913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        case QUERY_TYPE_OLDER:
94013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeStart = querySpec.start;
94113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.start -= MAX_QUERY_DURATION;
94213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            break;
94313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        case QUERY_TYPE_NEWER:
94413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeEnd = querySpec.end;
94513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.end += MAX_QUERY_DURATION;
94613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            break;
94713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        case QUERY_TYPE_CLEAN:
94813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeStart = querySpec.start;
94913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeEnd = querySpec.end;
95013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.start -= MAX_QUERY_DURATION / 2;
95113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.end += MAX_QUERY_DURATION / 2;
95213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            break;
95313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
95413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
95513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (++mEmptyCursorCount > RETRIES_ON_NO_DATA) {
95613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Nothing in the cursor again. Dropping query
95713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        mQueryQueue.poll();
95813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
95913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
96013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
96113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                updateHeaderFooter(totalAgendaRangeStart, totalAgendaRangeEnd);
96213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
9632d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                // Go over the events and mark the first day after yesterday
9642d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                // that has events in it
9652d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                synchronized (mAdapterInfos) {
9662d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    DayAdapterInfo info = mAdapterInfos.getFirst();
9672d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    if (info != null) {
9682d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        Time time = new Time(mTimeZone);
9692d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        long now = System.currentTimeMillis();
9702d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        time.set(now);
9712d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        int JulianToday = Time.getJulianDay(now, time.gmtoff);
9722d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        Iterator<DayAdapterInfo> iter = mAdapterInfos.iterator();
9732d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        boolean foundDay = false;
9742d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        while (iter.hasNext() && !foundDay) {
9752d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                            info = iter.next();
9762d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                            for (int i = 0; i < info.size; i++) {
9772d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                if (info.dayAdapter.findJulianDayFromPosition(i) >= JulianToday) {
9782d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                    info.dayAdapter.setAsFirstDayAfterYesterday(i);
9792d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                    foundDay = true;
9802d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                    break;
9812d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                }
9822d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                            }
9832d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        }
9842d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    }
9852d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                }
9862d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
98713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Fire off the next query if any
98813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Iterator<QuerySpec> it = mQueryQueue.iterator();
98913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                while (it.hasNext()) {
99013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    QuerySpec queryData = it.next();
99113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (!isInRange(queryData.start, queryData.end)) {
99213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Query accepted
99313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (DEBUGLOG) Log.e(TAG, "Query accepted. QueueSize:" + mQueryQueue.size());
99413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        doQuery(queryData);
99513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        break;
99613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } else {
99713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Query rejected
99813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        it.remove();
99913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (DEBUGLOG) Log.e(TAG, "Query rejected. QueueSize:" + mQueryQueue.size());
100013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
100113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
100213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
100323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (BASICLOG) {
100413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                for (DayAdapterInfo info3 : mAdapterInfos) {
100513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    Log.e(TAG, "> " + info3.toString());
100613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
100713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
100813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
100913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
101013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        /*
101113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         * Update the adapter info array with a the new cursor. Close out old
101213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         * cursors as needed.
101313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         *
101413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         * @return number of rows removed from the beginning
101513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         */
101613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        private int processNewCursor(QuerySpec data, Cursor cursor) {
101713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            synchronized (mAdapterInfos) {
101813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Remove adapter info's from adapterInfos as needed
101913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                DayAdapterInfo info = pruneAdapterInfo(data.queryType);
102013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int listPositionOffset = 0;
102113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (info == null) {
102213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    info = new DayAdapterInfo(mContext);
102313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else {
102413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (DEBUGLOG)
102513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        Log.e(TAG, "processNewCursor listPositionOffsetA="
102613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                                + -info.size);
102713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    listPositionOffset = -info.size;
102813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
102913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
103013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Setup adapter info
103113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.start = data.start;
103213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.end = data.end;
103313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.cursor = cursor;
1034dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan                info.dayAdapter.changeCursor(info);
103513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.size = info.dayAdapter.getCount();
103613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
103713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Insert into adapterInfos
103813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (mAdapterInfos.isEmpty()
103913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        || data.end <= mAdapterInfos.getFirst().start) {
104013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mAdapterInfos.addFirst(info);
104113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    listPositionOffset += info.size;
104213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else if (BASICLOG && data.start < mAdapterInfos.getLast().end) {
104313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mAdapterInfos.addLast(info);
104413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    for (DayAdapterInfo info2 : mAdapterInfos) {
104513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        Log.e("========== BUG ==", info2.toString());
104613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
104713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else {
104813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mAdapterInfos.addLast(info);
104913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
105013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
105113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Update offsets in adapterInfos
105213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mRowCount = 0;
105313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                for (DayAdapterInfo info3 : mAdapterInfos) {
105413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    info3.offset = mRowCount;
105513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mRowCount += info3.size;
105613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
105713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mLastUsedInfo = null;
105813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
105913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return listPositionOffset;
106013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
106113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
106213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
106313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
106413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static String getViewTitle(View x) {
106513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        String title = "";
106613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (x != null) {
106713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Object yy = x.getTag();
106813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (yy instanceof AgendaAdapter.ViewHolder) {
106913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                TextView tv = ((AgendaAdapter.ViewHolder) yy).title;
107013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (tv != null) {
107113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    title = (String) tv.getText();
107213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
107313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else if (yy != null) {
107413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                TextView dateView = ((AgendaByDayAdapter.ViewHolder) yy).dateView;
107513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (dateView != null) {
107613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    title = (String) dateView.getText();
107713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
107813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
107913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
108013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return title;
108113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
108213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
10839a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    public void onResume() {
10849a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTZUpdater.run();
10859a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    }
10869a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
108713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public void setHideDeclinedEvents(boolean hideDeclined) {
108813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHideDeclined = hideDeclined;
108913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
1090a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
1091ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public void setSelectedView(View v) {
1092ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (v != null) {
1093ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            Object vh = v.getTag();
1094ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            if (vh instanceof AgendaAdapter.ViewHolder) {
1095ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan                mSelectedInstanceId = ((AgendaAdapter.ViewHolder) vh).instanceId;
1096ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            }
1097ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        }
1098ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    }
1099ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
1100ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public long getSelectedInstanceId() {
1101ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        return mSelectedInstanceId;
1102ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    }
1103ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
1104ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public void setSelectedInstanceId(long selectedInstanceId) {
1105ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        mSelectedInstanceId = selectedInstanceId;
1106a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    }
110737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
110837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
110937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Implementation of HeaderIndexer interface for StickyHeeaderListView
111037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
111137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the location of the day header of a specific event specified in the position
111237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // in the adapter
111337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderPositionFromItemPosition(int position) {
1114980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
1115980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        // For phone configuration, return -1 so there will be no sticky header
1116980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        if (!mIsTabletConfig) {
1117980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            return -1;
1118980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        }
1119980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
112037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(position);
112137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (info != null) {
112237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            int pos = info.dayAdapter.getHeaderPosition(position - info.offset);
112337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return (pos != -1)?(pos + info.offset):-1;
112437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
112537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
112637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
112737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
112837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the number of events for a specific day header
112937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderItemsNumber(int headerPosition) {
1130980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        if (headerPosition < 0 || !mIsTabletConfig) {
113137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
113237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
113337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(headerPosition);
113437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (info != null) {
113537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return info.dayAdapter.getHeaderItemsCount(headerPosition - info.offset);
113637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
113737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
113837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
113913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan}
1140