AgendaWindowAdapter.java revision 5731a2a7dab25becafbb4e134b558ba4d0bad2ee
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
1913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.AsyncQueryHandler;
2013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.ContentResolver;
219138ce8a14924612c014da2b6e727b4117ba1a92Mason Tangimport android.content.ContentUris;
2213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.Context;
23a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawaimport android.content.res.Resources;
2413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.database.Cursor;
2513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.net.Uri;
26c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelsonimport android.os.Handler;
27a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract;
28a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Attendees;
29a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Calendars;
30a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.Instances;
3113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.DateUtils;
3213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.Time;
3313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.util.Log;
3413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.LayoutInflater;
3513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View;
3613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View.OnClickListener;
379a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport android.view.ViewGroup;
38c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelsonimport android.widget.AbsListView.OnScrollListener;
3913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.BaseAdapter;
4018af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelsonimport android.widget.GridLayout;
4113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.TextView;
4213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
4318af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelsonimport com.android.calendar.CalendarController;
4418af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelsonimport com.android.calendar.CalendarController.EventType;
4518af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelsonimport com.android.calendar.CalendarController.ViewType;
4618af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelsonimport com.android.calendar.R;
4718af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelsonimport com.android.calendar.StickyHeaderListView;
4818af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelsonimport com.android.calendar.Utils;
4918af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson
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
110a651f0460368b7f35610375c063f151b1e544ab2Alon Albert            Instances.DISPLAY_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
13718af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final Context mContext;
13818af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final Resources mResources;
13918af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final QueryHandler mQueryHandler;
14018af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final 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>();
15518af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final TextView mHeaderView;
15618af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final 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.
18518af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final Formatter mFormatter;
18618af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final StringBuilder mStringBuilder;
1879a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    private String mTimeZone;
1889a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
18996a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson    // defines if to pop-up the current event when the agenda is first shown
19018af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final boolean mShowEventOnStart;
19196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson
19218af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final 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;
21318af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson    private final float mItemRightMargin;
214a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
21513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Types of Query
21613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int QUERY_TYPE_OLDER = 0; // Query for older events
21713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int QUERY_TYPE_NEWER = 1; // Query for newer events
21813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static final int QUERY_TYPE_CLEAN = 2; // Delete everything and query around a date
21913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
22013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private static class QuerySpec {
22113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long queryStartMillis;
22213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Time goToTime;
22313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int start;
22413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int end;
2259138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        String searchQuery;
22613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int queryType;
227c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        long id;
22813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
22913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public QuerySpec(int queryType) {
23013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            this.queryType = queryType;
231c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            id = -1;
23213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
23323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan
23423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        @Override
23523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        public int hashCode() {
23623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            final int prime = 31;
23723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            int result = 1;
23823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + end;
23923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + (int) (queryStartMillis ^ (queryStartMillis >>> 32));
24023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + queryType;
24123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            result = prime * result + start;
2422f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            if (searchQuery != null) {
2432f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                result = prime * result + searchQuery.hashCode();
2442f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            }
24523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (goToTime != null) {
24623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                long goToTimeMillis = goToTime.toMillis(false);
24723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                result = prime * result + (int) (goToTimeMillis ^ (goToTimeMillis >>> 32));
24823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
249c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            result = prime * result + (int)id;
25023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            return result;
25123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        }
25223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan
25323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        @Override
25423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        public boolean equals(Object obj) {
25523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (this == obj) return true;
25623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (obj == null) return false;
25723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (getClass() != obj.getClass()) return false;
25823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            QuerySpec other = (QuerySpec) obj;
25923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (end != other.end || queryStartMillis != other.queryStartMillis
2609138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                    || queryType != other.queryType || start != other.start
261c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    || Utils.equals(searchQuery, other.searchQuery) || id != other.id) {
26223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                return false;
26323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
2649138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
26523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (goToTime != null) {
26623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                if (goToTime.toMillis(false) != other.goToTime.toMillis(false)) {
26723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    return false;
26823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                }
26923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            } else {
27023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                if (other.goToTime != null) {
27123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    return false;
27223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                }
27323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            }
27423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            return true;
27523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        }
27613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
27713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
27813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static class EventInfo {
27913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long begin;
28013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long end;
28113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long id;
282ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        int startDay;
2838b1119b1b58381c7fc550974f53cf93bd95dffa8Michael Chan        boolean allDay;
28413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
28513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
286dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan    static class DayAdapterInfo {
28713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Cursor cursor;
28813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        AgendaByDayAdapter dayAdapter;
28913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int start; // start day of the cursor's coverage
29013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int end; // end day of the cursor's coverage
29113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int offset; // offset in position in the list view
29213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int size; // dayAdapter.getCount()
29313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
29413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public DayAdapterInfo(Context context) {
29513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            dayAdapter = new AgendaByDayAdapter(context);
29613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
29713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
29813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        @Override
29913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public String toString() {
3009a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // Static class, so the time in this toString will not reflect the
3019a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            // home tz settings. This should only affect debugging.
30213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Time time = new Time();
30313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            StringBuilder sb = new StringBuilder();
30413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.setJulianDay(start);
30513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.normalize(false);
30613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append("Start:").append(time.toString());
30713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.setJulianDay(end);
30813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.normalize(false);
30913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append(" End:").append(time.toString());
31013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append(" Offset:").append(offset);
31113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            sb.append(" Size:").append(size);
31213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return sb.toString();
31313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
31413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
31513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
3169138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    public AgendaWindowAdapter(Context context,
31796a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson            AgendaListView agendaListView, boolean showEventOnStart) {
3189138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mContext = context;
319a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        mResources = context.getResources();
320163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan        mSelectedItemBackgroundColor = mResources
321163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan                .getColor(R.color.agenda_selected_background_color);
322163192b54fdf9fc15ca6e4bf04402c73c904d0d7Michael Chan        mSelectedItemTextColor = mResources.getColor(R.color.agenda_selected_text_color);
32318af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson        mItemRightMargin = mResources.getDimension(R.dimen.agenda_item_right_margin);
324980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        mIsTabletConfig = Utils.getConfigBool(mContext, R.bool.tablet_config);
325a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
3269a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTimeZone = Utils.getTimeZone(context, mTZUpdater);
32713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaListView = agendaListView;
3289138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mQueryHandler = new QueryHandler(context.getContentResolver());
32913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
33013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder = new StringBuilder(50);
33113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
33213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
33396a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson        mShowEventOnStart = showEventOnStart;
33496a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson
335c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // Implies there is no sticky header
336c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (!mShowEventOnStart) {
337c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mStickyHeaderSize = 0;
338c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
3399138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mSearchQuery = null;
3409138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
3419138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        LayoutInflater inflater = (LayoutInflater) context
34213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
34313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHeaderView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null);
34413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFooterView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null);
34513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHeaderView.setText(R.string.loading);
34613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mAgendaListView.addHeaderView(mHeaderView);
34713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
34813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
34913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in Adapter
35013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
35113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public int getViewTypeCount() {
35213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return AgendaByDayAdapter.TYPE_LAST;
35313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
35413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
35513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in BaseAdapter
35613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
35713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public boolean areAllItemsEnabled() {
35813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return false;
35913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
36013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
36113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in Adapter
36213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
36313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public int getItemViewType(int position) {
36413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
36513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
36613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.dayAdapter.getItemViewType(position - info.offset);
36713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
36813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return -1;
36913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
37013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
37113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
37213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Method in BaseAdapter
37313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    @Override
37413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public boolean isEnabled(int position) {
37513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
37613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
37713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.dayAdapter.isEnabled(position - info.offset);
37813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
37913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return false;
38013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
38113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
38213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
38313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
38413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public int getCount() {
38513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return mRowCount;
38613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
38713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
38813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
38913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public Object getItem(int position) {
39013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
39113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
39213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return info.dayAdapter.getItem(position - info.offset);
39313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
39413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return null;
39513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
39613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
39713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
398c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    // Method in BaseAdapter
399c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    @Override
400c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    public boolean hasStableIds() {
401c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan        return true;
402c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan    }
403c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan
40413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
405c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    @Override
40613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public long getItemId(int position) {
40713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
40813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
409c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            int curPos = info.dayAdapter.getCursorPosition(position - info.offset);
410c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (curPos == Integer.MIN_VALUE) {
411c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                return -1;
412c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
413c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Regular event
414c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (curPos >= 0) {
415c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                info.cursor.moveToPosition(curPos);
416c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                return info.cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID) << 20 +
417c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    info.cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN);
418c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
419c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Day Header
420c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return info.dayAdapter.findJulianDayFromPosition(position);
421c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
42213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
42313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return -1;
42413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
42513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
42613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
42713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    // Abstract Method in BaseAdapter
42813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public View getView(int position, View convertView, ViewGroup parent) {
42913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (position >= (mRowCount - PREFETCH_BOUNDARY)
43013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                && mNewerRequests <= mNewerRequestsProcessed) {
43113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (DEBUGLOG) Log.e(TAG, "queryForNewerEvents: ");
43213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mNewerRequests++;
43313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queueQuery(new QuerySpec(QUERY_TYPE_NEWER));
43413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
43513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
43613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (position < PREFETCH_BOUNDARY
43713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                && mOlderRequests <= mOlderRequestsProcessed) {
43813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (DEBUGLOG) Log.e(TAG, "queryForOlderEvents: ");
43913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mOlderRequests++;
44013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queueQuery(new QuerySpec(QUERY_TYPE_OLDER));
44113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
44213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
443a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        final View v;
44413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByPosition(position);
44513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
4462d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            int offset = position - info.offset;
4472d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            v = info.dayAdapter.getView(offset, convertView,
44813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    parent);
4492d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
4502d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // Turn on the past/present separator if the view is a day header
4512d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // and it is the first day with events after yesterday.
4522d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            if (info.dayAdapter.isDayHeaderView(offset)) {
4532d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                View simpleDivider = v.findViewById(R.id.top_divider_simple);
4542d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                View pastPresentDivider = v.findViewById(R.id.top_divider_past_present);
4552d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                if (info.dayAdapter.isFirstDayAfterYesterday(offset)) {
4562d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    if (simpleDivider != null && pastPresentDivider != null) {
4572d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        simpleDivider.setVisibility(View.GONE);
4582d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        pastPresentDivider.setVisibility(View.VISIBLE);
4592d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    }
4602d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                } else if (simpleDivider != null && pastPresentDivider != null) {
4612d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    simpleDivider.setVisibility(View.VISIBLE);
4622d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    pastPresentDivider.setVisibility(View.GONE);
4632d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                }
4642d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            }
46513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
4662d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson            // TODO
46713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Log.e(TAG, "BUG: getAdapterInfoByPosition returned null!!! " + position);
46813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            TextView tv = new TextView(mContext);
46913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            tv.setText("Bug! " + position);
47013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            v = tv;
47113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
47213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
47333de4c48430262a0509ffe50fc376b87520cb938RoboErik        // If this is not a tablet config don't do selection highlighting
47433de4c48430262a0509ffe50fc376b87520cb938RoboErik        if (!mIsTabletConfig) {
47533de4c48430262a0509ffe50fc376b87520cb938RoboErik            return v;
47633de4c48430262a0509ffe50fc376b87520cb938RoboErik        }
477ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        // Show selected marker if this is item is selected
478ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        boolean selected = false;
479ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        Object yy = v.getTag();
480ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (yy instanceof AgendaAdapter.ViewHolder) {
481ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            AgendaAdapter.ViewHolder vh = (AgendaAdapter.ViewHolder) yy;
482ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            selected = mSelectedInstanceId == vh.instanceId;
48396a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson            vh.selectedMarker.setVisibility((selected && mShowEventOnStart) ?
48496a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                    View.VISIBLE : View.GONE);
48518af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson            if (mShowEventOnStart) {
48618af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                GridLayout.LayoutParams lp =
48718af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                        (GridLayout.LayoutParams)vh.textContainer.getLayoutParams();
48818af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                if (selected) {
48918af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                    mSelectedVH = vh;
49018af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                    v.setBackgroundColor(mSelectedItemBackgroundColor);
49118af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                    vh.title.setTextColor(mSelectedItemTextColor);
49218af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                    vh.when.setTextColor(mSelectedItemTextColor);
49318af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                    vh.where.setTextColor(mSelectedItemTextColor);
49418af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                    lp.setMargins(0, 0, 0, 0);
49518af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                    vh.textContainer.setLayoutParams(lp);
49618af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                } else {
49718af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                    lp.setMargins(0, 0, (int)mItemRightMargin, 0);
49818af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                    vh.textContainer.setLayoutParams(lp);
49918af2447a421c514ce6da1723abea2869e349fb3Isaac Katzenelson                }
500ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            }
501a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        }
502a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
50313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (DEBUGLOG) {
50413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Log.e(TAG, "getView " + position + " = " + getViewTitle(v));
50513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
50613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return v;
50713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
50813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
5099fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik    private AgendaAdapter.ViewHolder mSelectedVH = null;
5109fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik
511c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private int findEventPositionNearestTime(Time time, long id) {
51213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        DayAdapterInfo info = getAdapterInfoByTime(time);
513499a660463ef870168cf0d63e668893a91d96b3aMichael Chan        int pos = -1;
51413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info != null) {
515499a660463ef870168cf0d63e668893a91d96b3aMichael Chan            pos = info.offset + info.dayAdapter.findEventPositionNearestTime(time, id);
51613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
517499a660463ef870168cf0d63e668893a91d96b3aMichael Chan        if (DEBUGLOG) Log.e(TAG, "findEventPositionNearestTime " + time + " id:" + id + " =" + pos);
518499a660463ef870168cf0d63e668893a91d96b3aMichael Chan        return pos;
51913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
52013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
5219a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    protected DayAdapterInfo getAdapterInfoByPosition(int position) {
52213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
52313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (mLastUsedInfo != null && mLastUsedInfo.offset <= position
52413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    && position < (mLastUsedInfo.offset + mLastUsedInfo.size)) {
52513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return mLastUsedInfo;
52613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
52713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            for (DayAdapterInfo info : mAdapterInfos) {
52813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (info.offset <= position
52913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        && position < (info.offset + info.size)) {
53013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mLastUsedInfo = info;
53113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    return info;
53213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
53313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
53413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
53513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return null;
53613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
53713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
53813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private DayAdapterInfo getAdapterInfoByTime(Time time) {
53913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (DEBUGLOG) Log.e(TAG, "getAdapterInfoByTime " + time.toString());
54013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
54113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Time tmpTime = new Time(time);
54213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long timeInMillis = tmpTime.normalize(true);
54313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int day = Time.getJulianDay(timeInMillis, tmpTime.gmtoff);
54413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
54513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            for (DayAdapterInfo info : mAdapterInfos) {
5468e597ca4f8eb3f9a3730d49aaeb431a0231af7d1Michael Chan                if (info.start <= day && day <= info.end) {
54713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    return info;
54813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
54913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
55013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
55113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return null;
55213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
55313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
554a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    public EventInfo getEventByPosition(final int positionInListView) {
55596d6163c524b338307b01d25916ccffd495e2f29Michael Chan        return getEventByPosition(positionInListView, true);
55696d6163c524b338307b01d25916ccffd495e2f29Michael Chan    }
55796d6163c524b338307b01d25916ccffd495e2f29Michael Chan
55896d6163c524b338307b01d25916ccffd495e2f29Michael Chan    /**
55996d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * Return the event info for a given position in the adapter
56096d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * @param positionInListView
56196d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * @param returnEventStartDay If true, return actual event startday. Otherwise
56296d6163c524b338307b01d25916ccffd495e2f29Michael Chan     *        return agenda date-header date as the startDay.
56396d6163c524b338307b01d25916ccffd495e2f29Michael Chan     *        The two will differ for multi-day events after the first day.
56496d6163c524b338307b01d25916ccffd495e2f29Michael Chan     * @return
56596d6163c524b338307b01d25916ccffd495e2f29Michael Chan     */
56696d6163c524b338307b01d25916ccffd495e2f29Michael Chan    public EventInfo getEventByPosition(final int positionInListView,
56796d6163c524b338307b01d25916ccffd495e2f29Michael Chan            boolean returnEventStartDay) {
568a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (DEBUGLOG) Log.e(TAG, "getEventByPosition " + positionInListView);
5699fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik        if (positionInListView < 0) {
5709fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik            return null;
5719fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik        }
57213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
573a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        final int positionInAdapter = positionInListView - OFF_BY_ONE_BUG;
574a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        DayAdapterInfo info = getAdapterInfoByPosition(positionInAdapter);
57513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (info == null) {
57613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return null;
57713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
57813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
579a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        int cursorPosition = info.dayAdapter.getCursorPosition(positionInAdapter - info.offset);
580a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (cursorPosition == Integer.MIN_VALUE) {
58113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return null;
58213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
58313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
58413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        boolean isDayHeader = false;
585a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (cursorPosition < 0) {
586a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa            cursorPosition = -cursorPosition;
58713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            isDayHeader = true;
58813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
58913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
590a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa        if (cursorPosition < info.cursor.getCount()) {
591c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            EventInfo ei = buildEventInfoFromCursor(info.cursor, cursorPosition, isDayHeader);
59296d6163c524b338307b01d25916ccffd495e2f29Michael Chan            if (!returnEventStartDay && !isDayHeader) {
593812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson                ei.startDay = info.dayAdapter.findJulianDayFromPosition(positionInAdapter -
594812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson                        info.offset);
59596d6163c524b338307b01d25916ccffd495e2f29Michael Chan            }
59696d6163c524b338307b01d25916ccffd495e2f29Michael Chan            return ei;
59713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
59813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return null;
59913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
60013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
601c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private EventInfo buildEventInfoFromCursor(final Cursor cursor, int cursorPosition,
602c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            boolean isDayHeader) {
603c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (cursorPosition == -1) {
604c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            cursor.moveToFirst();
605c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        } else {
606c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            cursor.moveToPosition(cursorPosition);
607c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
608ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        EventInfo event = new EventInfo();
609ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        event.begin = cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN);
610f836d4af478310abc9b63f1afa6ab964e2478fedRoboErik        event.end = cursor.getLong(AgendaWindowAdapter.INDEX_END);
611ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        event.startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY);
612ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
6138b1119b1b58381c7fc550974f53cf93bd95dffa8Michael Chan        event.allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0;
6148b1119b1b58381c7fc550974f53cf93bd95dffa8Michael Chan        if (event.allDay) { // UTC
615ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            Time time = new Time(mTimeZone);
616ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.setJulianDay(Time.getJulianDay(event.begin, 0));
617ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            event.begin = time.toMillis(false /* use isDst */);
618ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        } else if (isDayHeader) { // Trim to midnight.
619ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            Time time = new Time(mTimeZone);
620ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.set(event.begin);
621ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.hour = 0;
622ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.minute = 0;
623ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            time.second = 0;
624ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            event.begin = time.toMillis(false /* use isDst */);
625ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        }
626ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
627ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (!isDayHeader) {
6288b1119b1b58381c7fc550974f53cf93bd95dffa8Michael Chan            if (event.allDay) {
629ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                Time time = new Time(mTimeZone);
630ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                time.setJulianDay(Time.getJulianDay(event.end, 0));
631ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                event.end = time.toMillis(false /* use isDst */);
632ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            } else {
633ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson                event.end = cursor.getLong(AgendaWindowAdapter.INDEX_END);
634ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            }
635ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson
636ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            event.id = cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID);
637ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        }
638ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        return event;
639ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    }
640ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
641c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public void refresh(Time goToTime, long id, String searchQuery, boolean forced,
642c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            boolean refreshEventInfo) {
6434003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        if (searchQuery != null) {
6444003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang            mSearchQuery = searchQuery;
6454003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang        }
6464003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang
647c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan        if (DEBUGLOG) {
648c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            Log.e(TAG, this + ": refresh " + goToTime.toString() + " id " + id
649c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    + ((searchQuery != null) ? searchQuery : "")
650c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    + (forced ? " forced" : " not forced")
651c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    + (refreshEventInfo ? " refresh event info" : ""));
652c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan        }
653b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson
65423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan        int startDay = Time.getJulianDay(goToTime.toMillis(false), goToTime.gmtoff);
65513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
65613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (!forced && isInRange(startDay, startDay)) {
657ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            // No need to re-query
658ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            if (!mAgendaListView.isEventVisible(goToTime, id)) {
659c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                int gotoPosition = findEventPositionNearestTime(goToTime, id);
6608e597ca4f8eb3f9a3730d49aaeb431a0231af7d1Michael Chan                if (gotoPosition > 0) {
6615731a2a7dab25becafbb4e134b558ba4d0bad2eeIsaac Katzenelson                    mAgendaListView.setSelectionFromTop(gotoPosition +
6625731a2a7dab25becafbb4e134b558ba4d0bad2eeIsaac Katzenelson                            OFF_BY_ONE_BUG, mStickyHeaderSize);
663c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (mListViewScrollState == OnScrollListener.SCROLL_STATE_FLING) {
664c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        mAgendaListView.smoothScrollBy(0, 0);
665c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
666c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (refreshEventInfo) {
667c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        long newInstanceId = findInstanceIdFromPosition(gotoPosition);
668c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        if (newInstanceId != getSelectedInstanceId()) {
669c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            setSelectedInstanceId(newInstanceId);
670c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            new Handler().post(new Runnable() {
671c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                @Override
672c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                public void run() {
673c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                    notifyDataSetChanged();
674c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                }
675c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            });
676c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            Cursor tempCursor = getCursorByPosition(gotoPosition);
677c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            if (tempCursor != null) {
678c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                int tempCursorPosition = getCursorPositionByPosition(gotoPosition);
679c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                EventInfo event =
680c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                        buildEventInfoFromCursor(tempCursor, tempCursorPosition,
681c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                                false);
6826bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                                CalendarController.getInstance(mContext)
6836bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                                        .sendEventRelatedEventWithExtra(this, EventType.VIEW_EVENT,
6846bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                                                event.id, event.begin, event.end, 0,
6856bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                                                0, CalendarController.EventInfo.buildViewExtraLong(
6866bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                                                        Attendees.ATTENDEE_STATUS_NONE,
6876bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                                                        event.allDay), -1);
688c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            }
689c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        }
690c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
6918e597ca4f8eb3f9a3730d49aaeb431a0231af7d1Michael Chan                }
692c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
693e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                Time actualTime = new Time(mTimeZone);
694499a660463ef870168cf0d63e668893a91d96b3aMichael Chan                actualTime.set(goToTime);
695e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                CalendarController.getInstance(mContext).sendEvent(this, EventType.UPDATE_TITLE,
696e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        actualTime, actualTime, -1, ViewType.CURRENT);
697ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson            }
69813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return;
69913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
70013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
701c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        // If AllInOneActivity is sending a second GOTO event(in OnResume), ignore it.
702c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (!mCleanQueryInitiated || searchQuery != null) {
703c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Query for a total of MIN_QUERY_DURATION days
704c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            int endDay = startDay + MIN_QUERY_DURATION;
70513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
706c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mSelectedInstanceId = -1;
707c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mCleanQueryInitiated = true;
708ab557bf10630e7d23c20a000bb06e12580852c75Michael Chan            queueQuery(startDay, endDay, goToTime, searchQuery, QUERY_TYPE_CLEAN, id);
7094fe5d45eb8cbaac85764492e0a0b6c025771880aIsaac Katzenelson
710c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Pre-fetch more data to overcome a race condition in AgendaListView.shiftSelection
711c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // Queuing more data with the goToTime set to the selected time skips the call to
712c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            // shiftSelection on refresh.
713c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mOlderRequests++;
714c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            queueQuery(0, 0, goToTime, searchQuery, QUERY_TYPE_OLDER, id);
715c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            mNewerRequests++;
716c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            queueQuery(0, 0, goToTime, searchQuery, QUERY_TYPE_NEWER, id);
717c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
71813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
71913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
72013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public void close() {
72113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mShuttingDown = true;
72213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        pruneAdapterInfo(QUERY_TYPE_CLEAN);
72313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (mQueryHandler != null) {
72413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            mQueryHandler.cancelOperation(0);
72513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
72613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
72713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
72813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private DayAdapterInfo pruneAdapterInfo(int queryType) {
72913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
73013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            DayAdapterInfo recycleMe = null;
73113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (!mAdapterInfos.isEmpty()) {
73213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (mAdapterInfos.size() >= MAX_NUM_OF_ADAPTERS) {
73313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (queryType == QUERY_TYPE_NEWER) {
73413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe = mAdapterInfos.removeFirst();
73513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } else if (queryType == QUERY_TYPE_OLDER) {
73613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe = mAdapterInfos.removeLast();
73713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Keep the size only if the oldest items are removed.
73813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe.size = 0;
73913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
74013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (recycleMe != null) {
74113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (recycleMe.cursor != null) {
74213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            recycleMe.cursor.close();
74313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
74413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        return recycleMe;
74513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
74613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
74713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
74813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (mRowCount == 0 || queryType == QUERY_TYPE_CLEAN) {
74913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mRowCount = 0;
75013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    int deletedRows = 0;
75113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    DayAdapterInfo info;
75213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    do {
75313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        info = mAdapterInfos.poll();
75413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (info != null) {
755bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                            // TODO the following causes ANR's. Do this in a thread.
75613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            info.cursor.close();
75713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            deletedRows += info.size;
75813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            recycleMe = info;
75913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
76013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } while (info != null);
76113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
76213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (recycleMe != null) {
76313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe.cursor = null;
76413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        recycleMe.size = deletedRows;
76513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
76613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
76713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
76813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return recycleMe;
76913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
77013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
77113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
77213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private String buildQuerySelection() {
77313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        // Respect the preference to show/hide declined events
77413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
77513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (mHideDeclined) {
776950e8a615f3dcca0b61b2eb8f8de72ecf6825d4bAndy McFadden            return Calendars.VISIBLE + "=1 AND "
77713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    + Instances.SELF_ATTENDEE_STATUS + "!="
77813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    + Attendees.ATTENDEE_STATUS_DECLINED;
77913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else {
780950e8a615f3dcca0b61b2eb8f8de72ecf6825d4bAndy McFadden            return Calendars.VISIBLE + "=1";
78113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
78213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
78313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
7849138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private Uri buildQueryUri(int start, int end, String searchQuery) {
7859138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        Uri rootUri = searchQuery == null ?
7869138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                Instances.CONTENT_BY_DAY_URI :
7879138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                Instances.CONTENT_SEARCH_BY_DAY_URI;
7889138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        Uri.Builder builder = rootUri.buildUpon();
7899138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        ContentUris.appendId(builder, start);
7909138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        ContentUris.appendId(builder, end);
7919138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        if (searchQuery != null) {
7929138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang            builder.appendPath(searchQuery);
7939138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        }
7949138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        return builder.build();
79513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
79613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
79713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean isInRange(int start, int end) {
79813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mAdapterInfos) {
79913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (mAdapterInfos.isEmpty()) {
80013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return false;
80113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
80213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            return mAdapterInfos.getFirst().start <= start && end <= mAdapterInfos.getLast().end;
80313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
80413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
80513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
80613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private int calculateQueryDuration(int start, int end) {
80713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        int queryDuration = MAX_QUERY_DURATION;
80813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (mRowCount != 0) {
80913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queryDuration = IDEAL_NUM_OF_EVENTS * (end - start + 1) / mRowCount;
81013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
81113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
81213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (queryDuration > MAX_QUERY_DURATION) {
81313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queryDuration = MAX_QUERY_DURATION;
81413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        } else if (queryDuration < MIN_QUERY_DURATION) {
81513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queryDuration = MIN_QUERY_DURATION;
81613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
81713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
81813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return queryDuration;
81913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
82013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
8219138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang    private boolean queueQuery(int start, int end, Time goToTime,
822c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            String searchQuery, int queryType, long id) {
82313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        QuerySpec queryData = new QuerySpec(queryType);
82413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        queryData.goToTime = goToTime;
82513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        queryData.start = start;
82613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        queryData.end = end;
8279138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        queryData.searchQuery = searchQuery;
828c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        queryData.id = id;
82913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return queueQuery(queryData);
83013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
83113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
83213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private boolean queueQuery(QuerySpec queryData) {
8339138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        queryData.searchQuery = mSearchQuery;
83413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        Boolean queuedQuery;
83513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        synchronized (mQueryQueue) {
83613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            queuedQuery = false;
83713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Boolean doQueryNow = mQueryQueue.isEmpty();
83823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            mQueryQueue.add(queryData);
83923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            queuedQuery = true;
84023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (doQueryNow) {
84123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                doQuery(queryData);
84213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
84313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
84413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return queuedQuery;
84513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
84613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
84713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private void doQuery(QuerySpec queryData) {
84813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (!mAdapterInfos.isEmpty()) {
84913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int start = mAdapterInfos.getFirst().start;
85013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int end = mAdapterInfos.getLast().end;
85113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int queryDuration = calculateQueryDuration(start, end);
85213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            switch(queryData.queryType) {
85313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                case QUERY_TYPE_OLDER:
85413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.end = start - 1;
85513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.start = queryData.end - queryDuration;
85613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    break;
85713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                case QUERY_TYPE_NEWER:
85813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.start = end + 1;
85913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    queryData.end = queryData.start + queryDuration;
86013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    break;
86113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
8622f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan
8632f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            // By "compacting" cursors, this fixes the disco/ping-pong problem
8642f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            // b/5311977
8652f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            if (mRowCount < 20 && queryData.queryType != QUERY_TYPE_CLEAN) {
8662f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                if (DEBUGLOG) {
8672f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                    Log.e(TAG, "Compacting cursor: mRowCount=" + mRowCount
8682f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                            + " totalStart:" + start
8692f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                            + " totalEnd:" + end
8702f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                            + " query.start:" + queryData.start
8712f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                            + " query.end:" + queryData.end);
8722f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                }
8732f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan
8742f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                queryData.queryType = QUERY_TYPE_CLEAN;
8752f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan
8762f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                if (queryData.start > start) {
8772f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                    queryData.start = start;
8782f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                }
8792f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                if (queryData.end < end) {
8802f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                    queryData.end = end;
8812f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan                }
8822f6a549faa941dd5996a50e885307ab8d6f88f2dMichael Chan            }
88313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
88413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
88513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (BASICLOG) {
8869a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            Time time = new Time(mTimeZone);
88713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time.setJulianDay(queryData.start);
8889a88873f9ec97b47aaaaae47208d22b3998b8e99Erik            Time time2 = new Time(mTimeZone);
88913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            time2.setJulianDay(queryData.end);
89013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Log.v(TAG, "startQuery: " + time.toString() + " to "
89113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    + time2.toString() + " then go to " + queryData.goToTime);
89213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
89313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
89413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mQueryHandler.cancelOperation(0);
89513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (BASICLOG) queryData.queryStartMillis = System.nanoTime();
8969138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang
8979138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        Uri queryUri = buildQueryUri(
8989138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                queryData.start, queryData.end, queryData.searchQuery);
8999138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang        mQueryHandler.startQuery(0, queryData, queryUri,
9009138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                PROJECTION, buildQuerySelection(), null,
9019138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang                AGENDA_SORT_ORDER);
90213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
90313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
90413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private String formatDateString(int julianDay) {
9059a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        Time time = new Time(mTimeZone);
90613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        time.setJulianDay(julianDay);
90713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        long millis = time.toMillis(false);
90813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mStringBuilder.setLength(0);
90913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return DateUtils.formatDateRange(mContext, mFormatter, millis, millis,
91013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE
9119a88873f9ec97b47aaaaae47208d22b3998b8e99Erik                        | DateUtils.FORMAT_ABBREV_MONTH, mTimeZone).toString();
91213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
91313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
91413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private void updateHeaderFooter(final int start, final int end) {
91513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHeaderView.setText(mContext.getString(R.string.show_older_events,
91613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                formatDateString(start)));
91713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mFooterView.setText(mContext.getString(R.string.show_newer_events,
91813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                formatDateString(end)));
91913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
92013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
92113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    private class QueryHandler extends AsyncQueryHandler {
92213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
92313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        public QueryHandler(ContentResolver cr) {
92413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            super(cr);
92513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
92613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
92713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        @Override
92813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
92913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            QuerySpec data = (QuerySpec)cookie;
93013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (BASICLOG) {
93113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                long queryEndMillis = System.nanoTime();
93213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Log.e(TAG, "Query time(ms): "
93313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        + (queryEndMillis - data.queryStartMillis) / 1000000
93413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        + " Count: " + cursor.getCount());
93513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
93613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
937c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            if (data.queryType == QUERY_TYPE_CLEAN) {
938c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                mCleanQueryInitiated = false;
939c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            }
940c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
94113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (mShuttingDown) {
94213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                cursor.close();
94313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return;
94413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
94513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
94613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            // Notify Listview of changes and update position
94713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            int cursorSize = cursor.getCount();
9487278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik            if (cursorSize > 0 || mAdapterInfos.isEmpty() || data.queryType == QUERY_TYPE_CLEAN) {
94913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                final int listPositionOffset = processNewCursor(data, cursor);
950c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                int newPosition = -1;
95113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (data.goToTime == null) { // Typical Scrolling type query
95213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    notifyDataSetChanged();
95313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (listPositionOffset != 0) {
95413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        mAgendaListView.shiftSelection(listPositionOffset);
95513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
95613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else { // refresh() called. Go to the designated position
95713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    final Time goToTime = data.goToTime;
95813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    notifyDataSetChanged();
959c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    newPosition = findEventPositionNearestTime(goToTime, data.id);
96013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (newPosition >= 0) {
961c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        if (mListViewScrollState == OnScrollListener.SCROLL_STATE_FLING) {
962c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mAgendaListView.smoothScrollBy(0, 0);
963c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        }
964b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                        mAgendaListView.setSelectionFromTop(newPosition + OFF_BY_ONE_BUG,
965b996adff74022fc78ff02c4f7e6149ea6342a7c6Isaac Katzenelson                                mStickyHeaderSize);
966e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        Time actualTime = new Time(mTimeZone);
9674fe5d45eb8cbaac85764492e0a0b6c025771880aIsaac Katzenelson                        actualTime.set(goToTime);
968e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                        CalendarController.getInstance(mContext).sendEvent(this,
969e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                                EventType.UPDATE_TITLE, actualTime, actualTime, -1,
970e3f129ad0a39b47ef0f08f18734aed9b99126279RoboErik                                ViewType.CURRENT);
97113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
9727278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik                    if (DEBUGLOG) {
97313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        Log.e(TAG, "Setting listview to " +
974c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                "findEventPositionNearestTime: " + (newPosition + OFF_BY_ONE_BUG));
975c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
976c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                }
977c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
978c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // Make sure we change the selected instance Id only on a clean query and we
979c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // do not have one set already
980c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                if (mSelectedInstanceId == -1 && newPosition != -1 &&
981c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        data.queryType == QUERY_TYPE_CLEAN) {
982c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (data.id != -1 || data.goToTime != null) {
983c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        mSelectedInstanceId = findInstanceIdFromPosition(newPosition);
9847278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik                    }
98513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
986ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
98792ea39440681f86205ad10771f1770c550552320Michael Chan                // size == 1 means a fresh query. Possibly after the data changed.
98892ea39440681f86205ad10771f1770c550552320Michael Chan                // Let's check whether mSelectedInstanceId is still valid.
98992ea39440681f86205ad10771f1770c550552320Michael Chan                if (mAdapterInfos.size() == 1 && mSelectedInstanceId != -1) {
99092ea39440681f86205ad10771f1770c550552320Michael Chan                    boolean found = false;
99192ea39440681f86205ad10771f1770c550552320Michael Chan                    cursor.moveToPosition(-1);
99292ea39440681f86205ad10771f1770c550552320Michael Chan                    while (cursor.moveToNext()) {
99392ea39440681f86205ad10771f1770c550552320Michael Chan                        if (mSelectedInstanceId == cursor
99492ea39440681f86205ad10771f1770c550552320Michael Chan                                .getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID)) {
99592ea39440681f86205ad10771f1770c550552320Michael Chan                            found = true;
99692ea39440681f86205ad10771f1770c550552320Michael Chan                            break;
99792ea39440681f86205ad10771f1770c550552320Michael Chan                        }
99892ea39440681f86205ad10771f1770c550552320Michael Chan                    };
99992ea39440681f86205ad10771f1770c550552320Michael Chan
100092ea39440681f86205ad10771f1770c550552320Michael Chan                    if (!found) {
100192ea39440681f86205ad10771f1770c550552320Michael Chan                        mSelectedInstanceId = -1;
100292ea39440681f86205ad10771f1770c550552320Michael Chan                    }
100392ea39440681f86205ad10771f1770c550552320Michael Chan                }
100492ea39440681f86205ad10771f1770c550552320Michael Chan
1005c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                // Show the requested event
1006c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                if (mShowEventOnStart && data.queryType == QUERY_TYPE_CLEAN) {
1007c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    Cursor tempCursor = null;
1008c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    int tempCursorPosition = -1;
1009c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1010c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    // If no valid event is selected , just pick the first one
1011c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (mSelectedInstanceId == -1) {
1012c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        if (cursor.moveToFirst()) {
1013c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mSelectedInstanceId = cursor
1014c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                    .getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID);
1015c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            // Set up a dummy view holder so we have the right all day
1016c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            // info when the view is created.
1017c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            // TODO determine the full set of what might be useful to
1018c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            // know about the selected view and fill it in.
1019c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mSelectedVH = new AgendaAdapter.ViewHolder();
1020c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            mSelectedVH.allDay =
1021c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0;
1022c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                            tempCursor = cursor;
1023c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        }
1024c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    } else if (newPosition != -1) {
1025c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                         tempCursor = getCursorByPosition(newPosition);
1026c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                         tempCursorPosition = getCursorPositionByPosition(newPosition);
1027c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    }
1028c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                    if (tempCursor != null) {
1029c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                        EventInfo event = buildEventInfoFromCursor(tempCursor, tempCursorPosition,
1030c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson                                false);
10316bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                        CalendarController.getInstance(mContext).sendEventRelatedEventWithExtra(
10326bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                                this, EventType.VIEW_EVENT, event.id, event.begin,
10336bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                                event.end, 0, 0, CalendarController.EventInfo.buildViewExtraLong(
10346bcafcf4f28c2d1053547694bd60b3dd9c7fbaa1Isaac Katzenelson                                        Attendees.ATTENDEE_STATUS_NONE, event.allDay), -1);
103596a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson                    }
1036ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan                }
103713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else {
103813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                cursor.close();
103913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
104013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
104113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            // Update header and footer
104213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (!mDoneSettingUpHeaderFooter) {
104313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                OnClickListener headerFooterOnClickListener = new OnClickListener() {
104413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    public void onClick(View v) {
104513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (v == mHeaderView) {
104613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            queueQuery(new QuerySpec(QUERY_TYPE_OLDER));
104713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        } else {
104813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            queueQuery(new QuerySpec(QUERY_TYPE_NEWER));
104913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
105013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }};
105113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mHeaderView.setOnClickListener(headerFooterOnClickListener);
105213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mFooterView.setOnClickListener(headerFooterOnClickListener);
105313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mAgendaListView.addFooterView(mFooterView);
105413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mDoneSettingUpHeaderFooter = true;
105513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
105613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            synchronized (mQueryQueue) {
105713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int totalAgendaRangeStart = -1;
105813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int totalAgendaRangeEnd = -1;
105913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
106013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (cursorSize != 0) {
106113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // Remove the query that just completed
106213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    QuerySpec x = mQueryQueue.poll();
106323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    if (BASICLOG && !x.equals(data)) {
106423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        Log.e(TAG, "onQueryComplete - cookie != head of queue");
106523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    }
106613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mEmptyCursorCount = 0;
106723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    if (data.queryType == QUERY_TYPE_NEWER) {
106823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        mNewerRequestsProcessed++;
106923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    } else if (data.queryType == QUERY_TYPE_OLDER) {
107023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                        mOlderRequestsProcessed++;
107123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan                    }
107213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
107313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    totalAgendaRangeStart = mAdapterInfos.getFirst().start;
107413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    totalAgendaRangeEnd = mAdapterInfos.getLast().end;
107513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else { // CursorSize == 0
107613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    QuerySpec querySpec = mQueryQueue.peek();
107713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
107813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // Update Adapter Info with new start and end date range
107913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (!mAdapterInfos.isEmpty()) {
108013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        DayAdapterInfo first = mAdapterInfos.getFirst();
108113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        DayAdapterInfo last = mAdapterInfos.getLast();
108213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
108313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (first.start - 1 <= querySpec.end && querySpec.start < first.start) {
108413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            first.start = querySpec.start;
108513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
108613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
108713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (querySpec.start <= last.end + 1 && last.end < querySpec.end) {
108813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            last.end = querySpec.end;
108913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        }
109013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
109113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeStart = first.start;
109213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeEnd = last.end;
109313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } else {
109413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeStart = querySpec.start;
109513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        totalAgendaRangeEnd = querySpec.end;
109613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
109713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
109813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // Update query specification with expanded search range
109913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    // and maybe rerun query
110013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    switch (querySpec.queryType) {
110113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        case QUERY_TYPE_OLDER:
110213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeStart = querySpec.start;
110313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.start -= MAX_QUERY_DURATION;
110413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            break;
110513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        case QUERY_TYPE_NEWER:
110613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeEnd = querySpec.end;
110713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.end += MAX_QUERY_DURATION;
110813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            break;
110913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        case QUERY_TYPE_CLEAN:
111013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeStart = querySpec.start;
111113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            totalAgendaRangeEnd = querySpec.end;
111213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.start -= MAX_QUERY_DURATION / 2;
111313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            querySpec.end += MAX_QUERY_DURATION / 2;
111413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                            break;
111513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
111613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
111713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (++mEmptyCursorCount > RETRIES_ON_NO_DATA) {
111813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Nothing in the cursor again. Dropping query
111913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        mQueryQueue.poll();
112013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
112113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
112213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
112313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                updateHeaderFooter(totalAgendaRangeStart, totalAgendaRangeEnd);
112413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
11252d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                // Go over the events and mark the first day after yesterday
11262d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                // that has events in it
11272d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                synchronized (mAdapterInfos) {
11282d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    DayAdapterInfo info = mAdapterInfos.getFirst();
11292d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    if (info != null) {
11302d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        Time time = new Time(mTimeZone);
11312d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        long now = System.currentTimeMillis();
11322d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        time.set(now);
11332d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        int JulianToday = Time.getJulianDay(now, time.gmtoff);
11342d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        Iterator<DayAdapterInfo> iter = mAdapterInfos.iterator();
11352d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        boolean foundDay = false;
11362d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        while (iter.hasNext() && !foundDay) {
11372d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                            info = iter.next();
11382d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                            for (int i = 0; i < info.size; i++) {
11392d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                if (info.dayAdapter.findJulianDayFromPosition(i) >= JulianToday) {
11402d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                    info.dayAdapter.setAsFirstDayAfterYesterday(i);
11412d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                    foundDay = true;
11422d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                    break;
11432d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                                }
11442d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                            }
11452d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                        }
11462d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                    }
11472d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson                }
11482d49da2fe5626ee6e3610dc8df23e16e768bc61fIsaac Katzenelson
114913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Fire off the next query if any
115013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                Iterator<QuerySpec> it = mQueryQueue.iterator();
115113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                while (it.hasNext()) {
115213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    QuerySpec queryData = it.next();
1153ab557bf10630e7d23c20a000bb06e12580852c75Michael Chan                    if (queryData.queryType == QUERY_TYPE_CLEAN
1154ab557bf10630e7d23c20a000bb06e12580852c75Michael Chan                            || !isInRange(queryData.start, queryData.end)) {
115513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Query accepted
115613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (DEBUGLOG) Log.e(TAG, "Query accepted. QueueSize:" + mQueryQueue.size());
115713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        doQuery(queryData);
115813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        break;
115913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    } else {
116013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        // Query rejected
116113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        it.remove();
116213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        if (DEBUGLOG) Log.e(TAG, "Query rejected. QueueSize:" + mQueryQueue.size());
116313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
116413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
116513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
116623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan            if (BASICLOG) {
116713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                for (DayAdapterInfo info3 : mAdapterInfos) {
116813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    Log.e(TAG, "> " + info3.toString());
116913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
117013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
117113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
117213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
117313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        /*
117413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         * Update the adapter info array with a the new cursor. Close out old
117513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         * cursors as needed.
117613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         *
117713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         * @return number of rows removed from the beginning
117813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan         */
117913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        private int processNewCursor(QuerySpec data, Cursor cursor) {
118013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            synchronized (mAdapterInfos) {
118113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Remove adapter info's from adapterInfos as needed
118213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                DayAdapterInfo info = pruneAdapterInfo(data.queryType);
118313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                int listPositionOffset = 0;
118413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (info == null) {
118513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    info = new DayAdapterInfo(mContext);
118613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else {
118713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    if (DEBUGLOG)
118813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        Log.e(TAG, "processNewCursor listPositionOffsetA="
118913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                                + -info.size);
119013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    listPositionOffset = -info.size;
119113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
119213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
119313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Setup adapter info
119413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.start = data.start;
119513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.end = data.end;
119613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.cursor = cursor;
1197dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan                info.dayAdapter.changeCursor(info);
119813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                info.size = info.dayAdapter.getCount();
119913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
120013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Insert into adapterInfos
120113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (mAdapterInfos.isEmpty()
120213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        || data.end <= mAdapterInfos.getFirst().start) {
120313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mAdapterInfos.addFirst(info);
120413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    listPositionOffset += info.size;
120513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else if (BASICLOG && data.start < mAdapterInfos.getLast().end) {
120613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mAdapterInfos.addLast(info);
120713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    for (DayAdapterInfo info2 : mAdapterInfos) {
120813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                        Log.e("========== BUG ==", info2.toString());
120913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    }
121013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                } else {
121113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mAdapterInfos.addLast(info);
121213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
121313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
121413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                // Update offsets in adapterInfos
121513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mRowCount = 0;
121613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                for (DayAdapterInfo info3 : mAdapterInfos) {
121713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    info3.offset = mRowCount;
121813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    mRowCount += info3.size;
121913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
122013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                mLastUsedInfo = null;
122113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
122213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                return listPositionOffset;
122313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
122413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
122513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
122613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
122713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    static String getViewTitle(View x) {
122813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        String title = "";
122913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        if (x != null) {
123013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            Object yy = x.getTag();
123113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            if (yy instanceof AgendaAdapter.ViewHolder) {
123213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                TextView tv = ((AgendaAdapter.ViewHolder) yy).title;
123313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (tv != null) {
123413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    title = (String) tv.getText();
123513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
123613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            } else if (yy != null) {
123713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                TextView dateView = ((AgendaByDayAdapter.ViewHolder) yy).dateView;
123813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                if (dateView != null) {
123913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                    title = (String) dateView.getText();
124013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan                }
124113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan            }
124213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        }
124313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        return title;
124413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
124513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan
12469a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    public void onResume() {
12479a88873f9ec97b47aaaaae47208d22b3998b8e99Erik        mTZUpdater.run();
12489a88873f9ec97b47aaaaae47208d22b3998b8e99Erik    }
12499a88873f9ec97b47aaaaae47208d22b3998b8e99Erik
125013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    public void setHideDeclinedEvents(boolean hideDeclined) {
125113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan        mHideDeclined = hideDeclined;
125213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan    }
1253a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa
1254ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public void setSelectedView(View v) {
1255ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        if (v != null) {
1256ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            Object vh = v.getTag();
1257ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            if (vh instanceof AgendaAdapter.ViewHolder) {
12589fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik                mSelectedVH = (AgendaAdapter.ViewHolder) vh;
125914764f1bd8e6c9e932a22b96583b9cf87d2617e0Isaac Katzenelson                if (mSelectedInstanceId != mSelectedVH.instanceId) {
126014764f1bd8e6c9e932a22b96583b9cf87d2617e0Isaac Katzenelson                    mSelectedInstanceId = mSelectedVH.instanceId;
126114764f1bd8e6c9e932a22b96583b9cf87d2617e0Isaac Katzenelson                    notifyDataSetChanged();
126214764f1bd8e6c9e932a22b96583b9cf87d2617e0Isaac Katzenelson                }
1263ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan            }
1264ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        }
1265ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    }
1266ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
12679fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik    public AgendaAdapter.ViewHolder getSelectedViewHolder() {
12689fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik        return mSelectedVH;
12699fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik    }
12709fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik
1271ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public long getSelectedInstanceId() {
1272ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        return mSelectedInstanceId;
1273ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    }
1274ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan
1275ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan    public void setSelectedInstanceId(long selectedInstanceId) {
1276ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan        mSelectedInstanceId = selectedInstanceId;
12779fb45ac4a8796afb05915fb152e74d02506f59c6RoboErik        mSelectedVH = null;
1278a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa    }
127937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
1280c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private long findInstanceIdFromPosition(int position) {
1281c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(position);
1282c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (info != null) {
1283c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return info.dayAdapter.getInstanceId(position - info.offset);
1284c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
1285c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        return -1;
1286c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
1287c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1288c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private Cursor getCursorByPosition(int position) {
1289c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(position);
1290c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (info != null) {
1291c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return info.cursor;
1292c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
1293c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        return null;
1294c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
1295c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1296c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    private int getCursorPositionByPosition(int position) {
1297c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(position);
1298c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        if (info != null) {
1299c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson            return info.dayAdapter.getCursorPosition(position - info.offset);
1300c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        }
1301c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        return -1;
1302c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
130337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
130437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Implementation of HeaderIndexer interface for StickyHeeaderListView
130537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
130637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the location of the day header of a specific event specified in the position
130737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // in the adapter
1308c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    @Override
130937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderPositionFromItemPosition(int position) {
1310980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
1311980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        // For phone configuration, return -1 so there will be no sticky header
1312980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        if (!mIsTabletConfig) {
1313980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson            return -1;
1314980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        }
1315980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson
131637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(position);
131737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (info != null) {
131837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            int pos = info.dayAdapter.getHeaderPosition(position - info.offset);
131937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return (pos != -1)?(pos + info.offset):-1;
132037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
132137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
132237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
132337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson
132437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    // Returns the number of events for a specific day header
1325c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    @Override
132637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    public int getHeaderItemsNumber(int headerPosition) {
1327980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson        if (headerPosition < 0 || !mIsTabletConfig) {
132837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return -1;
132937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
133037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        DayAdapterInfo info = getAdapterInfoByPosition(headerPosition);
133137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        if (info != null) {
133237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson            return info.dayAdapter.getHeaderItemsCount(headerPosition - info.offset);
133337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        }
133437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson        return -1;
133537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson    }
1336c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1337c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    @Override
1338c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public void OnHeaderHeightChanged(int height) {
1339c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        mStickyHeaderSize = height;
1340c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
1341c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson
1342812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson    public int getStickyHeaderHeight() {
1343812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson        return mStickyHeaderSize;
1344812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson    }
1345812da1baf2eaf2951dbd849bed1b365bd2581609Isaac Katzenelson
1346c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    public void setScrollState(int state) {
1347c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson        mListViewScrollState = state;
1348c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson    }
134913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan}
1350