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 370f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.ArrayList; 380f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.Calendar; 390f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.Collections; 400f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.Comparator; 41afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.HashMap; 42afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.List; 43afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport java.util.Map; 440f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawaimport java.util.TimeZone; 450f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 460f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa/** 470f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * The class displaying a list of time zones that match a filter string 480f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * such as "Africa", "Europe", etc. Choosing an item from the list will set 490f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * the time zone. Pressing Back without choosing from the list will not 500f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * result in a change in the time zone setting. 510f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa */ 520f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawapublic class ZonePicker extends ListFragment { 530f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final String TAG = "ZonePicker"; 540f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 550f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public static interface ZoneSelectionListener { 560f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa // You can add any argument if you really need it... 5771cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa public void onZoneSelected(TimeZone tz); 580f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 590f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 602571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static final String KEY_ID = "id"; // value: String 612571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static final String KEY_DISPLAYNAME = "name"; // value: String 622571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static final String KEY_GMT = "gmt"; // value: String 632571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static final String KEY_OFFSET = "offset"; // value: int (Integer) 640f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final String XMLTAG_TIMEZONE = "timezone"; 650f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 660f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final int HOURS_1 = 60 * 60000; 670f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 680f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final int MENU_TIMEZONE = Menu.FIRST+1; 690f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private static final int MENU_ALPHABETICAL = Menu.FIRST; 700f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 710f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private boolean mSortedByTimezone; 720f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 730f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private SimpleAdapter mTimezoneSortedAdapter; 740f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private SimpleAdapter mAlphabeticalAdapter; 750f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 760f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private ZoneSelectionListener mListener; 770f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 782571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa /** 792571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * Constructs an adapter with TimeZone list. Sorted by TimeZone in default. 802571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * 812571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @param sortedByName use Name for sorting the list. 822571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa */ 832571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public static SimpleAdapter constructTimezoneAdapter(Context context, 842571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa boolean sortedByName) { 850688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa return constructTimezoneAdapter(context, sortedByName, 864166ec39ecd8a2066f4426e1b359a0b1f95af05eJeff Sharkey R.layout.date_time_setup_custom_list_item_2); 870688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa } 880688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa 890688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa /** 900688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa * Constructs an adapter with TimeZone list. Sorted by TimeZone in default. 910688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa * 920688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa * @param sortedByName use Name for sorting the list. 930688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa */ 940688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa public static SimpleAdapter constructTimezoneAdapter(Context context, 950688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa boolean sortedByName, int layoutId) { 960f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa final String[] from = new String[] {KEY_DISPLAYNAME, KEY_GMT}; 970f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa final int[] to = new int[] {android.R.id.text1, android.R.id.text2}; 98afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 992571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final String sortKey = (sortedByName ? KEY_DISPLAYNAME : KEY_OFFSET); 1002571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final MyComparator comparator = new MyComparator(sortKey); 1012571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final List<HashMap<String, Object>> sortedList = getZones(context); 1022571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa Collections.sort(sortedList, comparator); 1032571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final SimpleAdapter adapter = new SimpleAdapter(context, 1042571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa sortedList, 1050688f251af533c09682c791ae20834ab7854d7d7Daisuke Miyakawa layoutId, 1060f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa from, 1070f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa to); 1080f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 1092571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa return adapter; 1102571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1112571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 1122571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa /** 1132571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * Searches {@link TimeZone} from the given {@link SimpleAdapter} object, and returns 1142571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * the index for the TimeZone. 1152571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * 1162571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @param adapter SimpleAdapter constructed by 1172571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * {@link #constructTimezoneAdapter(Context, boolean)}. 1182571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @param tz TimeZone to be searched. 1192571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @return Index for the given TimeZone. -1 when there's no corresponding list item. 1202571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * returned. 1212571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa */ 1222571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public static int getTimeZoneIndex(SimpleAdapter adapter, TimeZone tz) { 1232571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final String defaultId = tz.getID(); 1242571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final int listSize = adapter.getCount(); 1252571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa for (int i = 0; i < listSize; i++) { 1262571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa // Using HashMap<String, Object> induces unnecessary warning. 1272571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final HashMap<?,?> map = (HashMap<?,?>)adapter.getItem(i); 1282571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final String id = (String)map.get(KEY_ID); 1292571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa if (defaultId.equals(id)) { 1302571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa // If current timezone is in this list, move focus to it 1312571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa return i; 1322571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1332571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1342571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa return -1; 1352571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1362571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 1372571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa /** 1382571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @param item one of items in adapters. The adapter should be constructed by 1392571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * {@link #constructTimezoneAdapter(Context, boolean)}. 1402571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa * @return TimeZone object corresponding to the item. 1412571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa */ 1422571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public static TimeZone obtainTimeZoneFromItem(Object item) { 1432571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa return TimeZone.getTimeZone((String)((Map<?, ?>)item).get(KEY_ID)); 1442571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 1452571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 1462571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa @Override 1472571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public void onActivityCreated(Bundle savedInstanseState) { 1482571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa super.onActivityCreated(savedInstanseState); 1492571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 1502571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final Activity activity = getActivity(); 1512571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa mTimezoneSortedAdapter = constructTimezoneAdapter(activity, false); 1522571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa mAlphabeticalAdapter = constructTimezoneAdapter(activity, true); 1530f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 1540f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa // Sets the adapter 1550f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa setSorting(true); 1561e9d497e2b0a3d00e83372d536b79c9ec0646b9dDaisuke Miyakawa setHasOptionsMenu(true); 1570f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 158afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 159afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 16097d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey public View onCreateView(LayoutInflater inflater, ViewGroup container, 16197d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey Bundle savedInstanceState) { 16297d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey final View view = super.onCreateView(inflater, container, savedInstanceState); 16397d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey final ListView list = (ListView) view.findViewById(android.R.id.list); 16497d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey Utils.forcePrepareCustomPreferencesList(container, view, list, false); 16597d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey return view; 16697d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey } 16797d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey 16897d07fa3aedde44368818551dc789eaff7bfb047Jeff Sharkey @Override 1690f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 1700f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.add(0, MENU_ALPHABETICAL, 0, R.string.zone_list_menu_sort_alphabetically) 1710f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa .setIcon(android.R.drawable.ic_menu_sort_alphabetically); 1720f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.add(0, MENU_TIMEZONE, 0, R.string.zone_list_menu_sort_by_timezone) 1730f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa .setIcon(R.drawable.ic_menu_3d_globe); 1740f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa super.onCreateOptionsMenu(menu, inflater); 175afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 1760f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 1770f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa @Override 1780f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public void onPrepareOptionsMenu(Menu menu) { 1790f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (mSortedByTimezone) { 1800f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.findItem(MENU_TIMEZONE).setVisible(false); 1810f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.findItem(MENU_ALPHABETICAL).setVisible(true); 1820f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } else { 1830f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.findItem(MENU_TIMEZONE).setVisible(true); 1840f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa menu.findItem(MENU_ALPHABETICAL).setVisible(false); 1850f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 186afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 187afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project 188afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 1890f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public boolean onOptionsItemSelected(MenuItem item) { 1900f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa switch (item.getItemId()) { 1910f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 1920f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa case MENU_TIMEZONE: 1930f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa setSorting(true); 1940f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return true; 1950f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 1960f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa case MENU_ALPHABETICAL: 1970f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa setSorting(false); 1980f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return true; 1990f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2000f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa default: 2010f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return false; 2020f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2030f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2040f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2050f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public void setZoneSelectionListener(ZoneSelectionListener listener) { 2060f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa mListener = listener; 2070f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2080f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2092571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private void setSorting(boolean sortByTimezone) { 2102571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final SimpleAdapter adapter = 2112571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa sortByTimezone ? mTimezoneSortedAdapter : mAlphabeticalAdapter; 2122571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa setListAdapter(adapter); 2132571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa mSortedByTimezone = sortByTimezone; 2142571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final int defaultIndex = getTimeZoneIndex(adapter, TimeZone.getDefault()); 2152571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa if (defaultIndex >= 0) { 2162571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa setSelection(defaultIndex); 2172571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa } 2180f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2190f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2202571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static List<HashMap<String, Object>> getZones(Context context) { 2212571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final List<HashMap<String, Object>> myData = new ArrayList<HashMap<String, Object>>(); 2222571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final long date = Calendar.getInstance().getTimeInMillis(); 2230f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa try { 2242571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa XmlResourceParser xrp = context.getResources().getXml(R.xml.timezones); 2250f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa while (xrp.next() != XmlResourceParser.START_TAG) 2260f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa continue; 2270f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa xrp.next(); 2280f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa while (xrp.getEventType() != XmlResourceParser.END_TAG) { 2290f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa while (xrp.getEventType() != XmlResourceParser.START_TAG) { 2300f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) { 2310f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return myData; 2320f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2330f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa xrp.next(); 2340f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2350f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (xrp.getName().equals(XMLTAG_TIMEZONE)) { 2360f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa String id = xrp.getAttributeValue(0); 2370f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa String displayName = xrp.nextText(); 2380f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa addItem(myData, id, displayName, date); 2390f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2400f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa while (xrp.getEventType() != XmlResourceParser.END_TAG) { 2410f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa xrp.next(); 2420f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2430f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa xrp.next(); 2440f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2450f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa xrp.close(); 2460f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } catch (XmlPullParserException xppe) { 2470f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa Log.e(TAG, "Ill-formatted timezones.xml file"); 2480f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } catch (java.io.IOException ioe) { 2490f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa Log.e(TAG, "Unable to read timezones.xml file"); 2500f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2510f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2520f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return myData; 2530f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2540f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2552571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static void addItem( 2562571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa List<HashMap<String, Object>> myData, String id, String displayName, long date) { 2572571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final HashMap<String, Object> map = new HashMap<String, Object>(); 2580f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa map.put(KEY_ID, id); 2590f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa map.put(KEY_DISPLAYNAME, displayName); 2602571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final TimeZone tz = TimeZone.getTimeZone(id); 2612571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final int offset = tz.getOffset(date); 2622571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final int p = Math.abs(offset); 2632571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final StringBuilder name = new StringBuilder(); 2640f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa name.append("GMT"); 2650f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2660f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (offset < 0) { 2670f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa name.append('-'); 2680f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } else { 2690f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa name.append('+'); 2700f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2710f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2720f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa name.append(p / (HOURS_1)); 2730f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa name.append(':'); 2740f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2750f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa int min = p / 60000; 2760f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa min %= 60; 2770f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2780f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (min < 10) { 2790f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa name.append('0'); 2800f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 2810f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa name.append(min); 2820f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2830f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa map.put(KEY_GMT, name.toString()); 2840f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa map.put(KEY_OFFSET, offset); 2850f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 2860f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa myData.add(map); 287afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 2880f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 289afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project @Override 2902571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public void onListItemClick(ListView listView, View v, int position, long id) { 2912571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final Map<?, ?> map = (Map<?, ?>)listView.getItemAtPosition(position); 2922571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final String tzId = (String) map.get(KEY_ID); 2932571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa 2940f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa // Update the system timezone value 2950f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa final Activity activity = getActivity(); 2962571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa final AlarmManager alarm = (AlarmManager) activity.getSystemService(Context.ALARM_SERVICE); 29771cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa alarm.setTimeZone(tzId); 29871cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa final TimeZone tz = TimeZone.getTimeZone(tzId); 2990f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (mListener != null) { 30071cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa mListener.onZoneSelected(tz); 30171cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa } else { 30271cc548f7ee51ff77a2c1dfb5da7a3f7b6c55fd5Daisuke Miyakawa getActivity().onBackPressed(); 3030f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3040f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3050f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3062571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa private static class MyComparator implements Comparator<HashMap<?, ?>> { 3070f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private String mSortingKey; 3080f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3090f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public MyComparator(String sortingKey) { 3100f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa mSortingKey = sortingKey; 3110f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3120f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3130f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa public void setSortingKey(String sortingKey) { 3140f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa mSortingKey = sortingKey; 315afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project } 3160f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3172571f0dcb1cc96b7220687aff6fcddc623b57c3cDaisuke Miyakawa public int compare(HashMap<?, ?> map1, HashMap<?, ?> map2) { 3180f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa Object value1 = map1.get(mSortingKey); 3190f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa Object value2 = map2.get(mSortingKey); 3200f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3210f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa /* 3220f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * This should never happen, but just in-case, put non-comparable 3230f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa * items at the end. 3240f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa */ 3250f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa if (!isComparable(value1)) { 3260f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return isComparable(value2) ? 1 : 0; 3270f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } else if (!isComparable(value2)) { 3280f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return -1; 3290f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3300f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3310f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return ((Comparable) value1).compareTo(value2); 3320f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3330f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa 3340f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa private boolean isComparable(Object value) { 3350f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa return (value != null) && (value instanceof Comparable); 3360f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 3370f4f2f3a81f2a6d7100b4cff0d8de062cb2bc8f6Daisuke Miyakawa } 338afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project} 339