AgendaWindowAdapter.java revision dad908b741d7d0a7e4a573030baeb74319ad9411
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 1713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanpackage com.android.calendar; 1813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 1913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.AsyncQueryHandler; 2013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.ContentResolver; 2113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.content.Context; 2213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.database.Cursor; 2313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.net.Uri; 2413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.provider.Calendar.Attendees; 2513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.provider.Calendar.Calendars; 2613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.provider.Calendar.Instances; 2713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.DateUtils; 2813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.text.format.Time; 2913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.util.Log; 3013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.LayoutInflater; 3113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View; 3213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.ViewGroup; 3313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.view.View.OnClickListener; 3413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.BaseAdapter; 3523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chanimport android.widget.ListView; 3613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport android.widget.TextView; 3713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 3813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Formatter; 3913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Iterator; 4013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.LinkedList; 4113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.Locale; 4213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanimport java.util.concurrent.ConcurrentLinkedQueue; 4313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 4413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan/* 4513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanBugs Bugs Bugs: 4613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- At rotation and launch time, the initial position is not set properly. This code is calling 4713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan listview.setSelection() in 2 rapid secessions but it dropped or didn't process the first one. 4813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Query of 2009 11 09 to 2010 01 15 didnt't return anything. In fact, Query of 2010 is showing nothing 4913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Scroll using trackball isn't repositioning properly after a new adapter is added. 5023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan- Track ball clicks at the header/footer doesn't work. 5113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Potential ping pong effect if the prefetch window is big and data is limited 5213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan- Add index in calendar provider 5313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 5413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanToDo ToDo ToDo: 5513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanGet design of header and footer from designer 5613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 5713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanMake scrolling smoother. 5813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanTest for correctness 5913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanLoading speed 6013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael ChanCheck for leaks and excessive allocations 6113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */ 6213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 6313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chanpublic class AgendaWindowAdapter extends BaseAdapter { 6413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 6523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan static final boolean BASICLOG = false; 6623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan static final boolean DEBUGLOG = false; 6713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static String TAG = "AgendaWindowAdapter"; 6813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 6913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final String AGENDA_SORT_ORDER = "startDay ASC, begin ASC, title ASC"; 7013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_TITLE = 1; 7113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_EVENT_LOCATION = 2; 7213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_ALL_DAY = 3; 7313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_HAS_ALARM = 4; 7413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_COLOR = 5; 7513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_RRULE = 6; 7613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_BEGIN = 7; 7713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_END = 8; 7813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_EVENT_ID = 9; 7913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_START_DAY = 10; 8013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_END_DAY = 11; 8113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public static final int INDEX_SELF_ATTENDEE_STATUS = 12; 8213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 8313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final String[] PROJECTION = new String[] { 8413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances._ID, // 0 8513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.TITLE, // 1 8613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.EVENT_LOCATION, // 2 8713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.ALL_DAY, // 3 8813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.HAS_ALARM, // 4 8913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.COLOR, // 5 9013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.RRULE, // 6 9113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.BEGIN, // 7 9213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.END, // 8 9313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.EVENT_ID, // 9 9413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.START_DAY, // 10 Julian start day 9513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.END_DAY, // 11 Julian end day 9613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Instances.SELF_ATTENDEE_STATUS, // 12 9713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan }; 9813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 9913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Listview may have a bug where the index/position is not consistent when there's a header. 10013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // TODO Need to look into this. 10113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int OFF_BY_ONE_BUG = 1; 10213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 10313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int MAX_NUM_OF_ADAPTERS = 5; 10413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 10513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int IDEAL_NUM_OF_EVENTS = 50; 10613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 10713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int MIN_QUERY_DURATION = 7; // days 10813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 10913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int MAX_QUERY_DURATION = 60; // days 11013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 11113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int PREFETCH_BOUNDARY = 1; 11213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 11313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Times to auto-expand/retry query after getting no data 11413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int RETRIES_ON_NO_DATA = 0; 11513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 11613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private Context mContext; 11713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 11813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private QueryHandler mQueryHandler; 11913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 12013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private AgendaListView mAgendaListView; 12113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 12213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mRowCount; // The sum of the rows in all the adapters 12313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 12413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mEmptyCursorCount; 12513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 12613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private DayAdapterInfo mLastUsedInfo; // Cached value of the last used adapter. 12713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 12813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private LinkedList<DayAdapterInfo> mAdapterInfos = new LinkedList<DayAdapterInfo>(); 12913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 13013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private ConcurrentLinkedQueue<QuerySpec> mQueryQueue = new ConcurrentLinkedQueue<QuerySpec>(); 13113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 13213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private TextView mHeaderView; 13313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 13413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private TextView mFooterView; 13513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 13613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean mDoneSettingUpHeaderFooter = false; 13713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 13813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan /* 13913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * When the user scrolled to the top, a query will be made for older events 14013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * and this will be incremented. Don't make more requests if 14113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * mOlderRequests > mOlderRequestsProcessed. 14213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */ 14313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mOlderRequests; 14413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 14513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Number of "older" query that has been processed. 14613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mOlderRequestsProcessed; 14713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 14813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan /* 14913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * When the user scrolled to the bottom, a query will be made for newer 15013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * events and this will be incremented. Don't make more requests if 15113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * mNewerRequests > mNewerRequestsProcessed. 15213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */ 15313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mNewerRequests; 15413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 15513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Number of "newer" query that has been processed. 15613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int mNewerRequestsProcessed; 15713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 15823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan // Note: Formatter is not thread safe. Fine for now as it is only used by the main thread. 15923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan private Formatter mFormatter; 16013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private StringBuilder mStringBuilder; 16113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 16213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean mShuttingDown; 16313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean mHideDeclined; 16413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 16513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Types of Query 16613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int QUERY_TYPE_OLDER = 0; // Query for older events 16713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int QUERY_TYPE_NEWER = 1; // Query for newer events 16813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static final int QUERY_TYPE_CLEAN = 2; // Delete everything and query around a date 16913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 17013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private static class QuerySpec { 17113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long queryStartMillis; 17213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 17313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time goToTime; 17413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 17513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int start; 17613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 17713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int end; 17813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 17913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int queryType; 18013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 18113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public QuerySpec(int queryType) { 18213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan this.queryType = queryType; 18313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 18423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan 18523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan @Override 18623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan public int hashCode() { 18723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan final int prime = 31; 18823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan int result = 1; 18923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + end; 19023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + (int) (queryStartMillis ^ (queryStartMillis >>> 32)); 19123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + queryType; 19223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + start; 19323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (goToTime != null) { 19423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan long goToTimeMillis = goToTime.toMillis(false); 19523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan result = prime * result + (int) (goToTimeMillis ^ (goToTimeMillis >>> 32)); 19623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 19723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return result; 19823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 19923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan 20023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan @Override 20123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan public boolean equals(Object obj) { 20223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (this == obj) return true; 20323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (obj == null) return false; 20423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (getClass() != obj.getClass()) return false; 20523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan QuerySpec other = (QuerySpec) obj; 20623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (end != other.end || queryStartMillis != other.queryStartMillis 20723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan || queryType != other.queryType || start != other.start) { 20823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return false; 20923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 21023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (goToTime != null) { 21123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (goToTime.toMillis(false) != other.goToTime.toMillis(false)) { 21223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return false; 21323f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 21423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } else { 21523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (other.goToTime != null) { 21623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return false; 21723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 21823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 21923f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan return true; 22023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 22113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 22213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 22313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan static class EventInfo { 22413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long begin; 22513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 22613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long end; 22713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 22813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long id; 22913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 23013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 231dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan static class DayAdapterInfo { 23213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Cursor cursor; 23313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 23413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan AgendaByDayAdapter dayAdapter; 23513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 23613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int start; // start day of the cursor's coverage 23713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 23813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int end; // end day of the cursor's coverage 23913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 24013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int offset; // offset in position in the list view 24113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 24213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int size; // dayAdapter.getCount() 24313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 24413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public DayAdapterInfo(Context context) { 24513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan dayAdapter = new AgendaByDayAdapter(context); 24613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 24713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 24813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 24913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public String toString() { 25013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time time = new Time(); 25113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan StringBuilder sb = new StringBuilder(); 25213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.setJulianDay(start); 25313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.normalize(false); 25413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan sb.append("Start:").append(time.toString()); 25513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.setJulianDay(end); 25613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.normalize(false); 25713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan sb.append(" End:").append(time.toString()); 25813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan sb.append(" Offset:").append(offset); 25913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan sb.append(" Size:").append(size); 26013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return sb.toString(); 26113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 26213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 26313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 26413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public AgendaWindowAdapter(AgendaActivity agendaActivity, 26513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan AgendaListView agendaListView) { 26613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mContext = agendaActivity; 26713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView = agendaListView; 26813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mQueryHandler = new QueryHandler(agendaActivity.getContentResolver()); 26913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 27013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mStringBuilder = new StringBuilder(50); 27113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mFormatter = new Formatter(mStringBuilder, Locale.getDefault()); 27213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 27313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan LayoutInflater inflater = (LayoutInflater) agendaActivity 27413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 27513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHeaderView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null); 27613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mFooterView = (TextView)inflater.inflate(R.layout.agenda_header_footer, null); 27713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHeaderView.setText(R.string.loading); 27813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView.addHeaderView(mHeaderView); 27913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 28013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 28113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Method in Adapter 28213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 28313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public int getViewTypeCount() { 28413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return AgendaByDayAdapter.TYPE_LAST; 28513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 28613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 28713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Method in BaseAdapter 28813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 28913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public boolean areAllItemsEnabled() { 29013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return false; 29113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 29213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 29313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Method in Adapter 29413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 29513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public int getItemViewType(int position) { 29613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 29713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 29813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info.dayAdapter.getItemViewType(position - info.offset); 29913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 30013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return -1; 30113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 30213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 30313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 30413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Method in BaseAdapter 30513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 30613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public boolean isEnabled(int position) { 30713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 30813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 30913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info.dayAdapter.isEnabled(position - info.offset); 31013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 31113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return false; 31213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 31313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 31413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 31513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Abstract Method in BaseAdapter 31613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public int getCount() { 31713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return mRowCount; 31813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 31913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 32013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Abstract Method in BaseAdapter 32113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public Object getItem(int position) { 32213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 32313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 32413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info.dayAdapter.getItem(position - info.offset); 32513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 32613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 32713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 32813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 32913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 33013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Abstract Method in BaseAdapter 33113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public long getItemId(int position) { 33213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 33313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 33413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info.dayAdapter.getItemId(position - info.offset); 33513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 33613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return -1; 33713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 33813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 33913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 34013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Abstract Method in BaseAdapter 34113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public View getView(int position, View convertView, ViewGroup parent) { 34213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (position >= (mRowCount - PREFETCH_BOUNDARY) 34313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan && mNewerRequests <= mNewerRequestsProcessed) { 34413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "queryForNewerEvents: "); 34513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mNewerRequests++; 34613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queueQuery(new QuerySpec(QUERY_TYPE_NEWER)); 34713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 34813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 34913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (position < PREFETCH_BOUNDARY 35013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan && mOlderRequests <= mOlderRequestsProcessed) { 35113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "queryForOlderEvents: "); 35213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mOlderRequests++; 35313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queueQuery(new QuerySpec(QUERY_TYPE_OLDER)); 35413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 35513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 35613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan View v; 35713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 35813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 35913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan v = info.dayAdapter.getView(position - info.offset, convertView, 36013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan parent); 36113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 36213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan //TODO 36313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "BUG: getAdapterInfoByPosition returned null!!! " + position); 36413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan TextView tv = new TextView(mContext); 36513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan tv.setText("Bug! " + position); 36613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan v = tv; 36713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 36813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 36913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) { 37013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "getView " + position + " = " + getViewTitle(v)); 37113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 37213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return v; 37313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 37413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 37513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int findDayPositionNearestTime(Time time) { 37613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "findDayPositionNearestTime " + time); 37713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 37813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByTime(time); 37913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 38013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info.offset + info.dayAdapter.findDayPositionNearestTime(time); 38113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 38213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return -1; 38313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 38413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 38513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 38613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private DayAdapterInfo getAdapterInfoByPosition(int position) { 38713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 38813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mLastUsedInfo != null && mLastUsedInfo.offset <= position 38913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan && position < (mLastUsedInfo.offset + mLastUsedInfo.size)) { 39013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return mLastUsedInfo; 39113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 39213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info : mAdapterInfos) { 39313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info.offset <= position 39413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan && position < (info.offset + info.size)) { 39513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mLastUsedInfo = info; 39613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info; 39713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 39813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 39913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 40013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 40113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 40213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 40313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private DayAdapterInfo getAdapterInfoByTime(Time time) { 40413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "getAdapterInfoByTime " + time.toString()); 40513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 40613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time tmpTime = new Time(time); 40713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long timeInMillis = tmpTime.normalize(true); 40813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int day = Time.getJulianDay(timeInMillis, tmpTime.gmtoff); 40913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 41013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info : mAdapterInfos) { 41113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info.start <= day && day < info.end) { 41213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return info; 41313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 41413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 41513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 41613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 41713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 41813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 41913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public EventInfo getEventByPosition(int position) { 42013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "getEventByPosition " + position); 42113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 42213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan EventInfo event = new EventInfo(); 42313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan position -= OFF_BY_ONE_BUG; 42413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = getAdapterInfoByPosition(position); 42513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info == null) { 42613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 42713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 42813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 42913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan position = info.dayAdapter.getCursorPosition(position - info.offset); 43013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (position == Integer.MIN_VALUE) { 43113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 43213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 43313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 43413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan boolean isDayHeader = false; 43513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (position < 0) { 43613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan position = -position; 43713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan isDayHeader = true; 43813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 43913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 44013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (position < info.cursor.getCount()) { 44113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.cursor.moveToPosition(position); 44213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan event.begin = info.cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN); 44313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (isDayHeader) { 44413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time time = new Time(); 44513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.set(event.begin); 44613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.hour = 0; 44713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.minute = 0; 44813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.second = 0; 44913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan event.begin = time.toMillis(false /* use isDst */); 45013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 45113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan event.end = info.cursor.getLong(AgendaWindowAdapter.INDEX_END); 45213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan event.id = info.cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID); 45313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 45413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return event; 45513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 45613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return null; 45713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 45813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 45913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public void refresh(Time goToTime, boolean forced) { 46023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan int startDay = Time.getJulianDay(goToTime.toMillis(false), goToTime.gmtoff); 46113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 46213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!forced && isInRange(startDay, startDay)) { 46313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // No need to requery 46413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView.setSelection(findDayPositionNearestTime(goToTime) + OFF_BY_ONE_BUG); 46513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return; 46613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 46713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 46813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Query for 2 days before the start day for a total of MIN_QUERY_DURATION days 46913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan startDay -= 2; 47013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int endDay = startDay + MIN_QUERY_DURATION; 47113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 47213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queueQuery(startDay, endDay, goToTime, QUERY_TYPE_CLEAN); 47313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 47413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 47513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public void close() { 47613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mShuttingDown = true; 47713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan pruneAdapterInfo(QUERY_TYPE_CLEAN); 47813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mQueryHandler != null) { 47913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mQueryHandler.cancelOperation(0); 48013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 48113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 48213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 48313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private DayAdapterInfo pruneAdapterInfo(int queryType) { 48413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 48513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo recycleMe = null; 48613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!mAdapterInfos.isEmpty()) { 48713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mAdapterInfos.size() >= MAX_NUM_OF_ADAPTERS) { 48813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (queryType == QUERY_TYPE_NEWER) { 48913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe = mAdapterInfos.removeFirst(); 49013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else if (queryType == QUERY_TYPE_OLDER) { 49113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe = mAdapterInfos.removeLast(); 49213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Keep the size only if the oldest items are removed. 49313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe.size = 0; 49413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 49513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (recycleMe != null) { 49613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (recycleMe.cursor != null) { 49713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe.cursor.close(); 49813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 49913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return recycleMe; 50013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 50113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 50213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 50313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mRowCount == 0 || queryType == QUERY_TYPE_CLEAN) { 50413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mRowCount = 0; 50513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int deletedRows = 0; 50613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info; 50713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan do { 50813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info = mAdapterInfos.poll(); 50913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info != null) { 51013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.cursor.close(); 51113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan deletedRows += info.size; 51213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe = info; 51313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 51413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } while (info != null); 51513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 51613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (recycleMe != null) { 51713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe.cursor = null; 51813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan recycleMe.size = deletedRows; 51913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 52013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 52113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 52213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return recycleMe; 52313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 52413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 52513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 52613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private String buildQuerySelection() { 52713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Respect the preference to show/hide declined events 52813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 52913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mHideDeclined) { 53013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return Calendars.SELECTED + "=1 AND " 53113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + Instances.SELF_ATTENDEE_STATUS + "!=" 53213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + Attendees.ATTENDEE_STATUS_DECLINED; 53313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 53413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return Calendars.SELECTED + "=1"; 53513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 53613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 53713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 53813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private Uri buildQueryUri(int start, int end) { 53913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan StringBuilder path = new StringBuilder(); 54013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan path.append(start); 54113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan path.append('/'); 54213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan path.append(end); 54313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Uri uri = Uri.withAppendedPath(Instances.CONTENT_BY_DAY_URI, path.toString()); 54413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return uri; 54513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 54613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 54713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean isInRange(int start, int end) { 54813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 54913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mAdapterInfos.isEmpty()) { 55013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return false; 55113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 55213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return mAdapterInfos.getFirst().start <= start && end <= mAdapterInfos.getLast().end; 55313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 55413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 55513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 55613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int calculateQueryDuration(int start, int end) { 55713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int queryDuration = MAX_QUERY_DURATION; 55813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mRowCount != 0) { 55913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryDuration = IDEAL_NUM_OF_EVENTS * (end - start + 1) / mRowCount; 56013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 56113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 56213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (queryDuration > MAX_QUERY_DURATION) { 56313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryDuration = MAX_QUERY_DURATION; 56413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else if (queryDuration < MIN_QUERY_DURATION) { 56513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryDuration = MIN_QUERY_DURATION; 56613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 56713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 56813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return queryDuration; 56913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 57013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 57113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean queueQuery(int start, int end, Time goToTime, int queryType) { 57213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec queryData = new QuerySpec(queryType); 57313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.goToTime = goToTime; 57413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.start = start; 57513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.end = end; 57613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return queueQuery(queryData); 57713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 57813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 57913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private boolean queueQuery(QuerySpec queryData) { 58013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Boolean queuedQuery; 58113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mQueryQueue) { 58213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queuedQuery = false; 58313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Boolean doQueryNow = mQueryQueue.isEmpty(); 58423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan mQueryQueue.add(queryData); 58523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan queuedQuery = true; 58623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (doQueryNow) { 58723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan doQuery(queryData); 58813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 58913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 59013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return queuedQuery; 59113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 59213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 59313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private void doQuery(QuerySpec queryData) { 59413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!mAdapterInfos.isEmpty()) { 59513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int start = mAdapterInfos.getFirst().start; 59613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int end = mAdapterInfos.getLast().end; 59713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int queryDuration = calculateQueryDuration(start, end); 59813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan switch(queryData.queryType) { 59913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_OLDER: 60013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.end = start - 1; 60113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.start = queryData.end - queryDuration; 60213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 60313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_NEWER: 60413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.start = end + 1; 60513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.end = queryData.start + queryDuration; 60613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 60713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 60813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 60913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 61013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (BASICLOG) { 61113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time time = new Time(); 61213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.setJulianDay(queryData.start); 61313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time time2 = new Time(); 61413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time2.setJulianDay(queryData.end); 61513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.v(TAG, "startQuery: " + time.toString() + " to " 61613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + time2.toString() + " then go to " + queryData.goToTime); 61713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 61813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 61913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mQueryHandler.cancelOperation(0); 62013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (BASICLOG) queryData.queryStartMillis = System.nanoTime(); 62113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mQueryHandler.startQuery(0, queryData, buildQueryUri( 62213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queryData.start, queryData.end), PROJECTION, 62313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan buildQuerySelection(), null, AGENDA_SORT_ORDER); 62413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 62513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 62613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private String formatDateString(int julianDay) { 62713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Time time = new Time(); 62813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan time.setJulianDay(julianDay); 62913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long millis = time.toMillis(false); 63013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mStringBuilder.setLength(0); 63113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return DateUtils.formatDateRange(mContext, mFormatter, millis, millis, 63213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_SHOW_DATE 63313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan | DateUtils.FORMAT_ABBREV_MONTH).toString(); 63413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 63513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 63613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private void updateHeaderFooter(final int start, final int end) { 63713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHeaderView.setText(mContext.getString(R.string.show_older_events, 63813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan formatDateString(start))); 63913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mFooterView.setText(mContext.getString(R.string.show_newer_events, 64013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan formatDateString(end))); 64113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 64213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 64313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private class QueryHandler extends AsyncQueryHandler { 64413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 64513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public QueryHandler(ContentResolver cr) { 64613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan super(cr); 64713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 64813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 64913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan @Override 65013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 65113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec data = (QuerySpec)cookie; 65213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (BASICLOG) { 65313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan long queryEndMillis = System.nanoTime(); 65413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "Query time(ms): " 65513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + (queryEndMillis - data.queryStartMillis) / 1000000 65613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + " Count: " + cursor.getCount()); 65713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 65813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 65913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mShuttingDown) { 66013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan cursor.close(); 66113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return; 66213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 66313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 66413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Notify Listview of changes and update position 66513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int cursorSize = cursor.getCount(); 66613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (cursorSize > 0 || mAdapterInfos.isEmpty()) { 66713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan final int listPositionOffset = processNewCursor(data, cursor); 66813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (data.goToTime == null) { // Typical Scrolling type query 66913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan notifyDataSetChanged(); 67013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (listPositionOffset != 0) { 67113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView.shiftSelection(listPositionOffset); 67213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 67313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { // refresh() called. Go to the designated position 67413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan final Time goToTime = data.goToTime; 67513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan notifyDataSetChanged(); 67613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int newPosition = findDayPositionNearestTime(goToTime); 67713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (newPosition >= 0) { 67813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView.setSelection(newPosition + OFF_BY_ONE_BUG); 67913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 68013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) 68113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "Setting listview to " + 68213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan "findDayPositionNearestTime: " + (newPosition + OFF_BY_ONE_BUG)); 68313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 68413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 68513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan cursor.close(); 68613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 68713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 68813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Update header and footer 68913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!mDoneSettingUpHeaderFooter) { 69013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan OnClickListener headerFooterOnClickListener = new OnClickListener() { 69113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public void onClick(View v) { 69213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (v == mHeaderView) { 69313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queueQuery(new QuerySpec(QUERY_TYPE_OLDER)); 69413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 69513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan queueQuery(new QuerySpec(QUERY_TYPE_NEWER)); 69613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 69713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan }}; 69813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHeaderView.setOnClickListener(headerFooterOnClickListener); 69913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mFooterView.setOnClickListener(headerFooterOnClickListener); 70013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAgendaListView.addFooterView(mFooterView); 70113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mDoneSettingUpHeaderFooter = true; 70213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 70313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mQueryQueue) { 70413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int totalAgendaRangeStart = -1; 70513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int totalAgendaRangeEnd = -1; 70613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 70713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (cursorSize != 0) { 70813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Remove the query that just completed 70913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec x = mQueryQueue.poll(); 71023f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (BASICLOG && !x.equals(data)) { 71123f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan Log.e(TAG, "onQueryComplete - cookie != head of queue"); 71223f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 71313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mEmptyCursorCount = 0; 71423f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (data.queryType == QUERY_TYPE_NEWER) { 71523f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan mNewerRequestsProcessed++; 71623f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } else if (data.queryType == QUERY_TYPE_OLDER) { 71723f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan mOlderRequestsProcessed++; 71823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan } 71913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 72013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = mAdapterInfos.getFirst().start; 72113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = mAdapterInfos.getLast().end; 72213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { // CursorSize == 0 72313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec querySpec = mQueryQueue.peek(); 72413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 72513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Update Adapter Info with new start and end date range 72613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!mAdapterInfos.isEmpty()) { 72713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo first = mAdapterInfos.getFirst(); 72813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo last = mAdapterInfos.getLast(); 72913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 73013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (first.start - 1 <= querySpec.end && querySpec.start < first.start) { 73113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan first.start = querySpec.start; 73213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 73313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 73413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (querySpec.start <= last.end + 1 && last.end < querySpec.end) { 73513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan last.end = querySpec.end; 73613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 73713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 73813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = first.start; 73913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = last.end; 74013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 74113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = querySpec.start; 74213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = querySpec.end; 74313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 74413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 74513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Update query specification with expanded search range 74613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // and maybe rerun query 74713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan switch (querySpec.queryType) { 74813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_OLDER: 74913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = querySpec.start; 75013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan querySpec.start -= MAX_QUERY_DURATION; 75113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 75213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_NEWER: 75313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = querySpec.end; 75413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan querySpec.end += MAX_QUERY_DURATION; 75513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 75613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan case QUERY_TYPE_CLEAN: 75713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeStart = querySpec.start; 75813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan totalAgendaRangeEnd = querySpec.end; 75913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan querySpec.start -= MAX_QUERY_DURATION / 2; 76013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan querySpec.end += MAX_QUERY_DURATION / 2; 76113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 76213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 76313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 76413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (++mEmptyCursorCount > RETRIES_ON_NO_DATA) { 76513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Nothing in the cursor again. Dropping query 76613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mQueryQueue.poll(); 76713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 76813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 76913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 77013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan updateHeaderFooter(totalAgendaRangeStart, totalAgendaRangeEnd); 77113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 77213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Fire off the next query if any 77313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Iterator<QuerySpec> it = mQueryQueue.iterator(); 77413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan while (it.hasNext()) { 77513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan QuerySpec queryData = it.next(); 77613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (!isInRange(queryData.start, queryData.end)) { 77713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Query accepted 77813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "Query accepted. QueueSize:" + mQueryQueue.size()); 77913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan doQuery(queryData); 78013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan break; 78113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 78213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Query rejected 78313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan it.remove(); 78413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) Log.e(TAG, "Query rejected. QueueSize:" + mQueryQueue.size()); 78513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 78613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 78713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 78823f400cdb34b08d9003f4a96fca5976ad632e4ceMichael Chan if (BASICLOG) { 78913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info3 : mAdapterInfos) { 79013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "> " + info3.toString()); 79113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 79213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 79313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 79413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 79513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan /* 79613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * Update the adapter info array with a the new cursor. Close out old 79713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * cursors as needed. 79813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * 79913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan * @return number of rows removed from the beginning 80013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan */ 80113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan private int processNewCursor(QuerySpec data, Cursor cursor) { 80213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan synchronized (mAdapterInfos) { 80313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Remove adapter info's from adapterInfos as needed 80413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan DayAdapterInfo info = pruneAdapterInfo(data.queryType); 80513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan int listPositionOffset = 0; 80613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (info == null) { 80713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info = new DayAdapterInfo(mContext); 80813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 80913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (DEBUGLOG) 81013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e(TAG, "processNewCursor listPositionOffsetA=" 81113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan + -info.size); 81213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan listPositionOffset = -info.size; 81313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 81413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 81513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Setup adapter info 81613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.start = data.start; 81713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.end = data.end; 81813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.cursor = cursor; 819dad908b741d7d0a7e4a573030baeb74319ad9411Michael Chan info.dayAdapter.changeCursor(info); 82013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info.size = info.dayAdapter.getCount(); 82113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 82213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Insert into adapterInfos 82313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (mAdapterInfos.isEmpty() 82413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan || data.end <= mAdapterInfos.getFirst().start) { 82513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAdapterInfos.addFirst(info); 82613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan listPositionOffset += info.size; 82713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else if (BASICLOG && data.start < mAdapterInfos.getLast().end) { 82813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAdapterInfos.addLast(info); 82913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info2 : mAdapterInfos) { 83013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Log.e("========== BUG ==", info2.toString()); 83113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 83213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else { 83313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mAdapterInfos.addLast(info); 83413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 83513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 83613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan // Update offsets in adapterInfos 83713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mRowCount = 0; 83813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan for (DayAdapterInfo info3 : mAdapterInfos) { 83913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan info3.offset = mRowCount; 84013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mRowCount += info3.size; 84113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 84213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mLastUsedInfo = null; 84313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 84413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return listPositionOffset; 84513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 84613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 84713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 84813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 84913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan static String getViewTitle(View x) { 85013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan String title = ""; 85113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (x != null) { 85213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan Object yy = x.getTag(); 85313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (yy instanceof AgendaAdapter.ViewHolder) { 85413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan TextView tv = ((AgendaAdapter.ViewHolder) yy).title; 85513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (tv != null) { 85613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan title = (String) tv.getText(); 85713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 85813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } else if (yy != null) { 85913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan TextView dateView = ((AgendaByDayAdapter.ViewHolder) yy).dateView; 86013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan if (dateView != null) { 86113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan title = (String) dateView.getText(); 86213850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 86313850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 86413850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 86513850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan return title; 86613850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 86713850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan 86813850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan public void setHideDeclinedEvents(boolean hideDeclined) { 86913850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan mHideDeclined = hideDeclined; 87013850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan } 87113850936e579386a0f2ee589607bbf8b7cf1a7d4Michael Chan} 872