1b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan/* 2b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * Copyright (C) 2013 The Android Open Source Project 3b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * 4b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * Licensed under the Apache License, Version 2.0 (the "License"); 5b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * you may not use this file except in compliance with the License. 6b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * You may obtain a copy of the License at 7b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * 8b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * http://www.apache.org/licenses/LICENSE-2.0 9b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * 10b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * Unless required by applicable law or agreed to in writing, software 11b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * distributed under the License is distributed on an "AS IS" BASIS, 12b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * See the License for the specific language governing permissions and 14b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * limitations under the License. 15b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan */ 16b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 17b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanpackage com.android.timezonepicker; 18b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 19b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.content.Context; 20b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.text.TextUtils; 21b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.util.Log; 22b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.view.LayoutInflater; 23b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.view.View; 24b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.view.View.OnClickListener; 25b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.view.ViewGroup; 26b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.widget.BaseAdapter; 27b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.widget.Filter; 28b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.widget.Filterable; 29b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport android.widget.TextView; 30b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 31b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanimport java.util.ArrayList; 3209a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzsteinimport java.util.Collections; 33b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 34b1b7080deea42aa533c3757b585cf765c6b76732Michael Chanpublic class TimeZoneFilterTypeAdapter extends BaseAdapter implements Filterable, OnClickListener { 35b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public static final String TAG = "TimeZoneFilterTypeAdapter"; 36b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 37a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung private static final boolean DEBUG = false; 38a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung 39b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public static final int FILTER_TYPE_EMPTY = -1; 40b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public static final int FILTER_TYPE_NONE = 0; 41852a8427f0ba0790fa2b7fd1bddba374f03953c6James Kung public static final int FILTER_TYPE_COUNTRY = 1; 42852a8427f0ba0790fa2b7fd1bddba374f03953c6James Kung public static final int FILTER_TYPE_STATE = 2; 43852a8427f0ba0790fa2b7fd1bddba374f03953c6James Kung public static final int FILTER_TYPE_GMT = 3; 44b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 45b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public interface OnSetFilterListener { 46b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan void onSetFilter(int filterType, String str, int time); 47b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 48b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 49b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan static class ViewHolder { 50b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int filterType; 51b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String str; 52b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int time; 53b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan TextView strTextView; 54b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 55b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan static void setupViewHolder(View v) { 56b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ViewHolder vh = new ViewHolder(); 57b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan vh.strTextView = (TextView) v.findViewById(R.id.value); 58b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan v.setTag(vh); 59b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 60b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 61b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 62b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan class FilterTypeResult { 63b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int type; 64b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String constraint; 65b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int time; 66b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 67852a8427f0ba0790fa2b7fd1bddba374f03953c6James Kung public FilterTypeResult(int type, String constraint, int time) { 680717b65fee21de6a321e42c9f3852f8b622c3215Michael Chan this.type = type; 690717b65fee21de6a321e42c9f3852f8b622c3215Michael Chan this.constraint = constraint; 700717b65fee21de6a321e42c9f3852f8b622c3215Michael Chan this.time = time; 710717b65fee21de6a321e42c9f3852f8b622c3215Michael Chan } 720717b65fee21de6a321e42c9f3852f8b622c3215Michael Chan 73b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 74b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public String toString() { 75b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return constraint; 76b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 77b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 78b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 79b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private ArrayList<FilterTypeResult> mLiveResults = new ArrayList<FilterTypeResult>(); 80b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private int mLiveResultsCount = 0; 81b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 82b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private ArrayFilter mFilter; 83b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 84b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private LayoutInflater mInflater; 85b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 86b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private TimeZoneData mTimeZoneData; 87b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private OnSetFilterListener mListener; 88b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 89b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public TimeZoneFilterTypeAdapter(Context context, TimeZoneData tzd, OnSetFilterListener l) { 90b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mTimeZoneData = tzd; 91b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mListener = l; 92b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 93b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 94b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 95b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 96b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int getCount() { 97b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return mLiveResultsCount; 98b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 99b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 100b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 101b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public FilterTypeResult getItem(int position) { 102b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return mLiveResults.get(position); 103b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 104b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 105b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 106b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public long getItemId(int position) { 107b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return position; 108b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 109b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 110b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 111b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public View getView(int position, View convertView, ViewGroup parent) { 112b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan View v; 113b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 114b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (convertView != null) { 115b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan v = convertView; 116b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 117b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan v = mInflater.inflate(R.layout.time_zone_filter_item, null); 118b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ViewHolder.setupViewHolder(v); 119b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 120b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 121b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ViewHolder vh = (ViewHolder) v.getTag(); 122b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 123b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (position >= mLiveResults.size()) { 124b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan Log.e(TAG, "getView: " + position + " of " + mLiveResults.size()); 125b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 126b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 127b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan FilterTypeResult filter = mLiveResults.get(position); 128b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 129b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan vh.filterType = filter.type; 130b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan vh.str = filter.constraint; 131b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan vh.time = filter.time; 132b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan vh.strTextView.setText(filter.constraint); 133b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return v; 134b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 135b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 136b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan OnClickListener mDummyListener = new OnClickListener() { 137b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 138b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 139b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public void onClick(View v) { 140b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 141b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan }; 142b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 143b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Implements OnClickListener 144b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 145b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // This onClickListener is actually called from the AutoCompleteTextView's 146b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // onItemClickListener. Trying to update the text in AutoCompleteTextView 147b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // is causing an infinite loop. 148b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 149b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public void onClick(View v) { 150b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mListener != null && v != null) { 151b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ViewHolder vh = (ViewHolder) v.getTag(); 152b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mListener.onSetFilter(vh.filterType, vh.str, vh.time); 153b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 154b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan notifyDataSetInvalidated(); 155b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 156b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 157b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Implements Filterable 158b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 159b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public Filter getFilter() { 160b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mFilter == null) { 161b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mFilter = new ArrayFilter(); 162b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 163b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return mFilter; 164b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 165b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 166b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private class ArrayFilter extends Filter { 167b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 168b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan protected FilterResults performFiltering(CharSequence prefix) { 169a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung if (DEBUG) { 170a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung Log.d(TAG, "performFiltering >>>> [" + prefix + "]"); 171a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung } 172b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 173b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan FilterResults results = new FilterResults(); 174b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan String prefixString = null; 175b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (prefix != null) { 176b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan prefixString = prefix.toString().trim().toLowerCase(); 177b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 178b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 179b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (TextUtils.isEmpty(prefixString)) { 180b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan results.values = null; 181b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan results.count = 0; 182b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return results; 183b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 184b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 185b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TODO Perf - we can loop through the filtered list if the new 186b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // search string starts with the old search string 187b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ArrayList<FilterTypeResult> filtered = new ArrayList<FilterTypeResult>(); 188b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 189b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // //////////////////////////////////////// 190b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Search by local time and GMT offset 191b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // //////////////////////////////////////// 192b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan boolean gmtOnly = false; 193b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int startParsePosition = 0; 194b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (prefixString.charAt(0) == '+' || prefixString.charAt(0) == '-') { 195b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan gmtOnly = true; 196b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 197b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 198b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (prefixString.startsWith("gmt")) { 199b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan startParsePosition = 3; 200b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan gmtOnly = true; 201b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 202b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 203b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int num = parseNum(prefixString, startParsePosition); 204b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (num != Integer.MIN_VALUE) { 205b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan boolean positiveOnly = prefixString.length() > startParsePosition 206b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan && prefixString.charAt(startParsePosition) == '+'; 207b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan handleSearchByGmt(filtered, num, positiveOnly); 208b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 209b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 210b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // //////////////////////////////////////// 211b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Search by country 212b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // //////////////////////////////////////// 21309a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein ArrayList<String> countries = new ArrayList<String>(); 214b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan for (String country : mTimeZoneData.mTimeZonesByCountry.keySet()) { 215b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TODO Perf - cache toLowerCase()? 2163d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (!TextUtils.isEmpty(country)) { 2173d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan final String lowerCaseCountry = country.toLowerCase(); 218020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein boolean isMatch = false; 2193d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (lowerCaseCountry.startsWith(prefixString) 2203d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan || (lowerCaseCountry.charAt(0) == prefixString.charAt(0) && 2213d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan isStartingInitialsFor(prefixString, lowerCaseCountry))) { 222020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein isMatch = true; 223020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein } else if (lowerCaseCountry.contains(" ")){ 224020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein // We should also search other words in the country name, so that 225020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein // searches like "Korea" yield "South Korea". 226020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein for (String word : lowerCaseCountry.split(" ")) { 227020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein if (word.startsWith(prefixString)) { 228020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein isMatch = true; 229020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein break; 230020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein } 231020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein } 232020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein } 233020b0c4329f432946df13a43a2831be0ee3b32cdSam Blitzstein if (isMatch) { 23409a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein countries.add(country); 235b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 236b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 237b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 23809a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein if (countries.size() > 0) { 23909a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein // Sort countries alphabetically. 24009a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein Collections.sort(countries); 24109a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein for (String country : countries) { 24209a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein filtered.add(new FilterTypeResult(FILTER_TYPE_COUNTRY, country, 0)); 24309a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein } 24409a2165919cb9b67c95b7885357c78e20bf5d9fbSam Blitzstein } 245b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 246b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // //////////////////////////////////////// 247b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // TODO Search by state 248b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // //////////////////////////////////////// 249a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung if (DEBUG) { 250a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung Log.d(TAG, "performFiltering <<<< " + filtered.size() + "[" + prefix + "]"); 251a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung } 252b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 253b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan results.values = filtered; 254b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan results.count = filtered.size(); 255b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return results; 256b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 257b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 2580717b65fee21de6a321e42c9f3852f8b622c3215Michael Chan /** 2593d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * Returns true if the prefixString is an initial for string. Note that 2603d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * this method will return true even if prefixString does not cover all 2613d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * the words. Words are separated by non-letters which includes spaces 2623d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * and symbols). 2633d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * 2643d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * For example: 26596e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein * isStartingInitialsFor("UA", "United Arab Emirates") would return true 2663d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * isStartingInitialsFor("US", "U.S. Virgin Island") would return true 26796e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein * 2683d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * @param prefixString 2693d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * @param string 2703d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan * @return 2713d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan */ 2723d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan private boolean isStartingInitialsFor(String prefixString, String string) { 2733d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan final int initialLen = prefixString.length(); 2743d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan final int strLen = string.length(); 2753d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan 2763d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan int initialIdx = 0; 2773d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan boolean wasWordBreak = true; 2783d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan for (int i = 0; i < strLen; i++) { 2793d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (!Character.isLetter(string.charAt(i))) { 2803d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan wasWordBreak = true; 2813d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan continue; 2823d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2833d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan 2843d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (wasWordBreak) { 2853d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (prefixString.charAt(initialIdx++) != string.charAt(i)) { 2863d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan return false; 2873d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2883d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan if (initialIdx == initialLen) { 2893d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan return true; 2903d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2913d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan wasWordBreak = false; 2923d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 2933d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 29496e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein 29596e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein // Special case for "USA". Note that both strings have been turned to lowercase already. 29696e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein if (prefixString.equals("usa") && string.equals("united states")) { 29796e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein return true; 29896e8dde991e426d0cd44f5b4eb76118fd7374ac0Sam Blitzstein } 2993d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan return false; 3003d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan } 3013d4445bb2a85048a735f21f7ec3ee9f9af6cee22Michael Chan 302b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan private void handleSearchByGmt(ArrayList<FilterTypeResult> filtered, int num, 303b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan boolean positiveOnly) { 304b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 305852a8427f0ba0790fa2b7fd1bddba374f03953c6James Kung FilterTypeResult r; 306b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (num >= 0) { 307b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (num == 1) { 308b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan for (int i = 19; i >= 10; i--) { 309b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mTimeZoneData.hasTimeZonesInHrOffset(i)) { 310852a8427f0ba0790fa2b7fd1bddba374f03953c6James Kung r = new FilterTypeResult(FILTER_TYPE_GMT, "GMT+" + i, i); 311b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan filtered.add(r); 312b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 313b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 314b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 315b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 316b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mTimeZoneData.hasTimeZonesInHrOffset(num)) { 317852a8427f0ba0790fa2b7fd1bddba374f03953c6James Kung r = new FilterTypeResult(FILTER_TYPE_GMT, "GMT+" + num, num); 318b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan filtered.add(r); 319b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 320b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan num *= -1; 321b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 322b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 323b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (!positiveOnly && num != 0) { 324b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mTimeZoneData.hasTimeZonesInHrOffset(num)) { 325852a8427f0ba0790fa2b7fd1bddba374f03953c6James Kung r = new FilterTypeResult(FILTER_TYPE_GMT, "GMT" + num, num); 326b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan filtered.add(r); 327b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 328b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 329b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (num == -1) { 330b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan for (int i = -10; i >= -19; i--) { 331b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mTimeZoneData.hasTimeZonesInHrOffset(i)) { 332852a8427f0ba0790fa2b7fd1bddba374f03953c6James Kung r = new FilterTypeResult(FILTER_TYPE_GMT, "GMT" + i, i); 333b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan filtered.add(r); 334b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 335b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 336b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 337b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 338b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 339b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 340b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan /** 341b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * Acceptable strings are in the following format: [+-]?[0-9]?[0-9] 342b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * 343b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * @param str 344b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * @param startIndex 345b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan * @return Integer.MIN_VALUE as invalid 346b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan */ 347b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan public int parseNum(String str, int startIndex) { 348b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int idx = startIndex; 349b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int num = Integer.MIN_VALUE; 350b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int negativeMultiplier = 1; 351b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 352b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // First char - check for + and - 353b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan char ch = str.charAt(idx++); 354b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan switch (ch) { 355b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan case '-': 356b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan negativeMultiplier = -1; 357b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // fall through 358b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan case '+': 359b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (idx >= str.length()) { 360b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // No more digits 361b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return Integer.MIN_VALUE; 362b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 363b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 364b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ch = str.charAt(idx++); 365b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan break; 366b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 367b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 368b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (!Character.isDigit(ch)) { 369b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // No digit 370b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return Integer.MIN_VALUE; 371b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 372b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 373b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Got first digit 374b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan num = Character.digit(ch, 10); 375b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 376b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Check next char 377b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (idx < str.length()) { 378b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan ch = str.charAt(idx++); 379b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (Character.isDigit(ch)) { 380b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Got second digit 381b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan num = 10 * num + Character.digit(ch, 10); 382b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 383b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return Integer.MIN_VALUE; 384b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 385b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 386b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 387b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (idx != str.length()) { 388b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan // Invalid 389b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return Integer.MIN_VALUE; 390b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 391b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 392a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung if (DEBUG) { 393a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung Log.d(TAG, "Parsing " + str + " -> " + negativeMultiplier * num); 394a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung } 395b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan return negativeMultiplier * num; 396b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 397b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 398b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @SuppressWarnings("unchecked") 399b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan @Override 400b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan protected void publishResults(CharSequence constraint, FilterResults 401b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan results) { 402b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (results.values == null || results.count == 0) { 403b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (mListener != null) { 404b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan int filterType; 405b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (TextUtils.isEmpty(constraint)) { 406b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan filterType = FILTER_TYPE_NONE; 407b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 408b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan filterType = FILTER_TYPE_EMPTY; 409b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 410b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mListener.onSetFilter(filterType, null, 0); 411b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 412a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung if (DEBUG) { 413a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung Log.d(TAG, "publishResults: " + results.count + " of null [" + constraint); 414a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung } 415b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 416b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mLiveResults = (ArrayList<FilterTypeResult>) results.values; 417a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung if (DEBUG) { 418a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung Log.d(TAG, "publishResults: " + results.count + " of " + mLiveResults.size() 419a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung + " [" + constraint); 420a8dd2dfa92587e5fc11e6c24da91be9e7bf3afb7James Kung } 421b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 422b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan mLiveResultsCount = results.count; 423b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan 424b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan if (results.count > 0) { 425b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan notifyDataSetChanged(); 426b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } else { 427b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan notifyDataSetInvalidated(); 428b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 429b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 430b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan } 431b1b7080deea42aa533c3757b585cf765c6b76732Michael Chan} 432