Home | History | Annotate | Download | only in timezone
      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.Intent;
     21 import android.icu.text.Collator;
     22 import android.icu.text.LocaleDisplayNames;
     23 import android.os.Bundle;
     24 import android.support.annotation.VisibleForTesting;
     25 import android.util.Log;
     26 
     27 import com.android.internal.logging.nano.MetricsProto;
     28 import com.android.settings.R;
     29 import com.android.settings.core.SubSettingLauncher;
     30 import com.android.settings.datetime.timezone.BaseTimeZoneAdapter.AdapterItem;
     31 import com.android.settings.datetime.timezone.model.FilteredCountryTimeZones;
     32 import com.android.settings.datetime.timezone.model.TimeZoneData;
     33 
     34 import java.util.ArrayList;
     35 import java.util.Comparator;
     36 import java.util.List;
     37 import java.util.Set;
     38 import java.util.TreeSet;
     39 
     40 /**
     41  * Render a list of regions into a list view.
     42  */
     43 public class RegionSearchPicker extends BaseTimeZonePicker {
     44     private static final int REQUEST_CODE_ZONE_PICKER = 1;
     45     private static final String TAG = "RegionSearchPicker";
     46 
     47     private BaseTimeZoneAdapter<RegionItem> mAdapter;
     48     private TimeZoneData mTimeZoneData;
     49 
     50     public RegionSearchPicker() {
     51         super(R.string.date_time_select_region, R.string.date_time_search_region, true, true);
     52     }
     53 
     54     @Override
     55     public int getMetricsCategory() {
     56         return MetricsProto.MetricsEvent.SETTINGS_ZONE_PICKER_REGION;
     57     }
     58 
     59     @Override
     60     protected BaseTimeZoneAdapter createAdapter(TimeZoneData timeZoneData) {
     61         mTimeZoneData = timeZoneData;
     62         mAdapter = new BaseTimeZoneAdapter<>(createAdapterItem(timeZoneData.getRegionIds()),
     63                 this::onListItemClick, getLocale(), false /* showItemSummary */,
     64                     null /* headerText */);
     65         return mAdapter;
     66     }
     67 
     68     private void onListItemClick(RegionItem item) {
     69         final String regionId = item.getId();
     70         final FilteredCountryTimeZones countryTimeZones = mTimeZoneData.lookupCountryTimeZones(
     71                 regionId);
     72         final Activity activity = getActivity();
     73         if (countryTimeZones == null || countryTimeZones.getTimeZoneIds().isEmpty()) {
     74             Log.e(TAG, "Region has no time zones: " + regionId);
     75             activity.setResult(Activity.RESULT_CANCELED);
     76             activity.finish();
     77             return;
     78         }
     79 
     80         List<String> timeZoneIds = countryTimeZones.getTimeZoneIds();
     81         // Choose the time zone associated the region if there is only one time zone in that region
     82         if (timeZoneIds.size() == 1) {
     83             final Intent resultData = new Intent()
     84                     .putExtra(EXTRA_RESULT_REGION_ID, regionId)
     85                     .putExtra(EXTRA_RESULT_TIME_ZONE_ID, timeZoneIds.get(0));
     86             getActivity().setResult(Activity.RESULT_OK, resultData);
     87             getActivity().finish();
     88         } else {
     89             // Launch the zone picker and let the user choose a time zone from the list of
     90             // time zones associated with the region.
     91             final Bundle args = new Bundle();
     92             args.putString(RegionZonePicker.EXTRA_REGION_ID, regionId);
     93             new SubSettingLauncher(getContext())
     94                     .setDestination(RegionZonePicker.class.getCanonicalName())
     95                     .setArguments(args)
     96                     .setSourceMetricsCategory(getMetricsCategory())
     97                     .setResultListener(this, REQUEST_CODE_ZONE_PICKER)
     98                     .launch();
     99         }
    100     }
    101 
    102     @Override
    103     public void onActivityResult(int requestCode, int resultCode, Intent data) {
    104         if (requestCode == REQUEST_CODE_ZONE_PICKER) {
    105             if (resultCode == Activity.RESULT_OK) {
    106                 getActivity().setResult(Activity.RESULT_OK, data);
    107             }
    108             getActivity().finish();
    109         }
    110     }
    111 
    112     private List<RegionItem> createAdapterItem(Set<String> regionIds) {
    113         final Collator collator = Collator.getInstance(getLocale());
    114         final TreeSet<RegionItem> items = new TreeSet<>(new RegionInfoComparator(collator));
    115         final LocaleDisplayNames localeDisplayNames = LocaleDisplayNames.getInstance(getLocale());
    116         long i = 0;
    117         for (String regionId : regionIds) {
    118             String name = localeDisplayNames.regionDisplayName(regionId);
    119             items.add(new RegionItem(i++, regionId, name));
    120         }
    121         return new ArrayList<>(items);
    122     }
    123 
    124     @VisibleForTesting
    125     static class RegionItem implements AdapterItem {
    126 
    127         private final String mId;
    128         private final String mName;
    129         private final long mItemId;
    130         private final String[] mSearchKeys;
    131 
    132         RegionItem(long itemId, String id, String name) {
    133             mId = id;
    134             mName = name;
    135             mItemId = itemId;
    136             // Allow to search with ISO_3166-1 alpha-2 code. It's handy for english users in some
    137             // countries, e.g. US for United States. It's not best search keys for users, but
    138             // ICU doesn't have the data for the alias names of a region.
    139             mSearchKeys = new String[] {mId, mName};
    140         }
    141 
    142         public String getId() {
    143             return mId;
    144         }
    145 
    146         @Override
    147         public CharSequence getTitle() {
    148             return mName;
    149         }
    150 
    151         @Override
    152         public CharSequence getSummary() {
    153             return null;
    154         }
    155 
    156         @Override
    157         public String getIconText() {
    158             return null;
    159         }
    160 
    161         @Override
    162         public String getCurrentTime() {
    163             return null;
    164         }
    165 
    166         @Override
    167         public long getItemId() {
    168             return mItemId;
    169         }
    170 
    171         @Override
    172         public String[] getSearchKeys() {
    173             return mSearchKeys;
    174         }
    175     }
    176 
    177     private static class RegionInfoComparator implements Comparator<RegionItem> {
    178         private final Collator mCollator;
    179 
    180         RegionInfoComparator(Collator collator) {
    181             mCollator = collator;
    182         }
    183 
    184         @Override
    185         public int compare(RegionItem r1, RegionItem r2) {
    186             return mCollator.compare(r1.getTitle(), r2.getTitle());
    187         }
    188     }
    189 }
    190