diff options
-rw-r--r-- | vdrmanager/res/drawable-hdpi/ic_menu_3d_globe.png | bin | 0 -> 3810 bytes | |||
-rw-r--r-- | vdrmanager/res/drawable-mdpi/ic_menu_3d_globe.png | bin | 0 -> 2376 bytes | |||
-rw-r--r-- | vdrmanager/res/drawable-xhdpi/ic_menu_3d_globe.png | bin | 0 -> 5986 bytes | |||
-rw-r--r-- | vdrmanager/res/drawable/ic_menu_3d_globe.png | bin | 0 -> 2376 bytes | |||
-rw-r--r-- | vdrmanager/res/xml/timezones.xml | 87 | ||||
-rw-r--r-- | vdrmanager/src/de/bjusystems/vdrmanager/ZonePicker.java | 336 |
6 files changed, 423 insertions, 0 deletions
diff --git a/vdrmanager/res/drawable-hdpi/ic_menu_3d_globe.png b/vdrmanager/res/drawable-hdpi/ic_menu_3d_globe.png Binary files differnew file mode 100644 index 0000000..1b55f09 --- /dev/null +++ b/vdrmanager/res/drawable-hdpi/ic_menu_3d_globe.png diff --git a/vdrmanager/res/drawable-mdpi/ic_menu_3d_globe.png b/vdrmanager/res/drawable-mdpi/ic_menu_3d_globe.png Binary files differnew file mode 100644 index 0000000..6755d5e --- /dev/null +++ b/vdrmanager/res/drawable-mdpi/ic_menu_3d_globe.png diff --git a/vdrmanager/res/drawable-xhdpi/ic_menu_3d_globe.png b/vdrmanager/res/drawable-xhdpi/ic_menu_3d_globe.png Binary files differnew file mode 100644 index 0000000..1fda0a2 --- /dev/null +++ b/vdrmanager/res/drawable-xhdpi/ic_menu_3d_globe.png diff --git a/vdrmanager/res/drawable/ic_menu_3d_globe.png b/vdrmanager/res/drawable/ic_menu_3d_globe.png Binary files differnew file mode 100644 index 0000000..6755d5e --- /dev/null +++ b/vdrmanager/res/drawable/ic_menu_3d_globe.png diff --git a/vdrmanager/res/xml/timezones.xml b/vdrmanager/res/xml/timezones.xml new file mode 100644 index 0000000..a66faf8 --- /dev/null +++ b/vdrmanager/res/xml/timezones.xml @@ -0,0 +1,87 @@ +<timezones> + <timezone id="Pacific/Majuro">Marshall Islands</timezone> + <timezone id="Pacific/Midway">Midway Island</timezone> + <timezone id="Pacific/Honolulu">Hawaii</timezone> + <timezone id="America/Anchorage">Alaska</timezone> + <timezone id="America/Los_Angeles">Pacific Time</timezone> + <timezone id="America/Tijuana">Tijuana</timezone> + <timezone id="America/Phoenix">Arizona</timezone> + <timezone id="America/Chihuahua">Chihuahua</timezone> + <timezone id="America/Denver">Mountain Time</timezone> + <timezone id="America/Costa_Rica">Central America</timezone> + <timezone id="America/Chicago">Central Time</timezone> + <timezone id="America/Mexico_City">Mexico City</timezone> + <timezone id="America/Regina">Saskatchewan</timezone> + <timezone id="America/Bogota">Bogota</timezone> + <timezone id="America/New_York">Eastern Time</timezone> + <timezone id="America/Caracas">Venezuela</timezone> + <timezone id="America/Barbados">Atlantic Time (Barbados)</timezone> + <timezone id="America/Halifax">Atlantic Time (Canada)</timezone> + <timezone id="America/Manaus">Manaus</timezone> + <timezone id="America/Santiago">Santiago</timezone> + <timezone id="America/St_Johns">Newfoundland</timezone> + <timezone id="America/Sao_Paulo">Brasilia</timezone> + <timezone id="America/Argentina/Buenos_Aires">Buenos Aires</timezone> + <timezone id="America/Godthab">Greenland</timezone> + <timezone id="America/Montevideo">Montevideo</timezone> + <timezone id="Atlantic/South_Georgia">Mid-Atlantic</timezone> + <timezone id="Atlantic/Azores">Azores</timezone> + <timezone id="Atlantic/Cape_Verde">Cape Verde Islands</timezone> + <timezone id="Africa/Casablanca">Casablanca</timezone> + <timezone id="Europe/London">London, Dublin</timezone> + <timezone id="Europe/Berlin">Berlin</timezone> + <timezone id="Europe/Amsterdam">Amsterdam</timezone> + <timezone id="Europe/Belgrade">Belgrade</timezone> + <timezone id="Europe/Brussels">Brussels</timezone> + <timezone id="Europe/Sarajevo">Sarajevo</timezone> + <timezone id="Africa/Windhoek">Windhoek</timezone> + <timezone id="Africa/Brazzaville">W. Africa Time</timezone> + <timezone id="Asia/Amman">Amman, Jordan</timezone> + <timezone id="Europe/Athens">Athens, Istanbul</timezone> + <timezone id="Asia/Beirut">Beirut, Lebanon</timezone> + <timezone id="Africa/Cairo">Cairo</timezone> + <timezone id="Europe/Helsinki">Helsinki</timezone> + <timezone id="Asia/Jerusalem">Jerusalem</timezone> + <timezone id="Europe/Minsk">Minsk</timezone> + <timezone id="Africa/Harare">Harare</timezone> + <timezone id="Asia/Baghdad">Baghdad</timezone> + <timezone id="Europe/Moscow">Moscow</timezone> + <timezone id="Asia/Kuwait">Kuwait</timezone> + <timezone id="Africa/Nairobi">Nairobi</timezone> + <timezone id="Asia/Tehran">Tehran</timezone> + <timezone id="Asia/Baku">Baku</timezone> + <timezone id="Asia/Tbilisi">Tbilisi</timezone> + <timezone id="Asia/Yerevan">Yerevan</timezone> + <timezone id="Asia/Dubai">Dubai</timezone> + <timezone id="Asia/Kabul">Kabul</timezone> + <timezone id="Asia/Karachi">Islamabad, Karachi</timezone> + <timezone id="Asia/Oral">Ural'sk</timezone> + <timezone id="Asia/Yekaterinburg">Yekaterinburg</timezone> + <timezone id="Asia/Calcutta">Kolkata</timezone> + <timezone id="Asia/Colombo">Sri Lanka</timezone> + <timezone id="Asia/Katmandu">Kathmandu</timezone> + <timezone id="Asia/Almaty">Astana</timezone> + <timezone id="Asia/Rangoon">Yangon</timezone> + <timezone id="Asia/Krasnoyarsk">Krasnoyarsk</timezone> + <timezone id="Asia/Bangkok">Bangkok</timezone> + <timezone id="Asia/Shanghai">Beijing</timezone> + <timezone id="Asia/Hong_Kong">Hong Kong</timezone> + <timezone id="Asia/Irkutsk">Irkutsk</timezone> + <timezone id="Asia/Kuala_Lumpur">Kuala Lumpur</timezone> + <timezone id="Australia/Perth">Perth</timezone> + <timezone id="Asia/Taipei">Taipei</timezone> + <timezone id="Asia/Seoul">Seoul</timezone> + <timezone id="Asia/Tokyo">Tokyo, Osaka</timezone> + <timezone id="Asia/Yakutsk">Yakutsk</timezone> + <timezone id="Australia/Adelaide">Adelaide</timezone> + <timezone id="Australia/Darwin">Darwin</timezone> + <timezone id="Australia/Brisbane">Brisbane</timezone> + <timezone id="Australia/Hobart">Hobart</timezone> + <timezone id="Australia/Sydney">Sydney, Canberra</timezone> + <timezone id="Asia/Vladivostok">Vladivostok</timezone> + <timezone id="Pacific/Guam">Guam</timezone> + <timezone id="Asia/Magadan">Magadan</timezone> + <timezone id="Pacific/Auckland">Auckland</timezone> + <timezone id="Pacific/Fiji">Fiji</timezone> + <timezone id="Pacific/Tongatapu">Tonga</timezone> +</timezones> diff --git a/vdrmanager/src/de/bjusystems/vdrmanager/ZonePicker.java b/vdrmanager/src/de/bjusystems/vdrmanager/ZonePicker.java new file mode 100644 index 0000000..3b1dfbc --- /dev/null +++ b/vdrmanager/src/de/bjusystems/vdrmanager/ZonePicker.java @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package de.bjusystems.vdrmanager; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; + +import org.xmlpull.v1.XmlPullParserException; + +import android.app.ListActivity; +import android.content.Context; +import android.content.Intent; +import android.content.res.XmlResourceParser; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ListView; +import android.widget.SimpleAdapter; + +/** + * The class displaying a list of time zones that match a filter string + * such as "Africa", "Europe", etc. Choosing an item from the list will set + * the time zone. Pressing Back without choosing from the list will not + * result in a change in the time zone setting. + */ +public class ZonePicker extends ListActivity { + private static final String TAG = "ZonePicker"; + + public static interface ZoneSelectionListener { + // You can add any argument if you really need it... + public void onZoneSelected(TimeZone tz); + } + + private static final String KEY_ID = "id"; // value: String + private static final String KEY_DISPLAYNAME = "name"; // value: String + private static final String KEY_GMT = "gmt"; // value: String + private static final String KEY_OFFSET = "offset"; // value: int (Integer) + private static final String XMLTAG_TIMEZONE = "timezone"; + + private static final int HOURS_1 = 60 * 60000; + + private static final int MENU_TIMEZONE = Menu.FIRST+1; + private static final int MENU_ALPHABETICAL = Menu.FIRST; + + private boolean mSortedByTimezone; + + private SimpleAdapter mTimezoneSortedAdapter; + private SimpleAdapter mAlphabeticalAdapter; + + private ZoneSelectionListener mListener; + + private String selectedTimeZone; + + /** + * Constructs an adapter with TimeZone list. Sorted by TimeZone in default. + * + * @param sortedByName use Name for sorting the list. + */ + public static SimpleAdapter constructTimezoneAdapter(Context context, + boolean sortedByName) { + return constructTimezoneAdapter(context, sortedByName, + android.R.layout.simple_list_item_2); + } + + /** + * Constructs an adapter with TimeZone list. Sorted by TimeZone in default. + * + * @param sortedByName use Name for sorting the list. + */ + public static SimpleAdapter constructTimezoneAdapter(Context context, + boolean sortedByName, int layoutId) { + final String[] from = new String[] {KEY_DISPLAYNAME, KEY_GMT}; + final int[] to = new int[] {android.R.id.text1, android.R.id.text2}; + + final String sortKey = (sortedByName ? KEY_DISPLAYNAME : KEY_OFFSET); + final MyComparator comparator = new MyComparator(sortKey); + final List<HashMap<String, Object>> sortedList = getZones(context); + Collections.sort(sortedList, comparator); + final SimpleAdapter adapter = new SimpleAdapter(context, + sortedList, + layoutId, + from, + to); + + return adapter; + } + + /** + * Searches {@link TimeZone} from the given {@link SimpleAdapter} object, and returns + * the index for the TimeZone. + * + * @param adapter SimpleAdapter constructed by + * {@link #constructTimezoneAdapter(Context, boolean)}. + * @param tz TimeZone to be searched. + * @return Index for the given TimeZone. -1 when there's no corresponding list item. + * returned. + */ + public static int getTimeZoneIndex(SimpleAdapter adapter, TimeZone tz) { + final String defaultId = tz.getID(); + final int listSize = adapter.getCount(); + for (int i = 0; i < listSize; i++) { + // Using HashMap<String, Object> induces unnecessary warning. + final HashMap<?,?> map = (HashMap<?,?>)adapter.getItem(i); + final String id = (String)map.get(KEY_ID); + if (defaultId.equals(id)) { + // If current timezone is in this list, move focus to it + return i; + } + } + return -1; + } + + /** + * @param item one of items in adapters. The adapter should be constructed by + * {@link #constructTimezoneAdapter(Context, boolean)}. + * @return TimeZone object corresponding to the item. + */ + public static TimeZone obtainTimeZoneFromItem(Object item) { + return TimeZone.getTimeZone((String)((Map<?, ?>)item).get(KEY_ID)); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + selectedTimeZone = getIntent().getStringExtra("current_tz"); + + mTimezoneSortedAdapter = constructTimezoneAdapter(this, false); + mAlphabeticalAdapter = constructTimezoneAdapter(this, true); + + // Sets the adapter + setSorting(true); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + menu.add(0, MENU_ALPHABETICAL, 0, R.string.zone_list_menu_sort_alphabetically) + .setIcon(android.R.drawable.ic_menu_sort_alphabetically); + menu.add(0, MENU_TIMEZONE, 0, R.string.zone_list_menu_sort_by_timezone) + .setIcon(R.drawable.ic_menu_3d_globe); + return true; + } + + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + if (mSortedByTimezone) { + menu.findItem(MENU_TIMEZONE).setVisible(false); + menu.findItem(MENU_ALPHABETICAL).setVisible(true); + } else { + menu.findItem(MENU_TIMEZONE).setVisible(true); + menu.findItem(MENU_ALPHABETICAL).setVisible(false); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + + case MENU_TIMEZONE: + setSorting(true); + return true; + + case MENU_ALPHABETICAL: + setSorting(false); + return true; + + default: + return false; + } + } + + public void setZoneSelectionListener(ZoneSelectionListener listener) { + mListener = listener; + } + + private void setSorting(boolean sortByTimezone) { + final SimpleAdapter adapter = + sortByTimezone ? mTimezoneSortedAdapter : mAlphabeticalAdapter; + setListAdapter(adapter); + mSortedByTimezone = sortByTimezone; + final int defaultIndex = getTimeZoneIndex(adapter, TimeZone.getDefault()); + if (defaultIndex >= 0) { + setSelection(defaultIndex); + } + } + + private static List<HashMap<String, Object>> getZones(Context context) { + final List<HashMap<String, Object>> myData = new ArrayList<HashMap<String, Object>>(); + final long date = Calendar.getInstance().getTimeInMillis(); + try { + XmlResourceParser xrp = context.getResources().getXml(R.xml.timezones); + while (xrp.next() != XmlResourceParser.START_TAG) + continue; + xrp.next(); + while (xrp.getEventType() != XmlResourceParser.END_TAG) { + while (xrp.getEventType() != XmlResourceParser.START_TAG) { + if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) { + return myData; + } + xrp.next(); + } + if (xrp.getName().equals(XMLTAG_TIMEZONE)) { + String id = xrp.getAttributeValue(0); + String displayName = xrp.nextText(); + addItem(myData, id, displayName, date); + } + while (xrp.getEventType() != XmlResourceParser.END_TAG) { + xrp.next(); + } + xrp.next(); + } + xrp.close(); + } catch (XmlPullParserException xppe) { + Log.e(TAG, "Ill-formatted timezones.xml file"); + } catch (java.io.IOException ioe) { + Log.e(TAG, "Unable to read timezones.xml file"); + } + + return myData; + } + + private static void addItem( + List<HashMap<String, Object>> myData, String id, String displayName, long date) { + final HashMap<String, Object> map = new HashMap<String, Object>(); + map.put(KEY_ID, id); + map.put(KEY_DISPLAYNAME, displayName); + final TimeZone tz = TimeZone.getTimeZone(id); + final int offset = tz.getOffset(date); + final int p = Math.abs(offset); + final StringBuilder name = new StringBuilder(); + name.append("GMT"); + + if (offset < 0) { + name.append('-'); + } else { + name.append('+'); + } + + name.append(p / (HOURS_1)); + name.append(':'); + + int min = p / 60000; + min %= 60; + + if (min < 10) { + name.append('0'); + } + name.append(min); + + map.put(KEY_GMT, name.toString()); + map.put(KEY_OFFSET, offset); + + myData.add(map); + } + + @Override + public void onListItemClick(ListView listView, View v, int position, long id) { + final Map<?, ?> map = (Map<?, ?>)listView.getItemAtPosition(position); + final String tzId = (String) map.get(KEY_ID); + + // Update the system timezone value + //final AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE); + //alarm.setTimeZone(tzId); + final TimeZone tz = TimeZone.getTimeZone(tzId); + //if (mListener != null) { + // mListener.onZoneSelected(tz); + //} else { + // onBackPressed(); + ///} + Intent returnIntent = new Intent(); + if(tz == null){ + setResult(RESULT_CANCELED, returnIntent); + } else { + returnIntent.putExtra("new_tz",tz.getID()); + setResult(RESULT_OK, returnIntent); + } + finish(); + } + + private static class MyComparator implements Comparator<HashMap<?, ?>> { + private String mSortingKey; + + public MyComparator(String sortingKey) { + mSortingKey = sortingKey; + } + + public void setSortingKey(String sortingKey) { + mSortingKey = sortingKey; + } + + public int compare(HashMap<?, ?> map1, HashMap<?, ?> map2) { + Object value1 = map1.get(mSortingKey); + Object value2 = map2.get(mSortingKey); + + /* + * This should never happen, but just in-case, put non-comparable + * items at the end. + */ + if (!isComparable(value1)) { + return isComparable(value2) ? 1 : 0; + } else if (!isComparable(value2)) { + return -1; + } + + return ((Comparable) value1).compareTo(value2); + } + + private boolean isComparable(Object value) { + return (value != null) && (value instanceof Comparable); + } + } +} |