Home | History | Annotate | Download | only in worldclock
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.deskclock.worldclock;
     18 
     19 import android.content.Context;
     20 import android.content.SharedPreferences;
     21 import android.preference.PreferenceManager;
     22 import android.view.LayoutInflater;
     23 import android.view.View;
     24 import android.view.ViewGroup;
     25 import android.widget.BaseAdapter;
     26 import android.widget.TextView;
     27 
     28 import java.text.Collator;
     29 import java.util.Arrays;
     30 import java.util.Calendar;
     31 import java.util.Comparator;
     32 import java.util.Date;
     33 import java.util.Locale;
     34 import java.util.TimeZone;
     35 
     36 import com.android.deskclock.AnalogClock;
     37 import com.android.deskclock.DigitalClock;
     38 import com.android.deskclock.R;
     39 import com.android.deskclock.SettingsActivity;
     40 
     41 public class WorldClockAdapter extends BaseAdapter {
     42     protected Object [] mCitiesList;
     43     private final LayoutInflater mInflater;
     44     private final Context mContext;
     45     private String mClockStyle;
     46     private final Collator mCollator = Collator.getInstance();
     47 
     48     public WorldClockAdapter(Context context) {
     49         super();
     50         mContext = context;
     51         loadData(context);
     52         mInflater = LayoutInflater.from(context);
     53     }
     54 
     55     public void reloadData(Context context) {
     56         loadData(context);
     57         notifyDataSetChanged();
     58     }
     59 
     60     public void loadData(Context context) {
     61         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
     62         mClockStyle = prefs.getString(SettingsActivity.KEY_CLOCK_STYLE,
     63                 mContext.getResources().getString(R.string.default_clock_style));
     64         mCitiesList = Cities.readCitiesFromSharedPrefs(prefs).values().toArray();
     65         sortList();
     66         mCitiesList = addHomeCity();
     67     }
     68 
     69     /***
     70      * Adds the home city as the first item of the adapter if the feature is on and the device time
     71      * zone is different from the home time zone that was set by the user.
     72      * return the list of cities.
     73      */
     74     private Object[] addHomeCity() {
     75         if (needHomeCity()) {
     76             SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mContext);
     77             String homeTZ = sharedPref.getString(SettingsActivity.KEY_HOME_TZ, "");
     78             CityObj c = new CityObj(
     79                     mContext.getResources().getString(R.string.home_label), homeTZ, null);
     80             Object[] temp = new Object[mCitiesList.length + 1];
     81             temp[0] = c;
     82             for (int i = 0; i < mCitiesList.length; i++) {
     83                 temp[i + 1] = mCitiesList[i];
     84             }
     85             return temp;
     86         } else {
     87             return mCitiesList;
     88         }
     89     }
     90 
     91     public boolean needHomeCity() {
     92         SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mContext);
     93         if (sharedPref.getBoolean(SettingsActivity.KEY_AUTO_HOME_CLOCK, false)) {
     94             String homeTZ = sharedPref.getString(
     95                     SettingsActivity.KEY_HOME_TZ, TimeZone.getDefault().getID());
     96             final Date now = new Date();
     97             return TimeZone.getTimeZone(homeTZ).getOffset(now.getTime())
     98                     != TimeZone.getDefault().getOffset(now.getTime());
     99         } else {
    100             return false;
    101         }
    102     }
    103 
    104     public boolean hasHomeCity() {
    105         return (mCitiesList != null) && mCitiesList.length > 0
    106                 && ((CityObj) mCitiesList[0]).mCityId == null;
    107     }
    108 
    109     private void sortList() {
    110         final Date now = new Date();
    111 
    112         // Sort by the Offset from GMT taking DST into account
    113         // and if the same sort by City Name
    114         Arrays.sort(mCitiesList, new Comparator<Object>() {
    115             private int safeCityNameCompare(CityObj city1, CityObj city2) {
    116                 if (city1.mCityName == null && city2.mCityName == null) {
    117                     return 0;
    118                 } else if (city1.mCityName == null) {
    119                     return -1;
    120                 } else if (city2.mCityName == null) {
    121                     return 1;
    122                 } else {
    123                     return mCollator.compare(city1.mCityName, city2.mCityName);
    124                 }
    125             }
    126 
    127             @Override
    128             public int compare(Object object1, Object object2) {
    129                 CityObj city1 = (CityObj) object1;
    130                 CityObj city2 = (CityObj) object2;
    131                 if (city1.mTimeZone == null && city2.mTimeZone == null) {
    132                     return safeCityNameCompare(city1, city2);
    133                 } else if (city1.mTimeZone == null) {
    134                     return -1;
    135                 } else if (city2.mTimeZone == null) {
    136                     return 1;
    137                 }
    138 
    139                 int gmOffset1 = TimeZone.getTimeZone(city1.mTimeZone).getOffset(now.getTime());
    140                 int gmOffset2 = TimeZone.getTimeZone(city2.mTimeZone).getOffset(now.getTime());
    141                 if (gmOffset1 == gmOffset2) {
    142                     return safeCityNameCompare(city1, city2);
    143                 } else {
    144                     return gmOffset1 - gmOffset2;
    145                 }
    146             }
    147         });
    148     }
    149 
    150     @Override
    151     public int getCount() {
    152         // Each item in the list holds 1 or 2 clocks
    153         return (mCitiesList.length  + 1)/2;
    154     }
    155 
    156     @Override
    157     public Object getItem(int p) {
    158         return null;
    159     }
    160 
    161     @Override
    162     public long getItemId(int p) {
    163         return p;
    164     }
    165 
    166     @Override
    167     public boolean isEnabled(int p) {
    168         return false;
    169     }
    170 
    171     @Override
    172     public View getView(int position, View view, ViewGroup parent) {
    173         // Index in cities list
    174         int index = position * 2;
    175         if (index < 0 || index >= mCitiesList.length) {
    176             return null;
    177         }
    178 
    179         if (view == null) {
    180             view = mInflater.inflate(R.layout.world_clock_list_item, parent, false);
    181         }
    182         // The world clock list item can hold two world clocks
    183         View rightClock = view.findViewById(R.id.city_right);
    184         updateView(view.findViewById(R.id.city_left), (CityObj)mCitiesList[index]);
    185         if (index + 1 < mCitiesList.length) {
    186             rightClock.setVisibility(View.VISIBLE);
    187             updateView(rightClock, (CityObj)mCitiesList[index + 1]);
    188         } else {
    189             // To make sure the spacing is right , make sure that the right clock style is selected
    190             // even if the clock is invisible.
    191             DigitalClock dclock = (DigitalClock)(rightClock.findViewById(R.id.digital_clock));
    192             AnalogClock aclock = (AnalogClock)(rightClock.findViewById(R.id.analog_clock));
    193             if (mClockStyle.equals("analog")) {
    194                 dclock.setVisibility(View.GONE);
    195                 aclock.setVisibility(View.INVISIBLE);
    196             } else {
    197                 dclock.setVisibility(View.INVISIBLE);
    198                 aclock.setVisibility(View.GONE);
    199             }
    200             rightClock.setVisibility(View.INVISIBLE);
    201         }
    202 
    203         return view;
    204     }
    205 
    206     private void updateView(View clock, CityObj cityObj) {
    207         View nameLayout= clock.findViewById(R.id.city_name_layout);
    208         TextView name = (TextView)(nameLayout.findViewById(R.id.city_name));
    209         TextView dayOfWeek = (TextView)(nameLayout.findViewById(R.id.city_day));
    210         DigitalClock dclock = (DigitalClock)(clock.findViewById(R.id.digital_clock));
    211         AnalogClock aclock = (AnalogClock)(clock.findViewById(R.id.analog_clock));
    212 
    213         if (mClockStyle.equals("analog")) {
    214             dclock.setVisibility(View.GONE);
    215             aclock.setVisibility(View.VISIBLE);
    216             aclock.setTimeZone(cityObj.mTimeZone);
    217             aclock.enableSeconds(false);
    218         } else {
    219             dclock.setVisibility(View.VISIBLE);
    220             aclock.setVisibility(View.GONE);
    221             dclock.setTimeZone(cityObj.mTimeZone);
    222         }
    223         name.setText(cityObj.mCityName);
    224         final Calendar now = Calendar.getInstance();
    225         now.setTimeZone(TimeZone.getDefault());
    226         int myDayOfWeek = now.get(Calendar.DAY_OF_WEEK);
    227         now.setTimeZone(TimeZone.getTimeZone(cityObj.mTimeZone));
    228         int cityDayOfWeek = now.get(Calendar.DAY_OF_WEEK);
    229         if (myDayOfWeek != cityDayOfWeek) {
    230             dayOfWeek.setText(mContext.getString(R.string.world_day_of_week_label,
    231                     now.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.getDefault())));
    232             dayOfWeek.setVisibility(View.VISIBLE);
    233         } else {
    234             dayOfWeek.setVisibility(View.GONE);
    235         }
    236     }
    237 }
    238