TimeZoneResultAdapter.java revision b1b7080deea42aa533c3757b585cf765c6b76732
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.timezonepicker; 18 19import android.content.Context; 20import android.content.SharedPreferences; 21import android.text.TextUtils; 22import android.util.Log; 23import android.view.LayoutInflater; 24import android.view.View; 25import android.view.View.OnClickListener; 26import android.view.ViewGroup; 27import android.widget.BaseAdapter; 28import android.widget.TextView; 29 30import com.android.timezonepicker.TimeZoneFilterTypeAdapter.OnSetFilterListener; 31import com.android.timezonepicker.TimeZonePickerView.OnTimeZoneSetListener; 32 33import java.util.ArrayList; 34import java.util.Arrays; 35import java.util.Iterator; 36import java.util.List; 37 38public class TimeZoneResultAdapter extends BaseAdapter implements OnClickListener, 39 OnSetFilterListener { 40 private static final String TAG = "TimeZoneResultAdapter"; 41 private static final int VIEW_TAG_TIME_ZONE = R.id.time_zone; 42 43 /** SharedPref name and key for recent time zones */ 44 private static final String SHARED_PREFS_NAME = "com.android.calendar_preferences"; 45 private static final String KEY_RECENT_TIMEZONES = "preferences_recent_timezones"; 46 47 /** 48 * The delimiter we use when serializing recent timezones to shared 49 * preferences 50 */ 51 private static final String RECENT_TIMEZONES_DELIMITER = ","; 52 53 /** The maximum number of recent timezones to save */ 54 private static final int MAX_RECENT_TIMEZONES = 3; 55 56 static class ViewHolder { 57 TextView timeZone; 58 TextView timeOffset; 59 TextView location; 60 61 static void setupViewHolder(View v) { 62 ViewHolder vh = new ViewHolder(); 63 vh.timeZone = (TextView) v.findViewById(R.id.time_zone); 64 vh.timeOffset = (TextView) v.findViewById(R.id.time_offset); 65 vh.location = (TextView) v.findViewById(R.id.location); 66 v.setTag(vh); 67 } 68 } 69 70 private Context mContext; 71 private LayoutInflater mInflater; 72 73 private OnTimeZoneSetListener mTimeZoneSetListener; 74 private TimeZoneData mTimeZoneData; 75 76 private int[] mFilteredTimeZoneIndices; 77 private int mFilteredTimeZoneLength = 0; 78 private int mFilterType; 79 80 public TimeZoneResultAdapter(Context context, TimeZoneData tzd, 81 com.android.timezonepicker.TimeZonePickerView.OnTimeZoneSetListener l) { 82 super(); 83 84 mContext = context; 85 mTimeZoneData = tzd; 86 mTimeZoneSetListener = l; 87 88 mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 89 90 mFilteredTimeZoneIndices = new int[mTimeZoneData.size()]; 91 92 onSetFilter(TimeZoneFilterTypeAdapter.FILTER_TYPE_NONE, null, 0); 93 } 94 95 // Implements OnSetFilterListener 96 @Override 97 public void onSetFilter(int filterType, String str, int time) { 98 Log.d(TAG, "onSetFilter: " + filterType + " [" + str + "] " + time); 99 100 mFilterType = filterType; 101 mFilteredTimeZoneLength = 0; 102 int idx = 0; 103 104 switch (filterType) { 105 case TimeZoneFilterTypeAdapter.FILTER_TYPE_EMPTY: 106 break; 107 case TimeZoneFilterTypeAdapter.FILTER_TYPE_NONE: 108 // Show the default/current value first 109 int defaultTzIndex = mTimeZoneData.getDefaultTimeZoneIndex(); 110 if (defaultTzIndex != -1) { 111 mFilteredTimeZoneIndices[mFilteredTimeZoneLength++] = defaultTzIndex; 112 } 113 114 // Show the recent selections 115 SharedPreferences prefs = mContext.getSharedPreferences(SHARED_PREFS_NAME, 116 Context.MODE_PRIVATE); 117 String recentsString = prefs.getString(KEY_RECENT_TIMEZONES, null); 118 if (!TextUtils.isEmpty(recentsString)) { 119 String[] recents = recentsString.split(RECENT_TIMEZONES_DELIMITER); 120 for (int i = recents.length - 1; i >= 0; i--) { 121 if (!TextUtils.isEmpty(recents[i]) 122 && !recents[i].equals(mTimeZoneData.mDefaultTimeZoneId)) { 123 int index = mTimeZoneData.findIndexByTimeZoneIdSlow(recents[i]); 124 if (index != -1) { 125 mFilteredTimeZoneIndices[mFilteredTimeZoneLength++] = index; 126 } 127 } 128 } 129 } 130 131 break; 132 case TimeZoneFilterTypeAdapter.FILTER_TYPE_GMT: 133 ArrayList<Integer> indices = mTimeZoneData.getTimeZonesByOffset(time); 134 if (indices != null) { 135 for (Integer i : indices) { 136 mFilteredTimeZoneIndices[mFilteredTimeZoneLength++] = i; 137 } 138 } 139 break; 140 case TimeZoneFilterTypeAdapter.FILTER_TYPE_TIME: 141 // TODO Filter by time properly 142 for (TimeZoneInfo tzi : mTimeZoneData.mTimeZones) { 143 if (str.equalsIgnoreCase(tzi.getGmtDisplayName(mContext))) { 144 mFilteredTimeZoneIndices[mFilteredTimeZoneLength++] = idx; 145 } 146 idx++; 147 } 148 break; 149 case TimeZoneFilterTypeAdapter.FILTER_TYPE_TIME_ZONE: 150 for (TimeZoneInfo tzi : mTimeZoneData.mTimeZones) { 151 if (str.equalsIgnoreCase(tzi.mDisplayName)) { 152 mFilteredTimeZoneIndices[mFilteredTimeZoneLength++] = idx; 153 } 154 idx++; 155 } 156 break; 157 case TimeZoneFilterTypeAdapter.FILTER_TYPE_COUNTRY: 158 ArrayList<Integer> tzIds = mTimeZoneData.mTimeZonesByCountry.get(str); 159 if (tzIds != null) { 160 for (Integer tzi : tzIds) { 161 mFilteredTimeZoneIndices[mFilteredTimeZoneLength++] = tzi; 162 } 163 } 164 break; 165 case TimeZoneFilterTypeAdapter.FILTER_TYPE_STATE: 166 // TODO Filter by state 167 break; 168 default: 169 throw new IllegalArgumentException(); 170 } 171 notifyDataSetChanged(); 172 } 173 174 /** 175 * Saves the given timezone ID as a recent timezone under shared 176 * preferences. If there are already the maximum number of recent timezones 177 * saved, it will remove the oldest and append this one. 178 * 179 * @param id the ID of the timezone to save 180 * @see {@link #MAX_RECENT_TIMEZONES} 181 */ 182 public void saveRecentTimezone(String id) { 183 SharedPreferences prefs = mContext.getSharedPreferences(SHARED_PREFS_NAME, 184 Context.MODE_PRIVATE); 185 String recentsString = prefs.getString(KEY_RECENT_TIMEZONES, null); 186 if (recentsString == null) { 187 recentsString = id; 188 } else { 189 List<String> recents = new ArrayList<String>( 190 Arrays.asList(recentsString.split(RECENT_TIMEZONES_DELIMITER))); 191 Iterator<String> it = recents.iterator(); 192 while(it.hasNext()) { 193 String tz = it.next(); 194 if (id.equals(tz)) { 195 it.remove(); 196 } 197 } 198 199 while (recents.size() >= MAX_RECENT_TIMEZONES) { 200 recents.remove(0); 201 } 202 recents.add(id); 203 204 StringBuilder builder = new StringBuilder(); 205 boolean first = true; 206 for (String recent : recents) { 207 if (first) { 208 first = false; 209 } else { 210 builder.append(RECENT_TIMEZONES_DELIMITER); 211 } 212 builder.append(recent); 213 } 214 recentsString = builder.toString(); 215 } 216 217 prefs.edit().putString(KEY_RECENT_TIMEZONES, recentsString).apply(); 218 } 219 220 @Override 221 public int getCount() { 222 return mFilteredTimeZoneLength; 223 } 224 225 @Override 226 public TimeZoneInfo getItem(int position) { 227 if (position < 0 || position >= mFilteredTimeZoneLength) { 228 return null; 229 } 230 231 return mTimeZoneData.get(mFilteredTimeZoneIndices[position]); 232 } 233 234 @Override 235 public long getItemId(int position) { 236 return mFilteredTimeZoneIndices[position]; 237 } 238 239 @Override 240 public View getView(int position, View convertView, ViewGroup parent) { 241 View v = convertView; 242 243 if (v == null) { 244 v = mInflater.inflate(R.layout.time_zone_item, null); 245 v.setOnClickListener(this); 246 ViewHolder.setupViewHolder(v); 247 } 248 249 TimeZoneInfo tzi = mTimeZoneData.get(mFilteredTimeZoneIndices[position]); 250 v.setTag(VIEW_TAG_TIME_ZONE, tzi); 251 252 ViewHolder vh = (ViewHolder) v.getTag(); 253 vh.timeOffset.setText(tzi.getGmtDisplayName(mContext)); 254 255 vh.timeZone.setText(tzi.mDisplayName); 256 257 String location = tzi.mCountry; 258 if (location == null) { 259 vh.location.setVisibility(View.INVISIBLE); 260 } else { 261 vh.location.setText(location); 262 vh.location.setVisibility(View.VISIBLE); 263 } 264 265 return v; 266 } 267 268 @Override 269 public boolean hasStableIds() { 270 return true; 271 } 272 273 // Implements OnClickListener 274 @Override 275 public void onClick(View v) { 276 if (mTimeZoneSetListener != null) { 277 TimeZoneInfo tzi = (TimeZoneInfo) v.getTag(VIEW_TAG_TIME_ZONE); 278 mTimeZoneSetListener.onTimeZoneSet(tzi); 279 saveRecentTimezone(tzi.mTzId); 280 } 281 } 282 283} 284