1 /* 2 * Copyright (C) 2018 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.settings.datetime.timezone; 18 19 import android.app.Activity; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.res.Resources; 23 import android.icu.text.DateFormat; 24 import android.icu.text.SimpleDateFormat; 25 import android.icu.util.Calendar; 26 import android.support.annotation.Nullable; 27 28 import com.android.settings.R; 29 import com.android.settings.datetime.timezone.model.TimeZoneData; 30 31 import java.util.ArrayList; 32 import java.util.Date; 33 import java.util.List; 34 import java.util.Locale; 35 36 /** 37 * Render a list of {@class TimeZoneInfo} into the list view in {@class BaseTimeZonePicker} 38 */ 39 public abstract class BaseTimeZoneInfoPicker extends BaseTimeZonePicker { 40 protected static final String TAG = "RegionZoneSearchPicker"; 41 protected ZoneAdapter mAdapter; 42 BaseTimeZoneInfoPicker(int titleResId, int searchHintResId, boolean searchEnabled, boolean defaultExpandSearch)43 protected BaseTimeZoneInfoPicker(int titleResId, int searchHintResId, 44 boolean searchEnabled, boolean defaultExpandSearch) { 45 super(titleResId, searchHintResId, searchEnabled, defaultExpandSearch); 46 } 47 48 @Override createAdapter(TimeZoneData timeZoneData)49 protected BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData) { 50 mAdapter = new ZoneAdapter(getContext(), getAllTimeZoneInfos(timeZoneData), 51 this::onListItemClick, getLocale(), getHeaderText()); 52 return mAdapter; 53 } 54 55 /** 56 * @return the text shown in the header, or null to show no header. 57 */ getHeaderText()58 protected @Nullable CharSequence getHeaderText() { 59 return null; 60 } 61 onListItemClick(TimeZoneInfoItem item)62 private void onListItemClick(TimeZoneInfoItem item) { 63 final TimeZoneInfo timeZoneInfo = item.mTimeZoneInfo; 64 getActivity().setResult(Activity.RESULT_OK, prepareResultData(timeZoneInfo)); 65 getActivity().finish(); 66 } 67 prepareResultData(TimeZoneInfo selectedTimeZoneInfo)68 protected Intent prepareResultData(TimeZoneInfo selectedTimeZoneInfo) { 69 return new Intent().putExtra(EXTRA_RESULT_TIME_ZONE_ID, selectedTimeZoneInfo.getId()); 70 } 71 getAllTimeZoneInfos(TimeZoneData timeZoneData)72 public abstract List<TimeZoneInfo> getAllTimeZoneInfos(TimeZoneData timeZoneData); 73 74 protected static class ZoneAdapter extends BaseTimeZoneAdapter<TimeZoneInfoItem> { 75 ZoneAdapter(Context context, List<TimeZoneInfo> timeZones, OnListItemClickListener<TimeZoneInfoItem> onListItemClickListener, Locale locale, CharSequence headerText)76 public ZoneAdapter(Context context, List<TimeZoneInfo> timeZones, 77 OnListItemClickListener<TimeZoneInfoItem> onListItemClickListener, Locale locale, 78 CharSequence headerText) { 79 super(createTimeZoneInfoItems(context, timeZones, locale), 80 onListItemClickListener, locale, true /* showItemSummary */, 81 headerText /* headerText */); 82 } 83 createTimeZoneInfoItems(Context context, List<TimeZoneInfo> timeZones, Locale locale)84 private static List<TimeZoneInfoItem> createTimeZoneInfoItems(Context context, 85 List<TimeZoneInfo> timeZones, Locale locale) { 86 final DateFormat currentTimeFormat = new SimpleDateFormat( 87 android.text.format.DateFormat.getTimeFormatString(context), locale); 88 final ArrayList<TimeZoneInfoItem> results = new ArrayList<>(timeZones.size()); 89 final Resources resources = context.getResources(); 90 long i = 0; 91 for (TimeZoneInfo timeZone : timeZones) { 92 results.add(new TimeZoneInfoItem(i++, timeZone, resources, currentTimeFormat)); 93 } 94 return results; 95 } 96 } 97 98 private static class TimeZoneInfoItem implements BaseTimeZoneAdapter.AdapterItem { 99 private final long mItemId; 100 private final TimeZoneInfo mTimeZoneInfo; 101 private final Resources mResources; 102 private final DateFormat mTimeFormat; 103 private final String mTitle; 104 private final String[] mSearchKeys; 105 TimeZoneInfoItem(long itemId, TimeZoneInfo timeZoneInfo, Resources resources, DateFormat timeFormat)106 private TimeZoneInfoItem(long itemId, TimeZoneInfo timeZoneInfo, Resources resources, 107 DateFormat timeFormat) { 108 mItemId = itemId; 109 mTimeZoneInfo = timeZoneInfo; 110 mResources = resources; 111 mTimeFormat = timeFormat; 112 mTitle = createTitle(timeZoneInfo); 113 mSearchKeys = new String[] { mTitle }; 114 } 115 createTitle(TimeZoneInfo timeZoneInfo)116 private static String createTitle(TimeZoneInfo timeZoneInfo) { 117 String name = timeZoneInfo.getExemplarLocation(); 118 if (name == null) { 119 name = timeZoneInfo.getGenericName(); 120 } 121 if (name == null && timeZoneInfo.getTimeZone().inDaylightTime(new Date())) { 122 name = timeZoneInfo.getDaylightName(); 123 } 124 if (name == null) { 125 name = timeZoneInfo.getStandardName(); 126 } 127 if (name == null) { 128 name = String.valueOf(timeZoneInfo.getGmtOffset()); 129 } 130 return name; 131 } 132 133 @Override getTitle()134 public CharSequence getTitle() { 135 return mTitle; 136 } 137 138 @Override getSummary()139 public CharSequence getSummary() { 140 String name = mTimeZoneInfo.getGenericName(); 141 if (name == null) { 142 if (mTimeZoneInfo.getTimeZone().inDaylightTime(new Date())) { 143 name = mTimeZoneInfo.getDaylightName(); 144 } else { 145 name = mTimeZoneInfo.getStandardName(); 146 } 147 } 148 149 // Ignore name / GMT offset if the title shows the same information 150 if (name == null || name.equals(mTitle)) { 151 CharSequence gmtOffset = mTimeZoneInfo.getGmtOffset(); 152 return gmtOffset == null || gmtOffset.toString().equals(mTitle) ? "" : gmtOffset; 153 } else { 154 return SpannableUtil.getResourcesText(mResources, 155 R.string.zone_info_offset_and_name, mTimeZoneInfo.getGmtOffset(), name); 156 } 157 } 158 159 @Override getIconText()160 public String getIconText() { 161 return null; 162 } 163 164 @Override getCurrentTime()165 public String getCurrentTime() { 166 return mTimeFormat.format(Calendar.getInstance(mTimeZoneInfo.getTimeZone())); 167 } 168 169 @Override getItemId()170 public long getItemId() { 171 return mItemId; 172 } 173 174 @Override getSearchKeys()175 public String[] getSearchKeys() { 176 return mSearchKeys; 177 } 178 } 179 } 180