AgendaWindowAdapter.java revision b996adff74022fc78ff02c4f7e6149ea6342a7c6
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;
33c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelsonimport android.os.Handler;
34a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract;
35a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees;
36a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Calendars;
37a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Instances;
3813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.DateUtils;
3913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.Time;
4013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.util.Log;
4113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.LayoutInflater;
4213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View;
4313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View.OnClickListener;
449a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport android.view.ViewGroup;
45c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelsonimport android.widget.AbsListView;
46c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelsonimport android.widget.AbsListView.OnScrollListener;
4713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.BaseAdapter;
4813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.TextView;
4913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
5013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Formatter;
5113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Iterator;
5213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.LinkedList;
5313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Locale;
5413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.concurrent.ConcurrentLinkedQueue;
5513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
5613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan/*
5713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanBugs Bugs Bugs:
5813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- At rotation and launch time, the initial position is not set properly. This code is calling
5913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan listview.setSelection() in 2 rapid secessions but it dropped or didn't process the first one.
6013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Scroll using trackball isn't repositioning properly after a new adapter is added.
6123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan- Track ball clicks at the header/footer doesn't work.
6213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Potential ping pong effect if the prefetch window is big and data is limited
6313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Add index in calendar provider
6413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
6513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanToDo ToDo ToDo:
6613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanGet design of header and footer from designer
6713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
6813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanMake scrolling smoother.
6913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanTest for correctness
7013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanLoading speed
7113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanCheck for leaks and excessive allocations
7213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */
7313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
7437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonpublic class AgendaWindowAdapter extends BaseAdapter
75c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    implements StickyHeaderListView.HeaderIndexer, StickyHeaderListView.HeaderHeightListener{
7613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
7723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    static final boolean BASICLOG = false;
7892c6688283442c800b4de0ca76c0e05a089f84c3RoboErik    static final boolean DEBUGLOG = false;
79a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    private static final String TAG = "AgendaWindowAdapter";
8013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
819138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private static final String AGENDA_SORT_ORDER =
82a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErik            CalendarContract.Instances.START_DAY + " ASC, " +
83a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErik            CalendarContract.Instances.BEGIN + " ASC, " +
84a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErik            CalendarContract.Events.TITLE + " ASC";
859138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
86ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public static final int INDEX_INSTANCE_ID = 0;
8713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_TITLE = 1;
8813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_EVENT_LOCATION = 2;
8913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_ALL_DAY = 3;
9013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_HAS_ALARM = 4;
9113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_COLOR = 5;
9213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_RRULE = 6;
9313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_BEGIN = 7;
9413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_END = 8;
9513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_EVENT_ID = 9;
9613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_START_DAY = 10;
9713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_END_DAY = 11;
9813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public static final int INDEX_SELF_ATTENDEE_STATUS = 12;
99056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson    public static final int INDEX_ORGANIZER = 13;
100056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson    public static final int INDEX_OWNER_ACCOUNT = 14;
101056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson    public static final int INDEX_CAN_ORGANIZER_RESPOND= 15;
1021121e409c5f504e8df75982475d8cc607d5f0dfaRoboErik    public static final int INDEX_TIME_ZONE = 16;
10313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
10413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final String[] PROJECTION = new String[] {
10513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances._ID, // 0
10613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.TITLE, // 1
10713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.EVENT_LOCATION, // 2
10813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.ALL_DAY, // 3
10913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.HAS_ALARM, // 4
1100e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik            Instances.CALENDAR_COLOR, // 5
11113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.RRULE, // 6
11213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.BEGIN, // 7
11313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.END, // 8
11413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.EVENT_ID, // 9
11513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.START_DAY, // 10 Julian start day
11613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.END_DAY, // 11 Julian end day
11713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Instances.SELF_ATTENDEE_STATUS, // 12
118056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson            Instances.ORGANIZER, // 13
119056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson            Instances.OWNER_ACCOUNT, // 14
120056079920bc9d141241648662ad4ebdea91b1fd4Isaac Katzenelson            Instances.CAN_ORGANIZER_RESPOND, // 15
1211121e409c5f504e8df75982475d8cc607d5f0dfaRoboErik            Instances.EVENT_TIMEZONE, // 16
12213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    };
12313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
12413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Listview may have a bug where the index/position is not consistent when there's a header.
125a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    // position == positionInListView - OFF_BY_ONE_BUG
12613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // TODO Need to look into this.
12713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int OFF_BY_ONE_BUG = 1;
12813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int MAX_NUM_OF_ADAPTERS = 5;
12913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int IDEAL_NUM_OF_EVENTS = 50;
13013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int MIN_QUERY_DURATION = 7; // days
13113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int MAX_QUERY_DURATION = 60; // days
13213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int PREFETCH_BOUNDARY = 1;
13313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1349138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** Times to auto-expand/retry query after getting no data */
1359138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private static final int RETRIES_ON_NO_DATA = 1;
13613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
13713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private Context mContext;
138a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    private Resources mResources;
13913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private QueryHandler mQueryHandler;
14013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private AgendaListView mAgendaListView;
14113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1429138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** The sum of the rows in all the adapters */
1439138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private int mRowCount;
14413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1459138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** The number of times we have queried and gotten no results back */
14613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mEmptyCursorCount;
14713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1489138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** Cached value of the last used adapter */
1499138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private DayAdapterInfo mLastUsedInfo;
15013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
151a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    private final LinkedList<DayAdapterInfo> mAdapterInfos =
152a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa            new LinkedList<DayAdapterInfo>();
153a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    private final ConcurrentLinkedQueue<QuerySpec> mQueryQueue =
154a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa            new ConcurrentLinkedQueue<QuerySpec>();
15513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private TextView mHeaderView;
15613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private TextView mFooterView;
15713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean mDoneSettingUpHeaderFooter = false;
15813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
159980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson    private final boolean mIsTabletConfig;
160980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
161c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    boolean mCleanQueryInitiated = false;
162c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private int mStickyHeaderSize = 44; // Initial size big enough for it to work
163c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1649138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /**
16513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * When the user scrolled to the top, a query will be made for older events
16613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * and this will be incremented. Don't make more requests if
16713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * mOlderRequests > mOlderRequestsProcessed.
16813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     */
16913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mOlderRequests;
17013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1719138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** Number of "older" query that has been processed. */
17213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mOlderRequestsProcessed;
17313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1749138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /**
17513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * When the user scrolled to the bottom, a query will be made for newer
17613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * events and this will be incremented. Don't make more requests if
17713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     * mNewerRequests > mNewerRequestsProcessed.
17813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan     */
17913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mNewerRequests;
18013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
1819138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** Number of "newer" query that has been processed. */
18213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int mNewerRequestsProcessed;
18313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
18423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    // Note: Formatter is not thread safe. Fine for now as it is only used by the main thread.
18523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan    private Formatter mFormatter;
18613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private StringBuilder mStringBuilder;
1879a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private String mTimeZone;
1889a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
18996a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson    // defines if to pop-up the current event when the agenda is first shown
19096a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson    private boolean mShowEventOnStart;
19196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson
1929a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private Runnable mTZUpdater = new Runnable() {
1939a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        @Override
1949a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        public void run() {
1959a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            mTimeZone = Utils.getTimeZone(mContext, this);
1969a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            notifyDataSetChanged();
1979a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        }
1989a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    };
19913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
20013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean mShuttingDown;
20113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean mHideDeclined;
20213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
203c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    // Used to stop a fling motion if the ListView is set to a specific position
204c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    int mListViewScrollState = OnScrollListener.SCROLL_STATE_IDLE;
205c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
2069138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    /** The current search query, or null if none */
2079138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private String mSearchQuery;
2089138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
209ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    private long mSelectedInstanceId = -1;
210a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
211163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan    private final int mSelectedItemBackgroundColor;
212163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan    private final int mSelectedItemTextColor;
213a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
21413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Types of Query
21513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int QUERY_TYPE_OLDER = 0; // Query for older events
21613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int QUERY_TYPE_NEWER = 1; // Query for newer events
21713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int QUERY_TYPE_CLEAN = 2; // Delete everything and query around a date
21813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
21913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static class QuerySpec {
22013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long queryStartMillis;
22113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Time goToTime;
22213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int start;
22313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int end;
2249138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        String searchQuery;
22513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int queryType;
226c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        long id;
22713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
22813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public QuerySpec(int queryType) {
22913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            this.queryType = queryType;
230c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            id = -1;
23113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
23223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan
23323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        @Override
23423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        public int hashCode() {
23523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            final int prime = 31;
23623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            int result = 1;
23723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + end;
23823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + (int) (queryStartMillis ^ (queryStartMillis >>> 32));
23923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + queryType;
24023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + start;
2412f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            if (searchQuery != null) {
2422f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                result = prime * result + searchQuery.hashCode();
2432f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            }
24423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (goToTime != null) {
24523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                long goToTimeMillis = goToTime.toMillis(false);
24623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                result = prime * result + (int) (goToTimeMillis ^ (goToTimeMillis >>> 32));
24723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
248c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            result = prime * result + (int)id;
24923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            return result;
25023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        }
25123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan
25223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        @Override
25323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        public boolean equals(Object obj) {
25423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (this == obj) return true;
25523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (obj == null) return false;
25623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (getClass() != obj.getClass()) return false;
25723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            QuerySpec other = (QuerySpec) obj;
25823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (end != other.end || queryStartMillis != other.queryStartMillis
2599138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                    || queryType != other.queryType || start != other.start
260c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    || Utils.equals(searchQuery, other.searchQuery) || id != other.id) {
26123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                return false;
26223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
2639138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
26423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (goToTime != null) {
26523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                if (goToTime.toMillis(false) != other.goToTime.toMillis(false)) {
26623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    return false;
26723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                }
26823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            } else {
26923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                if (other.goToTime != null) {
27023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    return false;
27123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                }
27223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
27323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            return true;
27423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        }
27513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
27613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
27713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static class EventInfo {
27813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long begin;
27913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long end;
28013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long id;
281ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        int startDay;
28213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
28313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
284dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    static class DayAdapterInfo {
28513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Cursor cursor;
28613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        AgendaByDayAdapter dayAdapter;
28713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int start; // start day of the cursor's coverage
28813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int end; // end day of the cursor's coverage
28913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int offset; // offset in position in the list view
29013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int size; // dayAdapter.getCount()
29113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
29213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public DayAdapterInfo(Context context) {
29313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            dayAdapter = new AgendaByDayAdapter(context);
29413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
29513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
29613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        @Override
29713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public String toString() {
2989a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // Static class, so the time in this toString will not reflect the
2999a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // home tz settings. This should only affect debugging.
30013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Time time = new Time();
30113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            StringBuilder sb = new StringBuilder();
30213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.setJulianDay(start);
30313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.normalize(false);
30413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append("Start:").append(time.toString());
30513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.setJulianDay(end);
30613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.normalize(false);
30713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append(" End:").append(time.toString());
30813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append(" Offset:").append(offset);
30913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append(" Size:").append(size);
31013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return sb.toString();
31113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
31213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
31313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
3149138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    public AgendaWindowAdapter(Context context,
31596a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson            AgendaListView agendaListView, boolean showEventOnStart) {
3169138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mContext = context;
317a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        mResources = context.getResources();
318163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan        mSelectedItemBackgroundColor = mResources
319163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                .getColor(R.color.agenda_selected_background_color);
320163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan        mSelectedItemTextColor = mResources.getColor(R.color.agenda_selected_text_color);
321980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        mIsTabletConfig = Utils.getConfigBool(mContext, R.bool.tablet_config);
322a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
3239a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTimeZone = Utils.getTimeZone(context, mTZUpdater);
32413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaListView = agendaListView;
3259138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mQueryHandler = new QueryHandler(context.getContentResolver());
32613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
32713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder = new StringBuilder(50);
32813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
32913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
33096a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson        mShowEventOnStart = showEventOnStart;
33196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson
332c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // Implies there is no sticky header
333c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (!mShowEventOnStart) {
334c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mStickyHeaderSize = 0;
335c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
3369138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mSearchQuery = null;
3379138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
3389138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        LayoutInflater inflater = (LayoutInflater) context
33913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
34013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHeaderView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null);
34113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFooterView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null);
34213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHeaderView.setText(R.string.loading);
34313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaListView.addHeaderView(mHeaderView);
34413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
34513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
34613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in Adapter
34713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
34813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public int getViewTypeCount() {
34913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return AgendaByDayAdapter.TYPE_LAST;
35013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
35113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
35213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in BaseAdapter
35313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
35413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public boolean areAllItemsEnabled() {
35513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return false;
35613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
35713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
35813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in Adapter
35913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
36013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public int getItemViewType(int position) {
36113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
36213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
36313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.dayAdapter.getItemViewType(position - info.offset);
36413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
36513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return -1;
36613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
36713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
36813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
36913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in BaseAdapter
37013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
37113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public boolean isEnabled(int position) {
37213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
37313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
37413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.dayAdapter.isEnabled(position - info.offset);
37513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
37613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return false;
37713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
37813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
37913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
38013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
38113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public int getCount() {
38213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return mRowCount;
38313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
38413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
38513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
38613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public Object getItem(int position) {
38713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
38813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
38913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.dayAdapter.getItem(position - info.offset);
39013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
39113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return null;
39213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
39313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
39413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
395c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    // Method in BaseAdapter
396c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    @Override
397c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    public boolean hasStableIds() {
398c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan        return true;
399c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    }
400c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan
40113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
402c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    @Override
40313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public long getItemId(int position) {
40413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
40513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
406c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            int curPos = info.dayAdapter.getCursorPosition(position - info.offset);
407c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (curPos == Integer.MIN_VALUE) {
408c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                return -1;
409c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
410c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Regular event
411c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (curPos >= 0) {
412c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                info.cursor.moveToPosition(curPos);
413c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                return info.cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID) << 20 +
414c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    info.cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN);
415c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
416c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Day Header
417c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return info.dayAdapter.findJulianDayFromPosition(position);
418c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
41913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
42013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return -1;
42113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
42213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
42313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
42413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
42513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public View getView(int position, View convertView, ViewGroup parent) {
42613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (position >= (mRowCount - PREFETCH_BOUNDARY)
42713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                && mNewerRequests <= mNewerRequestsProcessed) {
42813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (DEBUGLOG) Log.e(TAG, "queryForNewerEvents: ");
42913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mNewerRequests++;
43013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queueQuery(new QuerySpec(QUERY_TYPE_NEWER));
43113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
43213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
43313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (position < PREFETCH_BOUNDARY
43413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                && mOlderRequests <= mOlderRequestsProcessed) {
43513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (DEBUGLOG) Log.e(TAG, "queryForOlderEvents: ");
43613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mOlderRequests++;
43713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queueQuery(new QuerySpec(QUERY_TYPE_OLDER));
43813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
43913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
440a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        final View v;
44113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
44213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
4432d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            int offset = position - info.offset;
4442d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            v = info.dayAdapter.getView(offset, convertView,
44513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    parent);
4462d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
4472d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // Turn on the past/present separator if the view is a day header
4482d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // and it is the first day with events after yesterday.
4492d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            if (info.dayAdapter.isDayHeaderView(offset)) {
4502d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                View simpleDivider = v.findViewById(R.id.top_divider_simple);
4512d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                View pastPresentDivider = v.findViewById(R.id.top_divider_past_present);
4522d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                if (info.dayAdapter.isFirstDayAfterYesterday(offset)) {
4532d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    if (simpleDivider != null && pastPresentDivider != null) {
4542d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        simpleDivider.setVisibility(View.GONE);
4552d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        pastPresentDivider.setVisibility(View.VISIBLE);
4562d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    }
4572d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                } else if (simpleDivider != null && pastPresentDivider != null) {
4582d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    simpleDivider.setVisibility(View.VISIBLE);
4592d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    pastPresentDivider.setVisibility(View.GONE);
4602d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                }
4612d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            }
46213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
4632d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // TODO
46413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Log.e(TAG, "BUG: getAdapterInfoByPosition returned null!!! " + position);
46513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            TextView tv = new TextView(mContext);
46613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            tv.setText("Bug! " + position);
46713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            v = tv;
46813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
46913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
47033de4c48430262a0509ffe50fc376b87520cb938RoboErik        // If this is not a tablet config don't do selection highlighting
47133de4c48430262a0509ffe50fc376b87520cb938RoboErik        if (!mIsTabletConfig) {
47233de4c48430262a0509ffe50fc376b87520cb938RoboErik            return v;
47333de4c48430262a0509ffe50fc376b87520cb938RoboErik        }
474ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        // Show selected marker if this is item is selected
475ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        boolean selected = false;
476ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        Object yy = v.getTag();
477ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (yy instanceof AgendaAdapter.ViewHolder) {
478ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            AgendaAdapter.ViewHolder vh = (AgendaAdapter.ViewHolder) yy;
479ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            selected = mSelectedInstanceId == vh.instanceId;
48096a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson            vh.selectedMarker.setVisibility((selected && mShowEventOnStart) ?
48196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                    View.VISIBLE : View.GONE);
4827ef2981ab9ad32a6818b36cefbd39f070ba708edIsaac Katzenelson            if (selected && mShowEventOnStart) {
4839fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik                mSelectedVH = vh;
484163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                v.setBackgroundColor(mSelectedItemBackgroundColor);
485163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                vh.title.setTextColor(mSelectedItemTextColor);
486163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                vh.when.setTextColor(mSelectedItemTextColor);
487163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                vh.where.setTextColor(mSelectedItemTextColor);
488ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            }
489a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        }
490a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
49113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (DEBUGLOG) {
49213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Log.e(TAG, "getView " + position + " = " + getViewTitle(v));
49313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
49413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return v;
49513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
49613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
4979fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik    private AgendaAdapter.ViewHolder mSelectedVH = null;
4989fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik
499c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private int findEventPositionNearestTime(Time time, long id) {
500c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (DEBUGLOG) Log.e(TAG, "findEventPositionNearestTime " + time + " id " + id);
50113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByTime(time);
50213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
503c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return info.offset + info.dayAdapter.findEventPositionNearestTime(time, id);
50413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
50513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return -1;
50613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
50713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
50813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
5099a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    protected DayAdapterInfo getAdapterInfoByPosition(int position) {
51013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
51113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (mLastUsedInfo != null && mLastUsedInfo.offset <= position
51213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    && position < (mLastUsedInfo.offset + mLastUsedInfo.size)) {
51313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return mLastUsedInfo;
51413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
51513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            for (DayAdapterInfo info : mAdapterInfos) {
51613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (info.offset <= position
51713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        && position < (info.offset + info.size)) {
51813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mLastUsedInfo = info;
51913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    return info;
52013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
52113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
52213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
52313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return null;
52413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
52513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
52613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private DayAdapterInfo getAdapterInfoByTime(Time time) {
52713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (DEBUGLOG) Log.e(TAG, "getAdapterInfoByTime " + time.toString());
52813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
52913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Time tmpTime = new Time(time);
53013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long timeInMillis = tmpTime.normalize(true);
53113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int day = Time.getJulianDay(timeInMillis, tmpTime.gmtoff);
53213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
53313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            for (DayAdapterInfo info : mAdapterInfos) {
5348e597ca4f8eb3f9a3730d49aaeb431a0231af7d1Michael Chan                if (info.start <= day && day <= info.end) {
53513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    return info;
53613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
53713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
53813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
53913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return null;
54013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
54113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
542a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    public EventInfo getEventByPosition(final int positionInListView) {
54396d6163c524b338307b01d25916ccffd495e2f29Michael Chan        return getEventByPosition(positionInListView, true);
54496d6163c524b338307b01d25916ccffd495e2f29Michael Chan    }
54596d6163c524b338307b01d25916ccffd495e2f29Michael Chan
54696d6163c524b338307b01d25916ccffd495e2f29Michael Chan    /**
54796d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * Return the event info for a given position in the adapter
54896d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * @param positionInListView
54996d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * @param returnEventStartDay If true, return actual event startday. Otherwise
55096d6163c524b338307b01d25916ccffd495e2f29Michael Chan     *        return agenda date-header date as the startDay.
55196d6163c524b338307b01d25916ccffd495e2f29Michael Chan     *        The two will differ for multi-day events after the first day.
55296d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * @return
55396d6163c524b338307b01d25916ccffd495e2f29Michael Chan     */
55496d6163c524b338307b01d25916ccffd495e2f29Michael Chan    public EventInfo getEventByPosition(final int positionInListView,
55596d6163c524b338307b01d25916ccffd495e2f29Michael Chan            boolean returnEventStartDay) {
556a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (DEBUGLOG) Log.e(TAG, "getEventByPosition " + positionInListView);
5579fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik        if (positionInListView < 0) {
5589fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik            return null;
5599fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik        }
56013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
561a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        final int positionInAdapter = positionInListView - OFF_BY_ONE_BUG;
562a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        DayAdapterInfo info = getAdapterInfoByPosition(positionInAdapter);
56313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info == null) {
56413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return null;
56513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
56613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
567a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        int cursorPosition = info.dayAdapter.getCursorPosition(positionInAdapter - info.offset);
568a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (cursorPosition == Integer.MIN_VALUE) {
56913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return null;
57013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
57113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
57213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        boolean isDayHeader = false;
573a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (cursorPosition < 0) {
574a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa            cursorPosition = -cursorPosition;
57513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            isDayHeader = true;
57613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
57713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
578a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (cursorPosition < info.cursor.getCount()) {
579c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            EventInfo ei = buildEventInfoFromCursor(info.cursor, cursorPosition, isDayHeader);
58096d6163c524b338307b01d25916ccffd495e2f29Michael Chan            if (!returnEventStartDay && !isDayHeader) {
58196d6163c524b338307b01d25916ccffd495e2f29Michael Chan                ei.startDay = info.dayAdapter.findJulianDayFromPosition(cursorPosition);
58296d6163c524b338307b01d25916ccffd495e2f29Michael Chan            }
58396d6163c524b338307b01d25916ccffd495e2f29Michael Chan            return ei;
58413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
58513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return null;
58613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
58713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
588c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private EventInfo buildEventInfoFromCursor(final Cursor cursor, int cursorPosition,
589c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            boolean isDayHeader) {
590c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (cursorPosition == -1) {
591c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            cursor.moveToFirst();
592c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        } else {
593c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            cursor.moveToPosition(cursorPosition);
594c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
595ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        EventInfo event = new EventInfo();
596ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        event.begin = cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN);
597f836d4af478310abc9b63f1afa6ab964e2478fedRoboErik        event.end = cursor.getLong(AgendaWindowAdapter.INDEX_END);
598ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        event.startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY);
599ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
600ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        boolean allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0;
601ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (allDay) { // UTC
602ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            Time time = new Time(mTimeZone);
603ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.setJulianDay(Time.getJulianDay(event.begin, 0));
604ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            event.begin = time.toMillis(false /* use isDst */);
605ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        } else if (isDayHeader) { // Trim to midnight.
606ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            Time time = new Time(mTimeZone);
607ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.set(event.begin);
608ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.hour = 0;
609ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.minute = 0;
610ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.second = 0;
611ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            event.begin = time.toMillis(false /* use isDst */);
612ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        }
613ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
614ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (!isDayHeader) {
615ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            if (allDay) {
616ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                Time time = new Time(mTimeZone);
617ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                time.setJulianDay(Time.getJulianDay(event.end, 0));
618ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                event.end = time.toMillis(false /* use isDst */);
619ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            } else {
620ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                event.end = cursor.getLong(AgendaWindowAdapter.INDEX_END);
621ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            }
622ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson
623ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            event.id = cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID);
624ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        }
625ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        return event;
626ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    }
627ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
628c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public void refresh(Time goToTime, long id, String searchQuery, boolean forced,
629c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            boolean refreshEventInfo) {
6304003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        if (searchQuery != null) {
6314003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            mSearchQuery = searchQuery;
6324003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        }
6334003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang
634c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan        if (DEBUGLOG) {
635c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            Log.e(TAG, this + ": refresh " + goToTime.toString() + " id " + id
636c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    + ((searchQuery != null) ? searchQuery : "")
637c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    + (forced ? " forced" : " not forced")
638c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    + (refreshEventInfo ? " refresh event info" : ""));
639c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan        }
640b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson
64123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        int startDay = Time.getJulianDay(goToTime.toMillis(false), goToTime.gmtoff);
64213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
64313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (!forced && isInRange(startDay, startDay)) {
644ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            // No need to re-query
645ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            if (!mAgendaListView.isEventVisible(goToTime, id)) {
646c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                int gotoPosition = findEventPositionNearestTime(goToTime, id);
6478e597ca4f8eb3f9a3730d49aaeb431a0231af7d1Michael Chan                if (gotoPosition > 0) {
648c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    mAgendaListView.setSelectionFromTop(gotoPosition +
649b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                            OFF_BY_ONE_BUG, mStickyHeaderSize);
650c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (mListViewScrollState == OnScrollListener.SCROLL_STATE_FLING) {
651c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        mAgendaListView.smoothScrollBy(0, 0);
652c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
653c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (refreshEventInfo) {
654c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        long newInstanceId = findInstanceIdFromPosition(gotoPosition);
655c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        if (newInstanceId != getSelectedInstanceId()) {
656c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            setSelectedInstanceId(newInstanceId);
657c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            new Handler().post(new Runnable() {
658c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                @Override
659c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                public void run() {
660c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                    notifyDataSetChanged();
661c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                }
662c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            });
663c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            Cursor tempCursor = getCursorByPosition(gotoPosition);
664c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            if (tempCursor != null) {
665c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                int tempCursorPosition = getCursorPositionByPosition(gotoPosition);
666c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                EventInfo event =
667c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                        buildEventInfoFromCursor(tempCursor, tempCursorPosition,
668c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                                false);
669c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                CalendarController.getInstance(mContext).sendEventRelatedEvent(
670c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                        this, EventType.VIEW_EVENT, event.id, event.begin,
671c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                        event.end, 0, 0, -1);
672c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            }
673c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        }
674c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
6758e597ca4f8eb3f9a3730d49aaeb431a0231af7d1Michael Chan                }
676c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
677e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                Time actualTime = new Time(mTimeZone);
6784fe5d45eb8cbaac85764492e0a0b6c025771880aIsaac Katzenelson                if (goToTime != null) {
6794fe5d45eb8cbaac85764492e0a0b6c025771880aIsaac Katzenelson                    actualTime.set(goToTime);
6804fe5d45eb8cbaac85764492e0a0b6c025771880aIsaac Katzenelson                } else {
6814fe5d45eb8cbaac85764492e0a0b6c025771880aIsaac Katzenelson                    actualTime.set(mAgendaListView.getFirstVisibleTime());
6824fe5d45eb8cbaac85764492e0a0b6c025771880aIsaac Katzenelson                }
683e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                CalendarController.getInstance(mContext).sendEvent(this, EventType.UPDATE_TITLE,
684e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        actualTime, actualTime, -1, ViewType.CURRENT);
685ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            }
68613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return;
68713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
68813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
689c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // If AllInOneActivity is sending a second GOTO event(in OnResume), ignore it.
690c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (!mCleanQueryInitiated || searchQuery != null) {
691c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Query for a total of MIN_QUERY_DURATION days
692c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            int endDay = startDay + MIN_QUERY_DURATION;
69313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
694c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mSelectedInstanceId = -1;
695c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            queueQuery(startDay, endDay, goToTime, searchQuery, QUERY_TYPE_CLEAN, id);
696c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mCleanQueryInitiated = true;
6974fe5d45eb8cbaac85764492e0a0b6c025771880aIsaac Katzenelson
698c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Pre-fetch more data to overcome a race condition in AgendaListView.shiftSelection
699c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Queuing more data with the goToTime set to the selected time skips the call to
700c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // shiftSelection on refresh.
701c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mOlderRequests++;
702c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            queueQuery(0, 0, goToTime, searchQuery, QUERY_TYPE_OLDER, id);
703c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mNewerRequests++;
704c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            queueQuery(0, 0, goToTime, searchQuery, QUERY_TYPE_NEWER, id);
705c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
70613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
70713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
70813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public void close() {
70913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mShuttingDown = true;
71013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        pruneAdapterInfo(QUERY_TYPE_CLEAN);
71113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (mQueryHandler != null) {
71213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mQueryHandler.cancelOperation(0);
71313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
71413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
71513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
71613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private DayAdapterInfo pruneAdapterInfo(int queryType) {
71713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
71813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            DayAdapterInfo recycleMe = null;
71913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (!mAdapterInfos.isEmpty()) {
72013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (mAdapterInfos.size() >= MAX_NUM_OF_ADAPTERS) {
72113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (queryType == QUERY_TYPE_NEWER) {
72213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe = mAdapterInfos.removeFirst();
72313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } else if (queryType == QUERY_TYPE_OLDER) {
72413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe = mAdapterInfos.removeLast();
72513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Keep the size only if the oldest items are removed.
72613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe.size = 0;
72713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
72813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (recycleMe != null) {
72913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (recycleMe.cursor != null) {
73013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            recycleMe.cursor.close();
73113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
73213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        return recycleMe;
73313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
73413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
73513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
73613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (mRowCount == 0 || queryType == QUERY_TYPE_CLEAN) {
73713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mRowCount = 0;
73813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    int deletedRows = 0;
73913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    DayAdapterInfo info;
74013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    do {
74113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        info = mAdapterInfos.poll();
74213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (info != null) {
743bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                            // TODO the following causes ANR's. Do this in a thread.
74413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            info.cursor.close();
74513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            deletedRows += info.size;
74613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            recycleMe = info;
74713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
74813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } while (info != null);
74913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
75013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (recycleMe != null) {
75113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe.cursor = null;
75213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe.size = deletedRows;
75313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
75413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
75513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
75613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return recycleMe;
75713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
75813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
75913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
76013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private String buildQuerySelection() {
76113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        // Respect the preference to show/hide declined events
76213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
76313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (mHideDeclined) {
764950e8a615f3dcca0b61b2eb8f8de72ecf6825d4bAndy McFadden            return Calendars.VISIBLE + "=1 AND "
76513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    + Instances.SELF_ATTENDEE_STATUS + "!="
76613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    + Attendees.ATTENDEE_STATUS_DECLINED;
76713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
768950e8a615f3dcca0b61b2eb8f8de72ecf6825d4bAndy McFadden            return Calendars.VISIBLE + "=1";
76913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
77013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
77113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
7729138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private Uri buildQueryUri(int start, int end, String searchQuery) {
7739138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        Uri rootUri = searchQuery == null ?
7749138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                Instances.CONTENT_BY_DAY_URI :
7759138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                Instances.CONTENT_SEARCH_BY_DAY_URI;
7769138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        Uri.Builder builder = rootUri.buildUpon();
7779138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        ContentUris.appendId(builder, start);
7789138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        ContentUris.appendId(builder, end);
7799138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        if (searchQuery != null) {
7809138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang            builder.appendPath(searchQuery);
7819138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        }
7829138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        return builder.build();
78313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
78413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
78513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean isInRange(int start, int end) {
78613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
78713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (mAdapterInfos.isEmpty()) {
78813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return false;
78913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
79013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return mAdapterInfos.getFirst().start <= start && end <= mAdapterInfos.getLast().end;
79113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
79213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
79313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
79413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int calculateQueryDuration(int start, int end) {
79513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int queryDuration = MAX_QUERY_DURATION;
79613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (mRowCount != 0) {
79713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queryDuration = IDEAL_NUM_OF_EVENTS * (end - start + 1) / mRowCount;
79813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
79913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
80013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (queryDuration > MAX_QUERY_DURATION) {
80113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queryDuration = MAX_QUERY_DURATION;
80213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else if (queryDuration < MIN_QUERY_DURATION) {
80313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queryDuration = MIN_QUERY_DURATION;
80413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
80513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
80613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return queryDuration;
80713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
80813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
8099138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private boolean queueQuery(int start, int end, Time goToTime,
810c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            String searchQuery, int queryType, long id) {
81113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        QuerySpec queryData = new QuerySpec(queryType);
81213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        queryData.goToTime = goToTime;
81313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        queryData.start = start;
81413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        queryData.end = end;
8159138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        queryData.searchQuery = searchQuery;
816c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        queryData.id = id;
81713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return queueQuery(queryData);
81813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
81913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
82013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean queueQuery(QuerySpec queryData) {
8219138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        queryData.searchQuery = mSearchQuery;
82213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Boolean queuedQuery;
82313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mQueryQueue) {
82413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queuedQuery = false;
82513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Boolean doQueryNow = mQueryQueue.isEmpty();
82623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            mQueryQueue.add(queryData);
82723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            queuedQuery = true;
82823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (doQueryNow) {
82923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                doQuery(queryData);
83013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
83113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
83213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return queuedQuery;
83313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
83413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
83513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private void doQuery(QuerySpec queryData) {
83613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (!mAdapterInfos.isEmpty()) {
83713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int start = mAdapterInfos.getFirst().start;
83813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int end = mAdapterInfos.getLast().end;
83913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int queryDuration = calculateQueryDuration(start, end);
84013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            switch(queryData.queryType) {
84113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                case QUERY_TYPE_OLDER:
84213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.end = start - 1;
84313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.start = queryData.end - queryDuration;
84413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    break;
84513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                case QUERY_TYPE_NEWER:
84613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.start = end + 1;
84713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.end = queryData.start + queryDuration;
84813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    break;
84913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
8502f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan
8512f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            // By "compacting" cursors, this fixes the disco/ping-pong problem
8522f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            // b/5311977
8532f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            if (mRowCount < 20 && queryData.queryType != QUERY_TYPE_CLEAN) {
8542f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                if (DEBUGLOG) {
8552f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                    Log.e(TAG, "Compacting cursor: mRowCount=" + mRowCount
8562f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                            + " totalStart:" + start
8572f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                            + " totalEnd:" + end
8582f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                            + " query.start:" + queryData.start
8592f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                            + " query.end:" + queryData.end);
8602f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                }
8612f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan
8622f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                queryData.queryType = QUERY_TYPE_CLEAN;
8632f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan
8642f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                if (queryData.start > start) {
8652f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                    queryData.start = start;
8662f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                }
8672f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                if (queryData.end < end) {
8682f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                    queryData.end = end;
8692f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                }
8702f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            }
87113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
87213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
87313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (BASICLOG) {
8749a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            Time time = new Time(mTimeZone);
87513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.setJulianDay(queryData.start);
8769a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            Time time2 = new Time(mTimeZone);
87713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time2.setJulianDay(queryData.end);
87813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Log.v(TAG, "startQuery: " + time.toString() + " to "
87913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    + time2.toString() + " then go to " + queryData.goToTime);
88013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
88113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
88213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mQueryHandler.cancelOperation(0);
88313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (BASICLOG) queryData.queryStartMillis = System.nanoTime();
8849138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
8859138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        Uri queryUri = buildQueryUri(
8869138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                queryData.start, queryData.end, queryData.searchQuery);
8879138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mQueryHandler.startQuery(0, queryData, queryUri,
8889138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                PROJECTION, buildQuerySelection(), null,
8899138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                AGENDA_SORT_ORDER);
89013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
89113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
89213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private String formatDateString(int julianDay) {
8939a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        Time time = new Time(mTimeZone);
89413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        time.setJulianDay(julianDay);
89513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long millis = time.toMillis(false);
89613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder.setLength(0);
89713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return DateUtils.formatDateRange(mContext, mFormatter, millis, millis,
89813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE
8999a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                        | DateUtils.FORMAT_ABBREV_MONTH, mTimeZone).toString();
90013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
90113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
90213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private void updateHeaderFooter(final int start, final int end) {
90313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHeaderView.setText(mContext.getString(R.string.show_older_events,
90413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                formatDateString(start)));
90513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFooterView.setText(mContext.getString(R.string.show_newer_events,
90613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                formatDateString(end)));
90713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
90813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
90913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private class QueryHandler extends AsyncQueryHandler {
91013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
91113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public QueryHandler(ContentResolver cr) {
91213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            super(cr);
91313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
91413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
91513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        @Override
91613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
91713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            QuerySpec data = (QuerySpec)cookie;
91813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (BASICLOG) {
91913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                long queryEndMillis = System.nanoTime();
92013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Log.e(TAG, "Query time(ms): "
92113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        + (queryEndMillis - data.queryStartMillis) / 1000000
92213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        + " Count: " + cursor.getCount());
92313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
92413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
925c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (data.queryType == QUERY_TYPE_CLEAN) {
926c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                mCleanQueryInitiated = false;
927c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
928c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
92913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (mShuttingDown) {
93013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                cursor.close();
93113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return;
93213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
93313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
93413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            // Notify Listview of changes and update position
93513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int cursorSize = cursor.getCount();
9367278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik            if (cursorSize > 0 || mAdapterInfos.isEmpty() || data.queryType == QUERY_TYPE_CLEAN) {
93713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                final int listPositionOffset = processNewCursor(data, cursor);
938c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                int newPosition = -1;
93913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (data.goToTime == null) { // Typical Scrolling type query
94013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    notifyDataSetChanged();
94113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (listPositionOffset != 0) {
94213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        mAgendaListView.shiftSelection(listPositionOffset);
94313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
94413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else { // refresh() called. Go to the designated position
94513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    final Time goToTime = data.goToTime;
94613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    notifyDataSetChanged();
947c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    newPosition = findEventPositionNearestTime(goToTime, data.id);
94813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (newPosition >= 0) {
949c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        if (mListViewScrollState == OnScrollListener.SCROLL_STATE_FLING) {
950c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mAgendaListView.smoothScrollBy(0, 0);
951c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        }
952b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                        mAgendaListView.setSelectionFromTop(newPosition + OFF_BY_ONE_BUG,
953b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                                mStickyHeaderSize);
954e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        Time actualTime = new Time(mTimeZone);
9554fe5d45eb8cbaac85764492e0a0b6c025771880aIsaac Katzenelson                        actualTime.set(goToTime);
956e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        CalendarController.getInstance(mContext).sendEvent(this,
957e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                                EventType.UPDATE_TITLE, actualTime, actualTime, -1,
958e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                                ViewType.CURRENT);
95913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
9607278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik                    if (DEBUGLOG) {
96113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        Log.e(TAG, "Setting listview to " +
962c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                "findEventPositionNearestTime: " + (newPosition + OFF_BY_ONE_BUG));
963c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
964c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                }
965c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
966c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // Make sure we change the selected instance Id only on a clean query and we
967c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // do not have one set already
968c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                if (mSelectedInstanceId == -1 && newPosition != -1 &&
969c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        data.queryType == QUERY_TYPE_CLEAN) {
970c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (data.id != -1 || data.goToTime != null) {
971c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        mSelectedInstanceId = findInstanceIdFromPosition(newPosition);
9727278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik                    }
97313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
974ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
97592ea39440681f86205ad10771f1770c550552320Michael Chan                // size == 1 means a fresh query. Possibly after the data changed.
97692ea39440681f86205ad10771f1770c550552320Michael Chan                // Let's check whether mSelectedInstanceId is still valid.
97792ea39440681f86205ad10771f1770c550552320Michael Chan                if (mAdapterInfos.size() == 1 && mSelectedInstanceId != -1) {
97892ea39440681f86205ad10771f1770c550552320Michael Chan                    boolean found = false;
97992ea39440681f86205ad10771f1770c550552320Michael Chan                    cursor.moveToPosition(-1);
98092ea39440681f86205ad10771f1770c550552320Michael Chan                    while (cursor.moveToNext()) {
98192ea39440681f86205ad10771f1770c550552320Michael Chan                        if (mSelectedInstanceId == cursor
98292ea39440681f86205ad10771f1770c550552320Michael Chan                                .getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID)) {
98392ea39440681f86205ad10771f1770c550552320Michael Chan                            found = true;
98492ea39440681f86205ad10771f1770c550552320Michael Chan                            break;
98592ea39440681f86205ad10771f1770c550552320Michael Chan                        }
98692ea39440681f86205ad10771f1770c550552320Michael Chan                    };
98792ea39440681f86205ad10771f1770c550552320Michael Chan
98892ea39440681f86205ad10771f1770c550552320Michael Chan                    if (!found) {
98992ea39440681f86205ad10771f1770c550552320Michael Chan                        mSelectedInstanceId = -1;
99092ea39440681f86205ad10771f1770c550552320Michael Chan                    }
99192ea39440681f86205ad10771f1770c550552320Michael Chan                }
99292ea39440681f86205ad10771f1770c550552320Michael Chan
993c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // Show the requested event
994c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                if (mShowEventOnStart && data.queryType == QUERY_TYPE_CLEAN) {
995c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    Cursor tempCursor = null;
996c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    int tempCursorPosition = -1;
997c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
998c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    // If no valid event is selected , just pick the first one
999c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (mSelectedInstanceId == -1) {
1000c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        if (cursor.moveToFirst()) {
1001c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mSelectedInstanceId = cursor
1002c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                    .getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID);
1003c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            // Set up a dummy view holder so we have the right all day
1004c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            // info when the view is created.
1005c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            // TODO determine the full set of what might be useful to
1006c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            // know about the selected view and fill it in.
1007c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mSelectedVH = new AgendaAdapter.ViewHolder();
1008c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mSelectedVH.allDay =
1009c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0;
1010c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            tempCursor = cursor;
1011c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        }
1012c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    } else if (newPosition != -1) {
1013c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                         tempCursor = getCursorByPosition(newPosition);
1014c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                         tempCursorPosition = getCursorPositionByPosition(newPosition);
1015c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
1016c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (tempCursor != null) {
1017c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        EventInfo event = buildEventInfoFromCursor(tempCursor, tempCursorPosition,
1018c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                false);
101996a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                        CalendarController.getInstance(mContext).sendEventRelatedEvent(this,
102096a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                                EventType.VIEW_EVENT, event.id, event.begin, event.end, 0, 0, -1);
102196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                    }
1022ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan                }
102313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else {
102413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                cursor.close();
102513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
102613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
102713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            // Update header and footer
102813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (!mDoneSettingUpHeaderFooter) {
102913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                OnClickListener headerFooterOnClickListener = new OnClickListener() {
103013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    public void onClick(View v) {
103113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (v == mHeaderView) {
103213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            queueQuery(new QuerySpec(QUERY_TYPE_OLDER));
103313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        } else {
103413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            queueQuery(new QuerySpec(QUERY_TYPE_NEWER));
103513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
103613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }};
103713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mHeaderView.setOnClickListener(headerFooterOnClickListener);
103813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mFooterView.setOnClickListener(headerFooterOnClickListener);
103913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mAgendaListView.addFooterView(mFooterView);
104013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mDoneSettingUpHeaderFooter = true;
104113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
104213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            synchronized (mQueryQueue) {
104313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int totalAgendaRangeStart = -1;
104413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int totalAgendaRangeEnd = -1;
104513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
104613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (cursorSize != 0) {
104713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // Remove the query that just completed
104813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    QuerySpec x = mQueryQueue.poll();
104923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    if (BASICLOG && !x.equals(data)) {
105023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        Log.e(TAG, "onQueryComplete - cookie != head of queue");
105123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    }
105213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mEmptyCursorCount = 0;
105323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    if (data.queryType == QUERY_TYPE_NEWER) {
105423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        mNewerRequestsProcessed++;
105523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    } else if (data.queryType == QUERY_TYPE_OLDER) {
105623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        mOlderRequestsProcessed++;
105723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    }
105813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
105913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    totalAgendaRangeStart = mAdapterInfos.getFirst().start;
106013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    totalAgendaRangeEnd = mAdapterInfos.getLast().end;
106113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else { // CursorSize == 0
106213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    QuerySpec querySpec = mQueryQueue.peek();
106313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
106413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // Update Adapter Info with new start and end date range
106513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (!mAdapterInfos.isEmpty()) {
106613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        DayAdapterInfo first = mAdapterInfos.getFirst();
106713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        DayAdapterInfo last = mAdapterInfos.getLast();
106813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
106913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (first.start - 1 <= querySpec.end && querySpec.start < first.start) {
107013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            first.start = querySpec.start;
107113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
107213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
107313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (querySpec.start <= last.end + 1 && last.end < querySpec.end) {
107413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            last.end = querySpec.end;
107513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
107613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
107713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeStart = first.start;
107813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeEnd = last.end;
107913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } else {
108013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeStart = querySpec.start;
108113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeEnd = querySpec.end;
108213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
108313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
108413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // Update query specification with expanded search range
108513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // and maybe rerun query
108613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    switch (querySpec.queryType) {
108713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        case QUERY_TYPE_OLDER:
108813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeStart = querySpec.start;
108913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.start -= MAX_QUERY_DURATION;
109013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            break;
109113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        case QUERY_TYPE_NEWER:
109213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeEnd = querySpec.end;
109313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.end += MAX_QUERY_DURATION;
109413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            break;
109513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        case QUERY_TYPE_CLEAN:
109613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeStart = querySpec.start;
109713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeEnd = querySpec.end;
109813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.start -= MAX_QUERY_DURATION / 2;
109913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.end += MAX_QUERY_DURATION / 2;
110013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            break;
110113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
110213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
110313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (++mEmptyCursorCount > RETRIES_ON_NO_DATA) {
110413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Nothing in the cursor again. Dropping query
110513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        mQueryQueue.poll();
110613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
110713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
110813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
110913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                updateHeaderFooter(totalAgendaRangeStart, totalAgendaRangeEnd);
111013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
11112d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                // Go over the events and mark the first day after yesterday
11122d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                // that has events in it
11132d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                synchronized (mAdapterInfos) {
11142d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    DayAdapterInfo info = mAdapterInfos.getFirst();
11152d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    if (info != null) {
11162d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        Time time = new Time(mTimeZone);
11172d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        long now = System.currentTimeMillis();
11182d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        time.set(now);
11192d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        int JulianToday = Time.getJulianDay(now, time.gmtoff);
11202d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        Iterator<DayAdapterInfo> iter = mAdapterInfos.iterator();
11212d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        boolean foundDay = false;
11222d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        while (iter.hasNext() && !foundDay) {
11232d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                            info = iter.next();
11242d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                            for (int i = 0; i < info.size; i++) {
11252d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                if (info.dayAdapter.findJulianDayFromPosition(i) >= JulianToday) {
11262d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                    info.dayAdapter.setAsFirstDayAfterYesterday(i);
11272d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                    foundDay = true;
11282d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                    break;
11292d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                }
11302d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                            }
11312d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        }
11322d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    }
11332d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                }
11342d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
113513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Fire off the next query if any
113613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Iterator<QuerySpec> it = mQueryQueue.iterator();
113713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                while (it.hasNext()) {
113813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    QuerySpec queryData = it.next();
113913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (!isInRange(queryData.start, queryData.end)) {
114013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Query accepted
114113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (DEBUGLOG) Log.e(TAG, "Query accepted. QueueSize:" + mQueryQueue.size());
114213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        doQuery(queryData);
114313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        break;
114413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } else {
114513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Query rejected
114613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        it.remove();
114713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (DEBUGLOG) Log.e(TAG, "Query rejected. QueueSize:" + mQueryQueue.size());
114813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
114913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
115013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
115123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (BASICLOG) {
115213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                for (DayAdapterInfo info3 : mAdapterInfos) {
115313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    Log.e(TAG, "> " + info3.toString());
115413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
115513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
115613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
115713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
115813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        /*
115913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         * Update the adapter info array with a the new cursor. Close out old
116013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         * cursors as needed.
116113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         *
116213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         * @return number of rows removed from the beginning
116313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         */
116413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        private int processNewCursor(QuerySpec data, Cursor cursor) {
116513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            synchronized (mAdapterInfos) {
116613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Remove adapter info's from adapterInfos as needed
116713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                DayAdapterInfo info = pruneAdapterInfo(data.queryType);
116813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int listPositionOffset = 0;
116913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (info == null) {
117013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    info = new DayAdapterInfo(mContext);
117113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else {
117213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (DEBUGLOG)
117313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        Log.e(TAG, "processNewCursor listPositionOffsetA="
117413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                                + -info.size);
117513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    listPositionOffset = -info.size;
117613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
117713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
117813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Setup adapter info
117913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.start = data.start;
118013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.end = data.end;
118113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.cursor = cursor;
1182dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan                info.dayAdapter.changeCursor(info);
118313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.size = info.dayAdapter.getCount();
118413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
118513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Insert into adapterInfos
118613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (mAdapterInfos.isEmpty()
118713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        || data.end <= mAdapterInfos.getFirst().start) {
118813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mAdapterInfos.addFirst(info);
118913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    listPositionOffset += info.size;
119013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else if (BASICLOG && data.start < mAdapterInfos.getLast().end) {
119113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mAdapterInfos.addLast(info);
119213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    for (DayAdapterInfo info2 : mAdapterInfos) {
119313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        Log.e("========== BUG ==", info2.toString());
119413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
119513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else {
119613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mAdapterInfos.addLast(info);
119713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
119813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
119913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Update offsets in adapterInfos
120013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mRowCount = 0;
120113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                for (DayAdapterInfo info3 : mAdapterInfos) {
120213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    info3.offset = mRowCount;
120313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mRowCount += info3.size;
120413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
120513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mLastUsedInfo = null;
120613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
120713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return listPositionOffset;
120813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
120913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
121013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
121113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
121213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static String getViewTitle(View x) {
121313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        String title = "";
121413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (x != null) {
121513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Object yy = x.getTag();
121613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (yy instanceof AgendaAdapter.ViewHolder) {
121713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                TextView tv = ((AgendaAdapter.ViewHolder) yy).title;
121813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (tv != null) {
121913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    title = (String) tv.getText();
122013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
122113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else if (yy != null) {
122213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                TextView dateView = ((AgendaByDayAdapter.ViewHolder) yy).dateView;
122313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (dateView != null) {
122413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    title = (String) dateView.getText();
122513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
122613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
122713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
122813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return title;
122913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
123013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
12319a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    public void onResume() {
12329a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTZUpdater.run();
12339a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    }
12349a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
123513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public void setHideDeclinedEvents(boolean hideDeclined) {
123613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHideDeclined = hideDeclined;
123713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
1238a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
1239ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public void setSelectedView(View v) {
1240ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (v != null) {
1241ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            Object vh = v.getTag();
1242ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            if (vh instanceof AgendaAdapter.ViewHolder) {
12439fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik                mSelectedVH = (AgendaAdapter.ViewHolder) vh;
12449fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik                mSelectedInstanceId = mSelectedVH.instanceId;
1245ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            }
1246ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        }
1247ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    }
1248ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
12499fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik    public AgendaAdapter.ViewHolder getSelectedViewHolder() {
12509fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik        return mSelectedVH;
12519fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik    }
12529fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik
1253ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public long getSelectedInstanceId() {
1254ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        return mSelectedInstanceId;
1255ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    }
1256ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
1257ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public void setSelectedInstanceId(long selectedInstanceId) {
1258ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        mSelectedInstanceId = selectedInstanceId;
12599fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik        mSelectedVH = null;
1260a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    }
126137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
1262c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private long findInstanceIdFromPosition(int position) {
1263c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(position);
1264c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (info != null) {
1265c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return info.dayAdapter.getInstanceId(position - info.offset);
1266c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
1267c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        return -1;
1268c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
1269c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1270c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private Cursor getCursorByPosition(int position) {
1271c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(position);
1272c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (info != null) {
1273c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return info.cursor;
1274c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
1275c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        return null;
1276c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
1277c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1278c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private int getCursorPositionByPosition(int position) {
1279c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(position);
1280c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (info != null) {
1281c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return info.dayAdapter.getCursorPosition(position - info.offset);
1282c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
1283c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        return -1;
1284c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
128537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
128637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Implementation of HeaderIndexer interface for StickyHeeaderListView
128737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
128837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the location of the day header of a specific event specified in the position
128937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // in the adapter
1290c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    @Override
129137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderPositionFromItemPosition(int position) {
1292980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
1293980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        // For phone configuration, return -1 so there will be no sticky header
1294980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        if (!mIsTabletConfig) {
1295980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            return -1;
1296980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        }
1297980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
129837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(position);
129937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (info != null) {
130037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            int pos = info.dayAdapter.getHeaderPosition(position - info.offset);
130137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return (pos != -1)?(pos + info.offset):-1;
130237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
130337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
130437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
130537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
130637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the number of events for a specific day header
1307c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    @Override
130837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderItemsNumber(int headerPosition) {
1309980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        if (headerPosition < 0 || !mIsTabletConfig) {
131037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
131137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
131237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(headerPosition);
131337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (info != null) {
131437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return info.dayAdapter.getHeaderItemsCount(headerPosition - info.offset);
131537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
131637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
131737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
1318c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1319c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    @Override
1320c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public void OnHeaderHeightChanged(int height) {
1321c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        mStickyHeaderSize = height;
1322c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
1323c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1324c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public void setScrollState(int state) {
1325c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        mListViewScrollState = state;
1326c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
132713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan}
1328