1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/* 2afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License. 6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at 7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * 10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and 14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License. 15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */ 16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings; 18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 190f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.app.Activity; 200f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.app.AlarmManager; 210f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.app.ListFragment; 220f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.content.Context; 230f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.content.res.XmlResourceParser; 24afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Bundle; 250f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.util.Log; 2697d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkeyimport android.view.LayoutInflater; 270f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.view.Menu; 280f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.view.MenuInflater; 290f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.view.MenuItem; 30afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.view.View; 3197d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkeyimport android.view.ViewGroup; 32afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.widget.ListView; 330f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport android.widget.SimpleAdapter; 34afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 350f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport org.xmlpull.v1.XmlPullParserException; 360f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 37f1582bc3f58ac440c11c54b844287915594b433fElliott Hughesimport java.text.SimpleDateFormat; 380f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.ArrayList; 390f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.Calendar; 400f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.Collections; 410f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.Comparator; 42f1582bc3f58ac440c11c54b844287915594b433fElliott Hughesimport java.util.Date; 43afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.HashMap; 44f1582bc3f58ac440c11c54b844287915594b433fElliott Hughesimport java.util.HashSet; 45afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.List; 46f1582bc3f58ac440c11c54b844287915594b433fElliott Hughesimport java.util.Locale; 47afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.Map; 480f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.TimeZone; 49f1582bc3f58ac440c11c54b844287915594b433fElliott Hughesimport libcore.icu.ICU; 50f1582bc3f58ac440c11c54b844287915594b433fElliott Hughesimport libcore.icu.TimeZoneNames; 510f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 520f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa/** 530f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * The class displaying a list of time zones that match a filter string 540f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * such as "Africa", "Europe", etc. Choosing an item from the list will set 55f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes * the time zone. Pressing Back without choosing from the list will not 560f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * result in a change in the time zone setting. 570f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa */ 580f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawapublic class ZonePicker extends ListFragment { 590f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final String TAG = "ZonePicker"; 600f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 610f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public static interface ZoneSelectionListener { 620f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa // You can add any argument if you really need it... 6371cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa public void onZoneSelected(TimeZone tz); 640f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 650f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 662571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static final String KEY_ID = "id"; // value: String 672571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static final String KEY_DISPLAYNAME = "name"; // value: String 682571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static final String KEY_GMT = "gmt"; // value: String 692571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static final String KEY_OFFSET = "offset"; // value: int (Integer) 700f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final String XMLTAG_TIMEZONE = "timezone"; 710f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 720f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final int HOURS_1 = 60 * 60000; 730f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 740f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final int MENU_TIMEZONE = Menu.FIRST+1; 750f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final int MENU_ALPHABETICAL = Menu.FIRST; 760f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 770f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private boolean mSortedByTimezone; 780f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 790f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private SimpleAdapter mTimezoneSortedAdapter; 800f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private SimpleAdapter mAlphabeticalAdapter; 810f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 820f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private ZoneSelectionListener mListener; 830f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 842571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa /** 852571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * Constructs an adapter with TimeZone list. Sorted by TimeZone in default. 862571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * 872571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @param sortedByName use Name for sorting the list. 882571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa */ 892571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public static SimpleAdapter constructTimezoneAdapter(Context context, 902571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa boolean sortedByName) { 910688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa return constructTimezoneAdapter(context, sortedByName, 924166ec39ecd8a2066f4426e1b359a0b1f95af05eJeff Sharkey R.layout.date_time_setup_custom_list_item_2); 930688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa } 940688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa 950688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa /** 960688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa * Constructs an adapter with TimeZone list. Sorted by TimeZone in default. 970688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa * 980688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa * @param sortedByName use Name for sorting the list. 990688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa */ 1000688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa public static SimpleAdapter constructTimezoneAdapter(Context context, 1010688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa boolean sortedByName, int layoutId) { 1020f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa final String[] from = new String[] {KEY_DISPLAYNAME, KEY_GMT}; 1030f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa final int[] to = new int[] {android.R.id.text1, android.R.id.text2}; 104afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 1052571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final String sortKey = (sortedByName ? KEY_DISPLAYNAME : KEY_OFFSET); 1062571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final MyComparator comparator = new MyComparator(sortKey); 107f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes ZoneGetter zoneGetter = new ZoneGetter(); 108f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes final List<HashMap<String, Object>> sortedList = zoneGetter.getZones(context); 1092571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa Collections.sort(sortedList, comparator); 1102571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final SimpleAdapter adapter = new SimpleAdapter(context, 1112571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa sortedList, 1120688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa layoutId, 1130f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa from, 1140f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa to); 1150f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 1162571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa return adapter; 1172571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1182571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 1192571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa /** 1202571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * Searches {@link TimeZone} from the given {@link SimpleAdapter} object, and returns 1212571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * the index for the TimeZone. 1222571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * 1232571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @param adapter SimpleAdapter constructed by 1242571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * {@link #constructTimezoneAdapter(Context, boolean)}. 1252571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @param tz TimeZone to be searched. 1262571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @return Index for the given TimeZone. -1 when there's no corresponding list item. 1272571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * returned. 1282571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa */ 1292571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public static int getTimeZoneIndex(SimpleAdapter adapter, TimeZone tz) { 1302571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final String defaultId = tz.getID(); 1312571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final int listSize = adapter.getCount(); 1322571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa for (int i = 0; i < listSize; i++) { 1332571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa // Using HashMap<String, Object> induces unnecessary warning. 1342571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final HashMap<?,?> map = (HashMap<?,?>)adapter.getItem(i); 1352571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final String id = (String)map.get(KEY_ID); 1362571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa if (defaultId.equals(id)) { 1372571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa // If current timezone is in this list, move focus to it 1382571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa return i; 1392571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1402571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1412571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa return -1; 1422571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1432571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 1442571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa /** 1452571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @param item one of items in adapters. The adapter should be constructed by 1462571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * {@link #constructTimezoneAdapter(Context, boolean)}. 1472571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @return TimeZone object corresponding to the item. 1482571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa */ 1492571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public static TimeZone obtainTimeZoneFromItem(Object item) { 1502571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa return TimeZone.getTimeZone((String)((Map<?, ?>)item).get(KEY_ID)); 1512571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1522571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 1532571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa @Override 154f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes public void onActivityCreated(Bundle savedInstanceState) { 155f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes super.onActivityCreated(savedInstanceState); 1562571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 1572571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final Activity activity = getActivity(); 1582571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa mTimezoneSortedAdapter = constructTimezoneAdapter(activity, false); 1592571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa mAlphabeticalAdapter = constructTimezoneAdapter(activity, true); 1600f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 1610f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa // Sets the adapter 1620f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa setSorting(true); 1631e9d497e2b0a3d00e83372d536b79c9ec0646b9dDaisuke Miyakawa setHasOptionsMenu(true); 1640f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 165afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 166afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 16797d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey public View onCreateView(LayoutInflater inflater, ViewGroup container, 16897d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey Bundle savedInstanceState) { 16997d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey final View view = super.onCreateView(inflater, container, savedInstanceState); 17097d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey final ListView list = (ListView) view.findViewById(android.R.id.list); 17197d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey Utils.forcePrepareCustomPreferencesList(container, view, list, false); 17297d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey return view; 17397d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey } 17497d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey 17597d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey @Override 1760f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1770f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.add(0, MENU_ALPHABETICAL, 0, R.string.zone_list_menu_sort_alphabetically) 1780f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa .setIcon(android.R.drawable.ic_menu_sort_alphabetically); 1790f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.add(0, MENU_TIMEZONE, 0, R.string.zone_list_menu_sort_by_timezone) 1800f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa .setIcon(R.drawable.ic_menu_3d_globe); 1810f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa super.onCreateOptionsMenu(menu, inflater); 182afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 1830f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 1840f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa @Override 1850f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public void onPrepareOptionsMenu(Menu menu) { 1860f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (mSortedByTimezone) { 1870f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.findItem(MENU_TIMEZONE).setVisible(false); 1880f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.findItem(MENU_ALPHABETICAL).setVisible(true); 1890f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } else { 1900f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.findItem(MENU_TIMEZONE).setVisible(true); 1910f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.findItem(MENU_ALPHABETICAL).setVisible(false); 1920f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 193afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 194afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 195afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 1960f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public boolean onOptionsItemSelected(MenuItem item) { 1970f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa switch (item.getItemId()) { 1980f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 1990f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa case MENU_TIMEZONE: 2000f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa setSorting(true); 2010f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return true; 2020f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2030f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa case MENU_ALPHABETICAL: 2040f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa setSorting(false); 2050f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return true; 2060f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2070f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa default: 2080f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return false; 2090f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2100f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2110f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2120f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public void setZoneSelectionListener(ZoneSelectionListener listener) { 2130f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa mListener = listener; 2140f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2150f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2162571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private void setSorting(boolean sortByTimezone) { 2172571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final SimpleAdapter adapter = 2182571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa sortByTimezone ? mTimezoneSortedAdapter : mAlphabeticalAdapter; 2192571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa setListAdapter(adapter); 2202571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa mSortedByTimezone = sortByTimezone; 2212571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final int defaultIndex = getTimeZoneIndex(adapter, TimeZone.getDefault()); 2222571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa if (defaultIndex >= 0) { 2232571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa setSelection(defaultIndex); 2242571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 2250f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2260f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 227f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes static class ZoneGetter { 228f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes private final List<HashMap<String, Object>> mZones = 229f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes new ArrayList<HashMap<String, Object>>(); 230f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes private final HashSet<String> mLocalZones = new HashSet<String>(); 231f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes private final Date mNow = Calendar.getInstance().getTime(); 232f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes private final SimpleDateFormat mZoneNameFormatter = new SimpleDateFormat("zzzz"); 233f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes 234f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes private List<HashMap<String, Object>> getZones(Context context) { 235f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes for (String olsonId : TimeZoneNames.forLocale(Locale.getDefault())) { 236f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes mLocalZones.add(olsonId); 237f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes } 238f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes try { 239f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes XmlResourceParser xrp = context.getResources().getXml(R.xml.timezones); 240f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes while (xrp.next() != XmlResourceParser.START_TAG) { 241f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes continue; 2420f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 243f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes xrp.next(); 2440f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa while (xrp.getEventType() != XmlResourceParser.END_TAG) { 245f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes while (xrp.getEventType() != XmlResourceParser.START_TAG) { 246f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) { 247f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes return mZones; 248f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes } 249f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes xrp.next(); 250f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes } 251f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes if (xrp.getName().equals(XMLTAG_TIMEZONE)) { 252f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes String olsonId = xrp.getAttributeValue(0); 253f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes addTimeZone(olsonId); 254f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes } 255f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes while (xrp.getEventType() != XmlResourceParser.END_TAG) { 256f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes xrp.next(); 257f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes } 2580f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa xrp.next(); 2590f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 260f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes xrp.close(); 261f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes } catch (XmlPullParserException xppe) { 262f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes Log.e(TAG, "Ill-formatted timezones.xml file"); 263f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes } catch (java.io.IOException ioe) { 264f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes Log.e(TAG, "Unable to read timezones.xml file"); 2650f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 266f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes return mZones; 2670f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2680f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 269f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes private void addTimeZone(String olsonId) { 270f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes // We always need the "GMT-07:00" string. 271f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes final TimeZone tz = TimeZone.getTimeZone(olsonId); 272f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes 273f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes // For the display name, we treat time zones within the country differently 274f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes // from other countries' time zones. So in en_US you'd get "Pacific Daylight Time" 275f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes // but in de_DE you'd get "Los Angeles" for the same time zone. 276f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes String displayName; 277f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes if (mLocalZones.contains(olsonId)) { 278f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes // Within a country, we just use the local name for the time zone. 279f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes mZoneNameFormatter.setTimeZone(tz); 280f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes displayName = mZoneNameFormatter.format(mNow); 281f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes } else { 282f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes // For other countries' time zones, we use the exemplar location. 283f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes final String localeName = Locale.getDefault().toString(); 284f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes displayName = TimeZoneNames.getExemplarLocation(localeName, olsonId); 285f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes } 2860f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 287f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes final HashMap<String, Object> map = new HashMap<String, Object>(); 288f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes map.put(KEY_ID, olsonId); 289f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes map.put(KEY_DISPLAYNAME, displayName); 29004487594d73c89aa53548e6ad864e40d15324c62Elliott Hughes map.put(KEY_GMT, DateTimeSettings.getTimeZoneText(tz, false)); 291f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes map.put(KEY_OFFSET, tz.getOffset(mNow.getTime())); 2920f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 293f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes mZones.add(map); 2940f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 295afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 2960f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 297afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 2982571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public void onListItemClick(ListView listView, View v, int position, long id) { 2998287658863ffa8885c34abfc07e020e5275619f6Amith Yamasani // Ignore extra clicks 3008287658863ffa8885c34abfc07e020e5275619f6Amith Yamasani if (!isResumed()) return; 3012571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final Map<?, ?> map = (Map<?, ?>)listView.getItemAtPosition(position); 3022571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final String tzId = (String) map.get(KEY_ID); 3032571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 3040f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa // Update the system timezone value 3050f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa final Activity activity = getActivity(); 3062571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final AlarmManager alarm = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE); 30771cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa alarm.setTimeZone(tzId); 30871cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa final TimeZone tz = TimeZone.getTimeZone(tzId); 3090f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (mListener != null) { 31071cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa mListener.onZoneSelected(tz); 31171cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa } else { 31271cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa getActivity().onBackPressed(); 3130f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3140f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3150f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3162571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static class MyComparator implements Comparator<HashMap<?, ?>> { 3170f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private String mSortingKey; 3180f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3190f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public MyComparator(String sortingKey) { 3200f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa mSortingKey = sortingKey; 3210f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3220f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3230f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public void setSortingKey(String sortingKey) { 3240f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa mSortingKey = sortingKey; 325afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 3260f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3272571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public int compare(HashMap<?, ?> map1, HashMap<?, ?> map2) { 3280f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa Object value1 = map1.get(mSortingKey); 3290f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa Object value2 = map2.get(mSortingKey); 3300f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3310f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa /* 3320f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * This should never happen, but just in-case, put non-comparable 3330f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * items at the end. 3340f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa */ 3350f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (!isComparable(value1)) { 3360f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return isComparable(value2) ? 1 : 0; 3370f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } else if (!isComparable(value2)) { 3380f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return -1; 3390f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3400f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3410f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return ((Comparable) value1).compareTo(value2); 3420f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3430f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3440f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private boolean isComparable(Object value) { 345f1582bc3f58ac440c11c54b844287915594b433fElliott Hughes return (value != null) && (value instanceof Comparable); 3460f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3470f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 348afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project} 349