AgendaWindowAdapter.java revision ccf565b6a00e1df8c0de824ac91e9f6746e246b5
113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan/* 213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * Copyright (C) 2009 The Android Open Source Project 313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * 413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * you may not use this file except in compliance with the License. 613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * You may obtain a copy of the License at 713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * 813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * http://www.apache.org/licenses/LICENSE-2.0 913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * 1013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * Unless required by applicable law or agreed to in writing, software 1113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * distributed under the License is distributed on an "AS IS" BASIS, 1213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * See the License for the specific language governing permissions and 1413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * limitations under the License. 1513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */ 1613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1700b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tangpackage com.android.calendar.agenda; 1800b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tang 19ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chanimport com.android.calendar.CalendarController; 2000b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tangimport com.android.calendar.R; 2100b8c1a39d75c1b4626dc987bd1a51cfaf7c9be1Mason Tangimport com.android.calendar.Utils; 22ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chanimport com.android.calendar.CalendarController.EventType; 2313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 2413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.AsyncQueryHandler; 2513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.ContentResolver; 269138ce8a14924612c014da2b6e727b4117ba1a92Mason Tangimport android.content.ContentUris; 2713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.Context; 28a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawaimport android.content.res.Resources; 2913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.database.Cursor; 3013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.net.Uri; 319138ce8a14924612c014da2b6e727b4117ba1a92Mason Tangimport android.provider.Calendar; 3213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.provider.Calendar.Attendees; 3313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.provider.Calendar.Calendars; 3413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.provider.Calendar.Instances; 3513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.DateUtils; 3613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.Time; 3713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.util.Log; 3813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.LayoutInflater; 3913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View; 4013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View.OnClickListener; 419a88873f9ec97b47aaaaae47208d22b3998b8e99Erikimport android.view.ViewGroup; 4213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.BaseAdapter; 4313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.TextView; 4413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 4513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Formatter; 4613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Iterator; 4713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.LinkedList; 4813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Locale; 4913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.concurrent.ConcurrentLinkedQueue; 5013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 5113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan/* 5213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanBugs Bugs Bugs: 5313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- At rotation and launch time, the initial position is not set properly. This code is calling 5413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan listview.setSelection() in 2 rapid secessions but it dropped or didn't process the first one. 5513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Scroll using trackball isn't repositioning properly after a new adapter is added. 5623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan- Track ball clicks at the header/footer doesn't work. 5713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Potential ping pong effect if the prefetch window is big and data is limited 5813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Add index in calendar provider 5913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 6013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanToDo ToDo ToDo: 6113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanGet design of header and footer from designer 6213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 6313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanMake scrolling smoother. 6413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanTest for correctness 6513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanLoading speed 6613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanCheck for leaks and excessive allocations 6713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */ 6813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 6913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanpublic class AgendaWindowAdapter extends BaseAdapter { 7013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 7123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan static final boolean BASICLOG = false; 7223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan static final boolean DEBUGLOG = false; 73a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa private static final String TAG = "AgendaWindowAdapter"; 7413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 759138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang private static final String AGENDA_SORT_ORDER = 76a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa Calendar.Instances.START_DAY + " ASC, " + 77a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa Calendar.Instances.BEGIN + " ASC, " + 78a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa Calendar.Events.TITLE + " ASC"; 799138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang 80ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan public static final int INDEX_INSTANCE_ID = 0; 8113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_TITLE = 1; 8213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_EVENT_LOCATION = 2; 8313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_ALL_DAY = 3; 8413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_HAS_ALARM = 4; 8513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_COLOR = 5; 8613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_RRULE = 6; 8713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_BEGIN = 7; 8813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_END = 8; 8913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_EVENT_ID = 9; 9013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_START_DAY = 10; 9113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_END_DAY = 11; 9213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_SELF_ATTENDEE_STATUS = 12; 9313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 9413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final String[] PROJECTION = new String[] { 9513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances._ID, // 0 9613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.TITLE, // 1 9713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.EVENT_LOCATION, // 2 9813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.ALL_DAY, // 3 9913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.HAS_ALARM, // 4 10013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.COLOR, // 5 10113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.RRULE, // 6 10213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.BEGIN, // 7 10313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.END, // 8 10413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.EVENT_ID, // 9 10513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.START_DAY, // 10 Julian start day 10613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.END_DAY, // 11 Julian end day 10713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.SELF_ATTENDEE_STATUS, // 12 10813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan }; 10913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 11013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Listview may have a bug where the index/position is not consistent when there's a header. 111a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa // position == positionInListView - OFF_BY_ONE_BUG 11213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // TODO Need to look into this. 11313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int OFF_BY_ONE_BUG = 1; 11413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int MAX_NUM_OF_ADAPTERS = 5; 11513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int IDEAL_NUM_OF_EVENTS = 50; 11613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int MIN_QUERY_DURATION = 7; // days 11713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int MAX_QUERY_DURATION = 60; // days 11813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int PREFETCH_BOUNDARY = 1; 11913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1209138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** Times to auto-expand/retry query after getting no data */ 1219138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang private static final int RETRIES_ON_NO_DATA = 1; 12213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 12313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private Context mContext; 124a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa private Resources mResources; 12513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private QueryHandler mQueryHandler; 12613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private AgendaListView mAgendaListView; 12713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1289138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** The sum of the rows in all the adapters */ 1299138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang private int mRowCount; 13013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1319138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** The number of times we have queried and gotten no results back */ 13213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mEmptyCursorCount; 13313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1349138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** Cached value of the last used adapter */ 1359138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang private DayAdapterInfo mLastUsedInfo; 13613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 137a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa private final LinkedList<DayAdapterInfo> mAdapterInfos = 138a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa new LinkedList<DayAdapterInfo>(); 139a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa private final ConcurrentLinkedQueue<QuerySpec> mQueryQueue = 140a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa new ConcurrentLinkedQueue<QuerySpec>(); 14113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private TextView mHeaderView; 14213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private TextView mFooterView; 14313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean mDoneSettingUpHeaderFooter = false; 14413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1459138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** 14613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * When the user scrolled to the top, a query will be made for older events 14713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * and this will be incremented. Don't make more requests if 14813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * mOlderRequests > mOlderRequestsProcessed. 14913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */ 15013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mOlderRequests; 15113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1529138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** Number of "older" query that has been processed. */ 15313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mOlderRequestsProcessed; 15413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1559138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** 15613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * When the user scrolled to the bottom, a query will be made for newer 15713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * events and this will be incremented. Don't make more requests if 15813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * mNewerRequests > mNewerRequestsProcessed. 15913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */ 16013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mNewerRequests; 16113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1629138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** Number of "newer" query that has been processed. */ 16313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mNewerRequestsProcessed; 16413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 16523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan // Note: Formatter is not thread safe. Fine for now as it is only used by the main thread. 16623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan private Formatter mFormatter; 16713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private StringBuilder mStringBuilder; 1689a88873f9ec97b47aaaaae47208d22b3998b8e99Erik private String mTimeZone; 1699a88873f9ec97b47aaaaae47208d22b3998b8e99Erik 17096a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson 17196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson // defines if to pop-up the current event when the agenda is first shown 17296a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson private boolean mShowEventOnStart; 17396a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson 1749a88873f9ec97b47aaaaae47208d22b3998b8e99Erik private Runnable mTZUpdater = new Runnable() { 1759a88873f9ec97b47aaaaae47208d22b3998b8e99Erik @Override 1769a88873f9ec97b47aaaaae47208d22b3998b8e99Erik public void run() { 1779a88873f9ec97b47aaaaae47208d22b3998b8e99Erik mTimeZone = Utils.getTimeZone(mContext, this); 1789a88873f9ec97b47aaaaae47208d22b3998b8e99Erik notifyDataSetChanged(); 1799a88873f9ec97b47aaaaae47208d22b3998b8e99Erik } 1809a88873f9ec97b47aaaaae47208d22b3998b8e99Erik }; 18113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 18213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean mShuttingDown; 18313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean mHideDeclined; 18413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1859138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang /** The current search query, or null if none */ 1869138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang private String mSearchQuery; 1879138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang 188ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan private long mSelectedInstanceId = -1; 189a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa 190a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa private final int mSelectedAgendaItemColor; 191a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa 19213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Types of Query 19313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int QUERY_TYPE_OLDER = 0; // Query for older events 19413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int QUERY_TYPE_NEWER = 1; // Query for newer events 19513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int QUERY_TYPE_CLEAN = 2; // Delete everything and query around a date 19613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 19713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static class QuerySpec { 19813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long queryStartMillis; 19913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time goToTime; 20013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int start; 20113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int end; 2029138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang String searchQuery; 20313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int queryType; 20413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 20513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public QuerySpec(int queryType) { 20613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan this.queryType = queryType; 20713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 20823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan 20923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan @Override 21023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan public int hashCode() { 21123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan final int prime = 31; 21223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan int result = 1; 21323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + end; 21423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + (int) (queryStartMillis ^ (queryStartMillis >>> 32)); 21523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + queryType; 21623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + start; 2179138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang result = prime * result + searchQuery.hashCode(); 21823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (goToTime != null) { 21923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan long goToTimeMillis = goToTime.toMillis(false); 22023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + (int) (goToTimeMillis ^ (goToTimeMillis >>> 32)); 22123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 22223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return result; 22323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 22423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan 22523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan @Override 22623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan public boolean equals(Object obj) { 22723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (this == obj) return true; 22823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (obj == null) return false; 22923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (getClass() != obj.getClass()) return false; 23023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan QuerySpec other = (QuerySpec) obj; 23123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (end != other.end || queryStartMillis != other.queryStartMillis 2329138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang || queryType != other.queryType || start != other.start 2339138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang || Utils.equals(searchQuery, other.searchQuery)) { 23423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return false; 23523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 2369138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang 23723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (goToTime != null) { 23823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (goToTime.toMillis(false) != other.goToTime.toMillis(false)) { 23923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return false; 24023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 24123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } else { 24223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (other.goToTime != null) { 24323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return false; 24423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 24523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 24623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return true; 24723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 24813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 24913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 25013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan static class EventInfo { 25113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long begin; 25213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long end; 25313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long id; 254ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan int startDay; 25513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 25613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 257dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan static class DayAdapterInfo { 25813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Cursor cursor; 25913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan AgendaByDayAdapter dayAdapter; 26013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int start; // start day of the cursor's coverage 26113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int end; // end day of the cursor's coverage 26213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int offset; // offset in position in the list view 26313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int size; // dayAdapter.getCount() 26413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 26513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public DayAdapterInfo(Context context) { 26613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan dayAdapter = new AgendaByDayAdapter(context); 26713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 26813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 26913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 27013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public String toString() { 2719a88873f9ec97b47aaaaae47208d22b3998b8e99Erik // Static class, so the time in this toString will not reflect the 2729a88873f9ec97b47aaaaae47208d22b3998b8e99Erik // home tz settings. This should only affect debugging. 27313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time time = new Time(); 27413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan StringBuilder sb = new StringBuilder(); 27513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.setJulianDay(start); 27613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.normalize(false); 27713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan sb.append("Start:").append(time.toString()); 27813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.setJulianDay(end); 27913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.normalize(false); 28013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan sb.append(" End:").append(time.toString()); 28113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan sb.append(" Offset:").append(offset); 28213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan sb.append(" Size:").append(size); 28313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return sb.toString(); 28413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 28513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 28613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 2879138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang public AgendaWindowAdapter(Context context, 28896a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson AgendaListView agendaListView, boolean showEventOnStart) { 2899138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang mContext = context; 290a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa mResources = context.getResources(); 291ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan mSelectedAgendaItemColor = mResources.getColor(R.color.activated); 292a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa 2939a88873f9ec97b47aaaaae47208d22b3998b8e99Erik mTimeZone = Utils.getTimeZone(context, mTZUpdater); 29413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView = agendaListView; 2959138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang mQueryHandler = new QueryHandler(context.getContentResolver()); 29613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 29713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mStringBuilder = new StringBuilder(50); 29813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mFormatter = new Formatter(mStringBuilder, Locale.getDefault()); 29913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 30096a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson mShowEventOnStart = showEventOnStart; 30196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson 3029138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang mSearchQuery = null; 3039138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang 3049138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang LayoutInflater inflater = (LayoutInflater) context 30513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 30613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHeaderView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null); 30713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mFooterView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null); 30813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHeaderView.setText(R.string.loading); 30913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView.addHeaderView(mHeaderView); 31013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 31113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 31213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Method in Adapter 31313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 31413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public int getViewTypeCount() { 31513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return AgendaByDayAdapter.TYPE_LAST; 31613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 31713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 31813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Method in BaseAdapter 31913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 32013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public boolean areAllItemsEnabled() { 32113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return false; 32213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 32313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 32413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Method in Adapter 32513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 32613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public int getItemViewType(int position) { 32713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 32813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 32913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info.dayAdapter.getItemViewType(position - info.offset); 33013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 33113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return -1; 33213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 33313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 33413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 33513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Method in BaseAdapter 33613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 33713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public boolean isEnabled(int position) { 33813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 33913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 34013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info.dayAdapter.isEnabled(position - info.offset); 34113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 34213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return false; 34313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 34413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 34513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 34613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Abstract Method in BaseAdapter 34713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public int getCount() { 34813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return mRowCount; 34913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 35013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 35113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Abstract Method in BaseAdapter 35213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public Object getItem(int position) { 35313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 35413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 35513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info.dayAdapter.getItem(position - info.offset); 35613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 35713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 35813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 35913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 36013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 361c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan // Method in BaseAdapter 362c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan @Override 363c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan public boolean hasStableIds() { 364c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan return true; 365c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan } 366c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan 36713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Abstract Method in BaseAdapter 36813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public long getItemId(int position) { 36913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 37013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 371c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan return ((position - info.offset) << 20) + info.start ; 37213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 37313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return -1; 37413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 37513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 37613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 37713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Abstract Method in BaseAdapter 37813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public View getView(int position, View convertView, ViewGroup parent) { 37913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (position >= (mRowCount - PREFETCH_BOUNDARY) 38013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan && mNewerRequests <= mNewerRequestsProcessed) { 38113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "queryForNewerEvents: "); 38213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mNewerRequests++; 38313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queueQuery(new QuerySpec(QUERY_TYPE_NEWER)); 38413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 38513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 38613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (position < PREFETCH_BOUNDARY 38713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan && mOlderRequests <= mOlderRequestsProcessed) { 38813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "queryForOlderEvents: "); 38913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mOlderRequests++; 39013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queueQuery(new QuerySpec(QUERY_TYPE_OLDER)); 39113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 39213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 393a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa final View v; 39413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 39513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 39613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan v = info.dayAdapter.getView(position - info.offset, convertView, 39713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan parent); 39813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 39913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan //TODO 40013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "BUG: getAdapterInfoByPosition returned null!!! " + position); 40113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan TextView tv = new TextView(mContext); 40213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan tv.setText("Bug! " + position); 40313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan v = tv; 40413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 40513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 406ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan // Show selected marker if this is item is selected 407ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan boolean selected = false; 408ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan Object yy = v.getTag(); 409ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan if (yy instanceof AgendaAdapter.ViewHolder) { 410ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan AgendaAdapter.ViewHolder vh = (AgendaAdapter.ViewHolder) yy; 411ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan selected = mSelectedInstanceId == vh.instanceId; 41296a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson vh.selectedMarker.setVisibility((selected && mShowEventOnStart) ? 41396a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson View.VISIBLE : View.GONE); 414ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan if (selected) { 415ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan v.setBackgroundColor(mSelectedAgendaItemColor); 416ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } 417a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa } 418a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa 41913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) { 42013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "getView " + position + " = " + getViewTitle(v)); 42113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 42213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return v; 42313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 42413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 42513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int findDayPositionNearestTime(Time time) { 42613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "findDayPositionNearestTime " + time); 42713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 42813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByTime(time); 42913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 43013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info.offset + info.dayAdapter.findDayPositionNearestTime(time); 43113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 43213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return -1; 43313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 43413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 43513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 43613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private DayAdapterInfo getAdapterInfoByPosition(int position) { 43713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 43813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mLastUsedInfo != null && mLastUsedInfo.offset <= position 43913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan && position < (mLastUsedInfo.offset + mLastUsedInfo.size)) { 44013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return mLastUsedInfo; 44113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 44213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info : mAdapterInfos) { 44313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info.offset <= position 44413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan && position < (info.offset + info.size)) { 44513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mLastUsedInfo = info; 44613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info; 44713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 44813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 44913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 45013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 45113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 45213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 45313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private DayAdapterInfo getAdapterInfoByTime(Time time) { 45413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "getAdapterInfoByTime " + time.toString()); 45513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 45613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time tmpTime = new Time(time); 45713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long timeInMillis = tmpTime.normalize(true); 45813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int day = Time.getJulianDay(timeInMillis, tmpTime.gmtoff); 45913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 46013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info : mAdapterInfos) { 46113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info.start <= day && day < info.end) { 46213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info; 46313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 46413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 46513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 46613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 46713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 46813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 469a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa public EventInfo getEventByPosition(final int positionInListView) { 470a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa if (DEBUGLOG) Log.e(TAG, "getEventByPosition " + positionInListView); 47113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 472a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa final int positionInAdapter = positionInListView - OFF_BY_ONE_BUG; 473a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa DayAdapterInfo info = getAdapterInfoByPosition(positionInAdapter); 47413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info == null) { 47513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 47613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 47713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 478a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa int cursorPosition = info.dayAdapter.getCursorPosition(positionInAdapter - info.offset); 479a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa if (cursorPosition == Integer.MIN_VALUE) { 48013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 48113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 48213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 48313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan boolean isDayHeader = false; 484a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa if (cursorPosition < 0) { 485a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa cursorPosition = -cursorPosition; 48613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan isDayHeader = true; 48713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 48813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 489a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa if (cursorPosition < info.cursor.getCount()) { 490a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa info.cursor.moveToPosition(cursorPosition); 491ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan return buildEventInfoFromCursor(info.cursor, isDayHeader); 49213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 49313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 49413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 49513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 496ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan private EventInfo buildEventInfoFromCursor(final Cursor cursor, boolean isDayHeader) { 497ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan EventInfo event = new EventInfo(); 498ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan event.begin = cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN); 499ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan event.startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY); 500ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan 501ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan boolean allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0; 502ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan if (allDay) { // UTC 503ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan Time time = new Time(mTimeZone); 504ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan time.setJulianDay(Time.getJulianDay(event.begin, 0)); 505ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan event.begin = time.toMillis(false /* use isDst */); 506ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } else if (isDayHeader) { // Trim to midnight. 507ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan Time time = new Time(mTimeZone); 508ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan time.set(event.begin); 509ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan time.hour = 0; 510ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan time.minute = 0; 511ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan time.second = 0; 512ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan event.begin = time.toMillis(false /* use isDst */); 513ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } 514ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan 515ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan if (!isDayHeader) { 516ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson if (allDay) { 517ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson Time time = new Time(mTimeZone); 518ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson time.setJulianDay(Time.getJulianDay(event.end, 0)); 519ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson event.end = time.toMillis(false /* use isDst */); 520ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson } else { 521ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson event.end = cursor.getLong(AgendaWindowAdapter.INDEX_END); 522ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson } 523ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson 524ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan event.id = cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID); 525ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } 526ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan return event; 527ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } 528ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan 529ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson public void refresh(Time goToTime, long id, String searchQuery, boolean forced) { 5304003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang if (searchQuery != null) { 5314003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang mSearchQuery = searchQuery; 5324003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang } 5334003d1cd4d1ebe3863c9d3e92cd4232595183064Mason Tang 534c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan if (DEBUGLOG) { 535c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan Log.e(TAG, "refresh " + goToTime.toString() + (forced ? " forced" : " not forced")); 536c79507e566895b023ef0eaf6e32cdc402372b7caMichael Chan } 5377278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik 53823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan int startDay = Time.getJulianDay(goToTime.toMillis(false), goToTime.gmtoff); 53913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 54013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!forced && isInRange(startDay, startDay)) { 541ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson // No need to re-query 542ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson if (!mAgendaListView.isEventVisible(goToTime, id)) { 543ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson mAgendaListView.setSelection(findDayPositionNearestTime(goToTime) + OFF_BY_ONE_BUG); 544ccf565b6a00e1df8c0de824ac91e9f6746e246b5Isaac Katzenelson } 54513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return; 54613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 54713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 548088a7d0d8c4d0652a42b8bbeb940421cea5ad8dcMichael Chan // Query for a total of MIN_QUERY_DURATION days 54913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int endDay = startDay + MIN_QUERY_DURATION; 55013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 5519138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang queueQuery(startDay, endDay, goToTime, searchQuery, QUERY_TYPE_CLEAN); 55213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 55313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 55413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public void close() { 55513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mShuttingDown = true; 55613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan pruneAdapterInfo(QUERY_TYPE_CLEAN); 55713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mQueryHandler != null) { 55813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mQueryHandler.cancelOperation(0); 55913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 56013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 56113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 56213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private DayAdapterInfo pruneAdapterInfo(int queryType) { 56313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 56413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo recycleMe = null; 56513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!mAdapterInfos.isEmpty()) { 56613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mAdapterInfos.size() >= MAX_NUM_OF_ADAPTERS) { 56713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (queryType == QUERY_TYPE_NEWER) { 56813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe = mAdapterInfos.removeFirst(); 56913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else if (queryType == QUERY_TYPE_OLDER) { 57013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe = mAdapterInfos.removeLast(); 57113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Keep the size only if the oldest items are removed. 57213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe.size = 0; 57313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 57413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (recycleMe != null) { 57513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (recycleMe.cursor != null) { 57613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe.cursor.close(); 57713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 57813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return recycleMe; 57913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 58013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 58113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 58213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mRowCount == 0 || queryType == QUERY_TYPE_CLEAN) { 58313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mRowCount = 0; 58413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int deletedRows = 0; 58513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info; 58613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan do { 58713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info = mAdapterInfos.poll(); 58813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 589bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan // TODO the following causes ANR's. Do this in a thread. 59013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.cursor.close(); 59113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan deletedRows += info.size; 59213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe = info; 59313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 59413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } while (info != null); 59513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 59613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (recycleMe != null) { 59713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe.cursor = null; 59813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe.size = deletedRows; 59913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 60013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 60113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 60213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return recycleMe; 60313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 60413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 60513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 60613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private String buildQuerySelection() { 60713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Respect the preference to show/hide declined events 60813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 60913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mHideDeclined) { 610950e8a615f3dcca0b61b2eb8f8de72ecf6825d4bAndy McFadden return Calendars.VISIBLE + "=1 AND " 61113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + Instances.SELF_ATTENDEE_STATUS + "!=" 61213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + Attendees.ATTENDEE_STATUS_DECLINED; 61313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 614950e8a615f3dcca0b61b2eb8f8de72ecf6825d4bAndy McFadden return Calendars.VISIBLE + "=1"; 61513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 61613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 61713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 6189138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang private Uri buildQueryUri(int start, int end, String searchQuery) { 6199138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang Uri rootUri = searchQuery == null ? 6209138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang Instances.CONTENT_BY_DAY_URI : 6219138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang Instances.CONTENT_SEARCH_BY_DAY_URI; 6229138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang Uri.Builder builder = rootUri.buildUpon(); 6239138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang ContentUris.appendId(builder, start); 6249138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang ContentUris.appendId(builder, end); 6259138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang if (searchQuery != null) { 6269138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang builder.appendPath(searchQuery); 6279138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang } 6289138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang return builder.build(); 62913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 63013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 63113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean isInRange(int start, int end) { 63213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 63313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mAdapterInfos.isEmpty()) { 63413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return false; 63513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 63613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return mAdapterInfos.getFirst().start <= start && end <= mAdapterInfos.getLast().end; 63713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 63813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 63913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 64013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int calculateQueryDuration(int start, int end) { 64113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int queryDuration = MAX_QUERY_DURATION; 64213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mRowCount != 0) { 64313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryDuration = IDEAL_NUM_OF_EVENTS * (end - start + 1) / mRowCount; 64413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 64513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 64613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (queryDuration > MAX_QUERY_DURATION) { 64713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryDuration = MAX_QUERY_DURATION; 64813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else if (queryDuration < MIN_QUERY_DURATION) { 64913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryDuration = MIN_QUERY_DURATION; 65013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 65113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 65213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return queryDuration; 65313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 65413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 6559138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang private boolean queueQuery(int start, int end, Time goToTime, 6569138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang String searchQuery, int queryType) { 65713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec queryData = new QuerySpec(queryType); 65813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.goToTime = goToTime; 65913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.start = start; 66013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.end = end; 6619138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang queryData.searchQuery = searchQuery; 66213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return queueQuery(queryData); 66313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 66413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 66513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean queueQuery(QuerySpec queryData) { 6669138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang queryData.searchQuery = mSearchQuery; 66713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Boolean queuedQuery; 66813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mQueryQueue) { 66913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queuedQuery = false; 67013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Boolean doQueryNow = mQueryQueue.isEmpty(); 67123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan mQueryQueue.add(queryData); 67223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan queuedQuery = true; 67323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (doQueryNow) { 67423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan doQuery(queryData); 67513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 67613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 67713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return queuedQuery; 67813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 67913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 68013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private void doQuery(QuerySpec queryData) { 68113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!mAdapterInfos.isEmpty()) { 68213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int start = mAdapterInfos.getFirst().start; 68313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int end = mAdapterInfos.getLast().end; 68413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int queryDuration = calculateQueryDuration(start, end); 68513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan switch(queryData.queryType) { 68613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_OLDER: 68713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.end = start - 1; 68813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.start = queryData.end - queryDuration; 68913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 69013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_NEWER: 69113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.start = end + 1; 69213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.end = queryData.start + queryDuration; 69313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 69413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 69513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 69613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 69713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (BASICLOG) { 6989a88873f9ec97b47aaaaae47208d22b3998b8e99Erik Time time = new Time(mTimeZone); 69913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.setJulianDay(queryData.start); 7009a88873f9ec97b47aaaaae47208d22b3998b8e99Erik Time time2 = new Time(mTimeZone); 70113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time2.setJulianDay(queryData.end); 70213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.v(TAG, "startQuery: " + time.toString() + " to " 70313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + time2.toString() + " then go to " + queryData.goToTime); 70413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 70513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 70613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mQueryHandler.cancelOperation(0); 70713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (BASICLOG) queryData.queryStartMillis = System.nanoTime(); 7089138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang 7099138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang Uri queryUri = buildQueryUri( 7109138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang queryData.start, queryData.end, queryData.searchQuery); 7119138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang mQueryHandler.startQuery(0, queryData, queryUri, 7129138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang PROJECTION, buildQuerySelection(), null, 7139138ce8a14924612c014da2b6e727b4117ba1a92Mason Tang AGENDA_SORT_ORDER); 71413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 71513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 71613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private String formatDateString(int julianDay) { 7179a88873f9ec97b47aaaaae47208d22b3998b8e99Erik Time time = new Time(mTimeZone); 71813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.setJulianDay(julianDay); 71913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long millis = time.toMillis(false); 72013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mStringBuilder.setLength(0); 72113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return DateUtils.formatDateRange(mContext, mFormatter, millis, millis, 72213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE 7239a88873f9ec97b47aaaaae47208d22b3998b8e99Erik | DateUtils.FORMAT_ABBREV_MONTH, mTimeZone).toString(); 72413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 72513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 72613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private void updateHeaderFooter(final int start, final int end) { 72713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHeaderView.setText(mContext.getString(R.string.show_older_events, 72813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan formatDateString(start))); 72913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mFooterView.setText(mContext.getString(R.string.show_newer_events, 73013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan formatDateString(end))); 73113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 73213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 73313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private class QueryHandler extends AsyncQueryHandler { 73413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 73513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public QueryHandler(ContentResolver cr) { 73613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan super(cr); 73713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 73813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 73913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 74013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 74113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec data = (QuerySpec)cookie; 74213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (BASICLOG) { 74313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long queryEndMillis = System.nanoTime(); 74413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "Query time(ms): " 74513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + (queryEndMillis - data.queryStartMillis) / 1000000 74613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + " Count: " + cursor.getCount()); 74713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 74813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 74913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mShuttingDown) { 75013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan cursor.close(); 75113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return; 75213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 75313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 75413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Notify Listview of changes and update position 75513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int cursorSize = cursor.getCount(); 7567278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik if (cursorSize > 0 || mAdapterInfos.isEmpty() || data.queryType == QUERY_TYPE_CLEAN) { 75713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan final int listPositionOffset = processNewCursor(data, cursor); 75813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (data.goToTime == null) { // Typical Scrolling type query 75913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan notifyDataSetChanged(); 76013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (listPositionOffset != 0) { 76113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView.shiftSelection(listPositionOffset); 76213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 76313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { // refresh() called. Go to the designated position 76413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan final Time goToTime = data.goToTime; 76513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan notifyDataSetChanged(); 76613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int newPosition = findDayPositionNearestTime(goToTime); 76713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (newPosition >= 0) { 76813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView.setSelection(newPosition + OFF_BY_ONE_BUG); 76913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 7707278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik if (DEBUGLOG) { 77113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "Setting listview to " + 7727278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik "findDayPositionNearestTime: " + (newPosition + OFF_BY_ONE_BUG)); 7737278388c9b666f3d79b2ce4c7eeefe6ceb97aeb4Erik } 77413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 775ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan 77692ea39440681f86205ad10771f1770c550552320Michael Chan // size == 1 means a fresh query. Possibly after the data changed. 77792ea39440681f86205ad10771f1770c550552320Michael Chan // Let's check whether mSelectedInstanceId is still valid. 77892ea39440681f86205ad10771f1770c550552320Michael Chan if (mAdapterInfos.size() == 1 && mSelectedInstanceId != -1) { 77992ea39440681f86205ad10771f1770c550552320Michael Chan boolean found = false; 78092ea39440681f86205ad10771f1770c550552320Michael Chan cursor.moveToPosition(-1); 78192ea39440681f86205ad10771f1770c550552320Michael Chan while (cursor.moveToNext()) { 78292ea39440681f86205ad10771f1770c550552320Michael Chan if (mSelectedInstanceId == cursor 78392ea39440681f86205ad10771f1770c550552320Michael Chan .getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID)) { 78492ea39440681f86205ad10771f1770c550552320Michael Chan found = true; 78592ea39440681f86205ad10771f1770c550552320Michael Chan break; 78692ea39440681f86205ad10771f1770c550552320Michael Chan } 78792ea39440681f86205ad10771f1770c550552320Michael Chan }; 78892ea39440681f86205ad10771f1770c550552320Michael Chan 78992ea39440681f86205ad10771f1770c550552320Michael Chan if (!found) { 79092ea39440681f86205ad10771f1770c550552320Michael Chan mSelectedInstanceId = -1; 79192ea39440681f86205ad10771f1770c550552320Michael Chan } 79292ea39440681f86205ad10771f1770c550552320Michael Chan } 79392ea39440681f86205ad10771f1770c550552320Michael Chan 794ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan if (mSelectedInstanceId == -1 && cursor.moveToFirst()) { 795ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan mSelectedInstanceId = cursor.getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID); 796ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan 797ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan EventInfo event = buildEventInfoFromCursor(cursor, false); 79896a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson if (mShowEventOnStart) { 79996a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson CalendarController.getInstance(mContext).sendEventRelatedEvent(this, 80096a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson EventType.VIEW_EVENT, event.id, event.begin, event.end, 0, 0, -1); 80196a0b5436f79157e8175b3b761fd5ccfe26a7f62Isaac Katzenelson } 802ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } 80313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 80413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan cursor.close(); 80513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 80613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 80713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Update header and footer 80813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!mDoneSettingUpHeaderFooter) { 80913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan OnClickListener headerFooterOnClickListener = new OnClickListener() { 81013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public void onClick(View v) { 81113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (v == mHeaderView) { 81213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queueQuery(new QuerySpec(QUERY_TYPE_OLDER)); 81313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 81413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queueQuery(new QuerySpec(QUERY_TYPE_NEWER)); 81513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 81613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan }}; 81713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHeaderView.setOnClickListener(headerFooterOnClickListener); 81813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mFooterView.setOnClickListener(headerFooterOnClickListener); 81913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView.addFooterView(mFooterView); 82013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mDoneSettingUpHeaderFooter = true; 82113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 82213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mQueryQueue) { 82313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int totalAgendaRangeStart = -1; 82413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int totalAgendaRangeEnd = -1; 82513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 82613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (cursorSize != 0) { 82713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Remove the query that just completed 82813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec x = mQueryQueue.poll(); 82923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (BASICLOG && !x.equals(data)) { 83023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan Log.e(TAG, "onQueryComplete - cookie != head of queue"); 83123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 83213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mEmptyCursorCount = 0; 83323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (data.queryType == QUERY_TYPE_NEWER) { 83423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan mNewerRequestsProcessed++; 83523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } else if (data.queryType == QUERY_TYPE_OLDER) { 83623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan mOlderRequestsProcessed++; 83723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 83813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 83913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = mAdapterInfos.getFirst().start; 84013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = mAdapterInfos.getLast().end; 84113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { // CursorSize == 0 84213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec querySpec = mQueryQueue.peek(); 84313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 84413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Update Adapter Info with new start and end date range 84513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!mAdapterInfos.isEmpty()) { 84613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo first = mAdapterInfos.getFirst(); 84713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo last = mAdapterInfos.getLast(); 84813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 84913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (first.start - 1 <= querySpec.end && querySpec.start < first.start) { 85013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan first.start = querySpec.start; 85113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 85213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 85313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (querySpec.start <= last.end + 1 && last.end < querySpec.end) { 85413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan last.end = querySpec.end; 85513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 85613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 85713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = first.start; 85813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = last.end; 85913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 86013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = querySpec.start; 86113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = querySpec.end; 86213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 86313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 86413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Update query specification with expanded search range 86513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // and maybe rerun query 86613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan switch (querySpec.queryType) { 86713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_OLDER: 86813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = querySpec.start; 86913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan querySpec.start -= MAX_QUERY_DURATION; 87013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 87113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_NEWER: 87213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = querySpec.end; 87313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan querySpec.end += MAX_QUERY_DURATION; 87413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 87513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_CLEAN: 87613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = querySpec.start; 87713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = querySpec.end; 87813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan querySpec.start -= MAX_QUERY_DURATION / 2; 87913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan querySpec.end += MAX_QUERY_DURATION / 2; 88013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 88113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 88213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 88313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (++mEmptyCursorCount > RETRIES_ON_NO_DATA) { 88413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Nothing in the cursor again. Dropping query 88513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mQueryQueue.poll(); 88613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 88713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 88813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 88913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan updateHeaderFooter(totalAgendaRangeStart, totalAgendaRangeEnd); 89013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 89113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Fire off the next query if any 89213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Iterator<QuerySpec> it = mQueryQueue.iterator(); 89313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan while (it.hasNext()) { 89413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec queryData = it.next(); 89513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!isInRange(queryData.start, queryData.end)) { 89613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Query accepted 89713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "Query accepted. QueueSize:" + mQueryQueue.size()); 89813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan doQuery(queryData); 89913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 90013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 90113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Query rejected 90213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan it.remove(); 90313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "Query rejected. QueueSize:" + mQueryQueue.size()); 90413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 90513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 90613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 90723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (BASICLOG) { 90813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info3 : mAdapterInfos) { 90913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "> " + info3.toString()); 91013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 91113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 91213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 91313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 91413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan /* 91513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * Update the adapter info array with a the new cursor. Close out old 91613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * cursors as needed. 91713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * 91813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * @return number of rows removed from the beginning 91913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */ 92013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int processNewCursor(QuerySpec data, Cursor cursor) { 92113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 92213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Remove adapter info's from adapterInfos as needed 92313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = pruneAdapterInfo(data.queryType); 92413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int listPositionOffset = 0; 92513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info == null) { 92613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info = new DayAdapterInfo(mContext); 92713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 92813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) 92913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "processNewCursor listPositionOffsetA=" 93013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + -info.size); 93113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan listPositionOffset = -info.size; 93213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 93313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 93413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Setup adapter info 93513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.start = data.start; 93613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.end = data.end; 93713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.cursor = cursor; 938dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan info.dayAdapter.changeCursor(info); 93913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.size = info.dayAdapter.getCount(); 94013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 94113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Insert into adapterInfos 94213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mAdapterInfos.isEmpty() 94313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan || data.end <= mAdapterInfos.getFirst().start) { 94413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAdapterInfos.addFirst(info); 94513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan listPositionOffset += info.size; 94613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else if (BASICLOG && data.start < mAdapterInfos.getLast().end) { 94713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAdapterInfos.addLast(info); 94813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info2 : mAdapterInfos) { 94913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e("========== BUG ==", info2.toString()); 95013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 95113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 95213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAdapterInfos.addLast(info); 95313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 95413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 95513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Update offsets in adapterInfos 95613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mRowCount = 0; 95713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info3 : mAdapterInfos) { 95813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info3.offset = mRowCount; 95913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mRowCount += info3.size; 96013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 96113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mLastUsedInfo = null; 96213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 96313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return listPositionOffset; 96413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 96513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 96613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 96713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 96813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan static String getViewTitle(View x) { 96913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan String title = ""; 97013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (x != null) { 97113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Object yy = x.getTag(); 97213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (yy instanceof AgendaAdapter.ViewHolder) { 97313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan TextView tv = ((AgendaAdapter.ViewHolder) yy).title; 97413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (tv != null) { 97513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan title = (String) tv.getText(); 97613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 97713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else if (yy != null) { 97813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan TextView dateView = ((AgendaByDayAdapter.ViewHolder) yy).dateView; 97913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (dateView != null) { 98013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan title = (String) dateView.getText(); 98113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 98213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 98313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 98413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return title; 98513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 98613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 9879a88873f9ec97b47aaaaae47208d22b3998b8e99Erik public void onResume() { 9889a88873f9ec97b47aaaaae47208d22b3998b8e99Erik mTZUpdater.run(); 9899a88873f9ec97b47aaaaae47208d22b3998b8e99Erik } 9909a88873f9ec97b47aaaaae47208d22b3998b8e99Erik 99113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public void setHideDeclinedEvents(boolean hideDeclined) { 99213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHideDeclined = hideDeclined; 99313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 994a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa 995ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan public void setSelectedView(View v) { 996ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan if (v != null) { 997ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan Object vh = v.getTag(); 998ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan if (vh instanceof AgendaAdapter.ViewHolder) { 999ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan mSelectedInstanceId = ((AgendaAdapter.ViewHolder) vh).instanceId; 1000ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } 1001ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } 1002ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } 1003ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan 1004ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan public long getSelectedInstanceId() { 1005ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan return mSelectedInstanceId; 1006ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan } 1007ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan 1008ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan public void setSelectedInstanceId(long selectedInstanceId) { 1009ffbc790abf31576c84af7ddeab090fcd93ef3299Michael Chan mSelectedInstanceId = selectedInstanceId; 1010a9507932dbc49ecb9f5c71fda6af3a47b0b2a39aDaisuke Miyakawa } 101113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan} 1012