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