• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.deskclock.AnalogClock;
29 import com.android.deskclock.DigitalClock;
30 import com.android.deskclock.R;
31 import com.android.deskclock.SettingsActivity;
32 import com.android.deskclock.Utils;
33 
34 import java.text.Collator;
35 import java.util.Arrays;
36 import java.util.Calendar;
37 import java.util.Comparator;
38 import java.util.Date;
39 import java.util.HashMap;
40 import java.util.Locale;
41 import java.util.TimeZone;
42 
43 public class WorldClockAdapter extends BaseAdapter {
44     protected Object [] mCitiesList;
45     private final LayoutInflater mInflater;
46     private final Context mContext;
47     private String mClockStyle;
48     private final Collator mCollator = Collator.getInstance();
49     protected HashMap<String, CityObj> mCitiesDb = new HashMap<String, CityObj>();
50 
WorldClockAdapter(Context context)51     public WorldClockAdapter(Context context) {
52         super();
53         mContext = context;
54         loadData(context);
55         loadCitiesDb(context);
56         mInflater = LayoutInflater.from(context);
57     }
58 
reloadData(Context context)59     public void reloadData(Context context) {
60         loadData(context);
61         notifyDataSetChanged();
62     }
63 
loadData(Context context)64     public void loadData(Context context) {
65         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
66         mClockStyle = prefs.getString(SettingsActivity.KEY_CLOCK_STYLE,
67                 mContext.getResources().getString(R.string.default_clock_style));
68         mCitiesList = Cities.readCitiesFromSharedPrefs(prefs).values().toArray();
69         sortList();
70         mCitiesList = addHomeCity();
71     }
72 
loadCitiesDb(Context context)73     public void loadCitiesDb(Context context) {
74         mCitiesDb.clear();
75         // Read the cities DB so that the names and timezones will be taken from the DB
76         // and not from the selected list so that change of locale or changes in the DB will
77         // be reflected.
78         CityObj[] cities = Utils.loadCitiesDataBase(context);
79         if (cities != null) {
80             for (int i = 0; i < cities.length; i ++) {
81                 mCitiesDb.put(cities[i].mCityId, cities [i]);
82             }
83         }
84     }
85 
86     /***
87      * Adds the home city as the first item of the adapter if the feature is on and the device time
88      * zone is different from the home time zone that was set by the user.
89      * return the list of cities.
90      */
addHomeCity()91     private Object[] addHomeCity() {
92         if (needHomeCity()) {
93             SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mContext);
94             String homeTZ = sharedPref.getString(SettingsActivity.KEY_HOME_TZ, "");
95             CityObj c = new CityObj(
96                     mContext.getResources().getString(R.string.home_label), homeTZ, null);
97             Object[] temp = new Object[mCitiesList.length + 1];
98             temp[0] = c;
99             for (int i = 0; i < mCitiesList.length; i++) {
100                 temp[i + 1] = mCitiesList[i];
101             }
102             return temp;
103         } else {
104             return mCitiesList;
105         }
106     }
107 
needHomeCity()108     public boolean needHomeCity() {
109         SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(mContext);
110         if (sharedPref.getBoolean(SettingsActivity.KEY_AUTO_HOME_CLOCK, false)) {
111             String homeTZ = sharedPref.getString(
112                     SettingsActivity.KEY_HOME_TZ, TimeZone.getDefault().getID());
113             final Date now = new Date();
114             return TimeZone.getTimeZone(homeTZ).getOffset(now.getTime())
115                     != TimeZone.getDefault().getOffset(now.getTime());
116         } else {
117             return false;
118         }
119     }
120 
hasHomeCity()121     public boolean hasHomeCity() {
122         return (mCitiesList != null) && mCitiesList.length > 0
123                 && ((CityObj) mCitiesList[0]).mCityId == null;
124     }
125 
sortList()126     private void sortList() {
127         final Date now = new Date();
128 
129         // Sort by the Offset from GMT taking DST into account
130         // and if the same sort by City Name
131         Arrays.sort(mCitiesList, new Comparator<Object>() {
132             private int safeCityNameCompare(CityObj city1, CityObj city2) {
133                 if (city1.mCityName == null && city2.mCityName == null) {
134                     return 0;
135                 } else if (city1.mCityName == null) {
136                     return -1;
137                 } else if (city2.mCityName == null) {
138                     return 1;
139                 } else {
140                     return mCollator.compare(city1.mCityName, city2.mCityName);
141                 }
142             }
143 
144             @Override
145             public int compare(Object object1, Object object2) {
146                 CityObj city1 = (CityObj) object1;
147                 CityObj city2 = (CityObj) object2;
148                 if (city1.mTimeZone == null && city2.mTimeZone == null) {
149                     return safeCityNameCompare(city1, city2);
150                 } else if (city1.mTimeZone == null) {
151                     return -1;
152                 } else if (city2.mTimeZone == null) {
153                     return 1;
154                 }
155 
156                 int gmOffset1 = TimeZone.getTimeZone(city1.mTimeZone).getOffset(now.getTime());
157                 int gmOffset2 = TimeZone.getTimeZone(city2.mTimeZone).getOffset(now.getTime());
158                 if (gmOffset1 == gmOffset2) {
159                     return safeCityNameCompare(city1, city2);
160                 } else {
161                     return gmOffset1 - gmOffset2;
162                 }
163             }
164         });
165     }
166 
167     @Override
getCount()168     public int getCount() {
169         // Each item in the list holds 1 or 2 clocks
170         return (mCitiesList.length  + 1)/2;
171     }
172 
173     @Override
getItem(int p)174     public Object getItem(int p) {
175         return null;
176     }
177 
178     @Override
getItemId(int p)179     public long getItemId(int p) {
180         return p;
181     }
182 
183     @Override
isEnabled(int p)184     public boolean isEnabled(int p) {
185         return false;
186     }
187 
188     @Override
getView(int position, View view, ViewGroup parent)189     public View getView(int position, View view, ViewGroup parent) {
190         // Index in cities list
191         int index = position * 2;
192         if (index < 0 || index >= mCitiesList.length) {
193             return null;
194         }
195 
196         if (view == null) {
197             view = mInflater.inflate(R.layout.world_clock_list_item, parent, false);
198         }
199         // The world clock list item can hold two world clocks
200         View rightClock = view.findViewById(R.id.city_right);
201         updateView(view.findViewById(R.id.city_left), (CityObj)mCitiesList[index]);
202         if (index + 1 < mCitiesList.length) {
203             rightClock.setVisibility(View.VISIBLE);
204             updateView(rightClock, (CityObj)mCitiesList[index + 1]);
205         } else {
206             // To make sure the spacing is right , make sure that the right clock style is selected
207             // even if the clock is invisible.
208             DigitalClock dclock = (DigitalClock)(rightClock.findViewById(R.id.digital_clock));
209             AnalogClock aclock = (AnalogClock)(rightClock.findViewById(R.id.analog_clock));
210             if (mClockStyle.equals("analog")) {
211                 dclock.setVisibility(View.GONE);
212                 aclock.setVisibility(View.INVISIBLE);
213             } else {
214                 dclock.setVisibility(View.INVISIBLE);
215                 aclock.setVisibility(View.GONE);
216             }
217             rightClock.setVisibility(View.INVISIBLE);
218         }
219 
220         return view;
221     }
222 
updateView(View clock, CityObj cityObj)223     private void updateView(View clock, CityObj cityObj) {
224         View nameLayout= clock.findViewById(R.id.city_name_layout);
225         TextView name = (TextView)(nameLayout.findViewById(R.id.city_name));
226         TextView dayOfWeek = (TextView)(nameLayout.findViewById(R.id.city_day));
227         DigitalClock dclock = (DigitalClock)(clock.findViewById(R.id.digital_clock));
228         AnalogClock aclock = (AnalogClock)(clock.findViewById(R.id.analog_clock));
229 
230         if (mClockStyle.equals("analog")) {
231             dclock.setVisibility(View.GONE);
232             aclock.setVisibility(View.VISIBLE);
233             aclock.setTimeZone(cityObj.mTimeZone);
234             aclock.enableSeconds(false);
235         } else {
236             dclock.setVisibility(View.VISIBLE);
237             aclock.setVisibility(View.GONE);
238             dclock.setTimeZone(cityObj.mTimeZone);
239         }
240         CityObj cityInDb = mCitiesDb.get(cityObj.mCityId);
241         // Home city or city not in DB , use data from the save selected cities list
242         name.setText(Utils.getCityName(cityObj, cityInDb));
243 
244         final Calendar now = Calendar.getInstance();
245         now.setTimeZone(TimeZone.getDefault());
246         int myDayOfWeek = now.get(Calendar.DAY_OF_WEEK);
247         // Get timezone from cities DB if available
248         String cityTZ = (cityInDb != null) ? cityInDb.mTimeZone : cityObj.mTimeZone;
249         now.setTimeZone(TimeZone.getTimeZone(cityTZ));
250         int cityDayOfWeek = now.get(Calendar.DAY_OF_WEEK);
251         if (myDayOfWeek != cityDayOfWeek) {
252             dayOfWeek.setText(mContext.getString(R.string.world_day_of_week_label,
253                     now.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.SHORT, Locale.getDefault())));
254             dayOfWeek.setVisibility(View.VISIBLE);
255         } else {
256             dayOfWeek.setVisibility(View.GONE);
257         }
258     }
259 }
260