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