Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f50e9af authored by James Kung's avatar James Kung Committed by Android (Google) Code Review
Browse files

Merge "Appending selected cities to top of list" into ics-ub-clock-amazon

parents 34b7d8c6 96ae9779
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -334,6 +334,9 @@
    <!-- Menu item on Cities screen to sort by alphabetical order -->
    <string name="menu_item_sort_by_name">Sort by name</string>

    <!-- Label for selected cities in Cities list view -->
    <string name="selected_cities_label">Selected Cities</string>

    <!-- Stop Watch strings -->
    <!-- Describes the purpose of the button to resume running a stopwatch -->
    <string name="sw_resume_button">Resume</string>
+114 −105
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import com.android.deskclock.Utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.TimeZone;
@@ -94,24 +95,31 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,
    private SharedPreferences mPrefs;
    private int mSortType;

    private String mSelectedCitiesHeaderString;

    /***
     * Adapter for a list of cities with the respected time zone. The Adapter
     * sorts the list alphabetically and create an indexer.
     ***/
    private class CityAdapter extends BaseAdapter implements Filterable, SectionIndexer {
        private static final int VIEW_TYPE_CITY = 0;
        private static final int VIEW_TYPE_HEADER = 1;

        private static final String FORMAT_24_HOUR = "k:mm";
        private static final String FORMAT_12_HOUR = "h:mm aa";

        private static final String DELETED_ENTRY = "C0";
        private final HashMap<String, CityObj> mSelectedCitiesList;  // selected cities

        private List<CityObj> mDisplayedCitiesList;
        private CityObj[] mCities;

        private String[] mSortByNameSectionHeaders;
        private Integer[] mSortByNameSectionPositions;
        private CityObj[] mCities;
        private CityObj[] mSelectedCities;

        private String[] mSortByTimeSectionHeaders;
        private Integer[] mSortByTimeSectionPositions;
        private String[] mSectionHeaders;
        private Integer[] mSectionPositions;

        private CityNameComparator mSortByNameComparator = new CityNameComparator();
        private CityGmtOffsetComparator mSortByGmtOffsetComparator = new CityGmtOffsetComparator();
        private CityGmtOffsetComparator mSortByTimeComparator = new CityGmtOffsetComparator();

        private final LayoutInflater mInflater;
        private boolean mIs24HoursMode; // AM/PM or 24 hours mode
@@ -124,40 +132,56 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,
                String modifiedQuery = constraint.toString().trim().toUpperCase();

                ArrayList<CityObj> filteredList = new ArrayList<CityObj>();
                int positionIndex = 0;
                int i = 0;
                while (i < mCities.length) {
                    CityObj city = mCities[i];
                ArrayList<String> sectionHeaders = new ArrayList<String>();
                ArrayList<Integer> sectionPositions = new ArrayList<Integer>();

                // If the search query is empty, add in the selected cities
                if (TextUtils.isEmpty(modifiedQuery)) {
                    if (mSelectedCities.length > 0) {
                        filteredList.add(new CityObj(mSelectedCitiesHeaderString,
                                mSelectedCitiesHeaderString,
                                null));
                    }
                    for (CityObj city : mSelectedCities) {
                        filteredList.add(city);
                    }
                }

                String val = null;
                int offset = -100000; //some value that cannot be a real offset
                for (CityObj city : mCities) {

                    // If the city is a deleted entry, ignore it.
                    if (city.mCityId.equals(DELETED_ENTRY)) {
                        i++;
                        continue;
                    }

                    // If the search query is empty, add section headers
                    // If the search query is empty, add section headers.
                    if (TextUtils.isEmpty(modifiedQuery)) {

                        // If the list is sorted by name, and the position index is correct,
                        // insert a section header into the list
                        if (mSortType == SORT_BY_NAME &&
                                mSortByNameSectionPositions.length > positionIndex &&
                                mSortByNameSectionPositions[positionIndex] == filteredList.size()) {
                            String name = mSortByNameSectionHeaders[positionIndex];
                            filteredList.add(new CityObj(name, null, null));
                            positionIndex++;
                            continue;

                        // If the list is sorted by name, and the city begins with a letter
                        // different than the previous city's letter, insert a section header.
                        if (mSortType == SORT_BY_NAME
                                && !city.mCityName.substring(0, 1).equals(val)) {
                                val = city.mCityName.substring(0, 1).toUpperCase();
                                sectionHeaders.add(val);
                                sectionPositions.add(filteredList.size());
                                filteredList.add(new CityObj(val, null, null));
                        }

                        // If the list is sorted by time, and the position index is correct,
                        // insert a section header into the list
                        if (mSortType == SORT_BY_GMT_OFFSET &&
                                mSortByTimeSectionPositions.length > positionIndex &&
                                mSortByTimeSectionPositions[positionIndex] == filteredList.size()) {
                            String timezone = mSortByTimeSectionHeaders[positionIndex];
                            filteredList.add(new CityObj(null, timezone, null));
                            positionIndex++;
                            continue;
                        // If the list is sorted by time, and the gmt offset is different than
                        // the previous city's gmt offset, insert a section header.
                        if (mSortType == SORT_BY_GMT_OFFSET) {
                            TimeZone timezone = TimeZone.getTimeZone(city.mTimeZone);
                            int newOffset = timezone.getRawOffset();
                            if (offset != newOffset) {
                                offset = newOffset;
                                String offsetString = Utils.getGMTHourOffset(timezone, true);
                                sectionHeaders.add(offsetString);
                                sectionPositions.add(filteredList.size());
                                filteredList.add(new CityObj(null, offsetString, null));
                            }
                        }
                    }

@@ -167,8 +191,11 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,
                    if (city.mCityId != null && cityName.startsWith(modifiedQuery)) {
                        filteredList.add(city);
                    }
                    i++;
                }

                mSectionHeaders = sectionHeaders.toArray(new String[sectionHeaders.size()]);
                mSectionPositions = sectionPositions.toArray(new Integer[sectionPositions.size()]);

                results.values = filteredList;
                results.count = filteredList.size();
                return results;
@@ -186,71 +213,29 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,
        };

        public CityAdapter(
                Context context, HashMap<String, CityObj> selectedList, LayoutInflater factory) {
                Context context, LayoutInflater factory) {
            super();
            loadCities(context);
            mSelectedCitiesList = selectedList;
            mInflater = factory;
            mCalendar = Calendar.getInstance();
            mCalendar.setTimeInMillis(System.currentTimeMillis());
            Collection<CityObj> selectedCities = mUserSelectedCities.values();
            mSelectedCities = selectedCities.toArray(new CityObj[selectedCities.size()]);
            set24HoursMode(context);
        }

        public void refreshSelectedCities() {
            Collection<CityObj> selectedCities = mUserSelectedCities.values();
            mSelectedCities = selectedCities.toArray(new CityObj[selectedCities.size()]);
            sortCities(mSortType);
        }


        private void loadCities(Context c) {
            mCities = Utils.loadCitiesFromXml(c);
            if (mCities == null) {
                return;
            }

            // Sort alphabetically and populate section headers for sort-by-name
            Arrays.sort(mCities, mSortByNameComparator);
            String val = null;
            ArrayList<String> sections = new ArrayList<String>();
            ArrayList<Integer> positions = new ArrayList<Integer>();
            int count = 0;
            for (CityObj city : mCities) {
                if (city.mCityId.equals(DELETED_ENTRY)) {
                    continue;
                }

                if (!city.mCityName.substring(0, 1).equals(val)) {
                    val = city.mCityName.substring(0, 1).toUpperCase();
                    sections.add(val);
                    positions.add(count);
                    count++;
                }
                count++;
            }
            mSortByNameSectionHeaders = sections.toArray(new String[sections.size()]);
            mSortByNameSectionPositions = positions.toArray(new Integer[positions.size()]);

            // Sort by GMT offset and populate section headers for sort-by-time
            Arrays.sort(mCities, mSortByGmtOffsetComparator);
            int offset = -100000; // some number that cannot be a real offset
            val = null;
            sections.clear();
            positions.clear();
            ArrayList<String> scrollLabels = new ArrayList<String>();
            count = 0;
            for (CityObj city : mCities) {
                if (city.mCityId.equals(DELETED_ENTRY)) {
                    continue;
                }

                TimeZone timezone = TimeZone.getTimeZone(city.mTimeZone);
                int newOffset = timezone.getRawOffset();
                if (newOffset != offset) {
                    offset = newOffset;
                    sections.add(Utils.getGMTHourOffset(timezone, true));
                    positions.add(count);
                    count++;
                }
                count++;
            }
            mSortByTimeSectionHeaders = sections.toArray(new String[sections.size()]);
            mSortByTimeSectionPositions = positions.toArray(new Integer[positions.size()]);

            sortCities(mSortType);
        }

@@ -265,7 +250,11 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,
        private void sortCities(final int sortType) {
            mSortType = sortType;
            Arrays.sort(mCities, sortType == SORT_BY_NAME ? mSortByNameComparator
                    : mSortByGmtOffsetComparator);
                    : mSortByTimeComparator);
            if (mSelectedCities != null) {
                Arrays.sort(mSelectedCities, sortType == SORT_BY_NAME ? mSortByNameComparator
                        : mSortByTimeComparator);
            }
            mPrefs.edit().putInt(PREF_SORT, sortType).commit();
            mFilter.filter(mQueryTextBuffer.toString());
        }
@@ -302,30 +291,52 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,
            CityObj c = mDisplayedCitiesList.get(position);
            // Header view: A CityObj with nothing but the first letter as the name
            if (c.mCityId == null) {
                if (view == null || view.findViewById(R.id.header) == null) {
                if (view == null) {
                    view = mInflater.inflate(R.layout.city_list_header, parent, false);
                    view.setTag(view.findViewById(R.id.header));
                }
                TextView header = (TextView) view.findViewById(R.id.header);
                header.setText(mSortType == SORT_BY_NAME ? c.mCityName : c.mTimeZone);
                ((TextView) view.getTag()).setText(
                        mSortType == SORT_BY_NAME ? c.mCityName : c.mTimeZone);
            } else { // City view
                // Make sure to recycle a City view only
                if (view == null || view.findViewById(R.id.city_name) == null) {
                if (view == null) {
                    view = mInflater.inflate(R.layout.city_list_item, parent, false);
                    CityViewHolder holder = new CityViewHolder();
                    holder.name = (TextView) view.findViewById(R.id.city_name);
                    holder.time = (TextView) view.findViewById(R.id.city_time);
                    holder.selected = (CheckBox) view.findViewById(R.id.city_onoff);
                    view.setTag(holder);
                }
                view.setOnClickListener(CitiesActivity.this);
                TextView name = (TextView) view.findViewById(R.id.city_name);
                TextView tz = (TextView) view.findViewById(R.id.city_time);
                CheckBox cb = (CheckBox) view.findViewById(R.id.city_onoff);
                cb.setTag(c);
                cb.setChecked(mSelectedCitiesList.containsKey(c.mCityId));
                cb.setOnCheckedChangeListener(CitiesActivity.this);
                CityViewHolder holder = (CityViewHolder) view.getTag();
                holder.selected.setTag(c);
                holder.selected.setChecked(mUserSelectedCities.containsKey(c.mCityId));
                holder.selected.setOnCheckedChangeListener(CitiesActivity.this);
                mCalendar.setTimeZone(TimeZone.getTimeZone(c.mTimeZone));
                tz.setText(DateFormat.format(mIs24HoursMode ? "k:mm" : "h:mmaa", mCalendar));
                name.setText(c.mCityName, TextView.BufferType.SPANNABLE);
                holder.time.setText(DateFormat.format(mIs24HoursMode ? FORMAT_24_HOUR
                        : FORMAT_12_HOUR, mCalendar));
                holder.name.setText(c.mCityName, TextView.BufferType.SPANNABLE);
            }
            return view;
        }

        @Override
        public int getViewTypeCount() {
            return 2;
        }

        @Override
        public int getItemViewType(int position) {
            return (mDisplayedCitiesList.get(position).mCityId != null)
                    ? VIEW_TYPE_CITY : VIEW_TYPE_HEADER;
        }

        private class CityViewHolder {
            TextView name;
            TextView time;
            CheckBox selected;
        }

        public void set24HoursMode(Context c) {
            mIs24HoursMode = Alarms.get24HourMode(c);
            notifyDataSetChanged();
@@ -333,17 +344,14 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,

        @Override
        public int getPositionForSection(int section) {
            Integer[] positions = mSortType == SORT_BY_NAME ? mSortByNameSectionPositions :
                mSortByTimeSectionPositions;
            return (positions != null) ? (Integer) positions[section] : 0;
            return (mSectionPositions != null) ? mSectionPositions[section] : 0;
        }


        @Override
        public int getSectionForPosition(int p) {
            Integer[] positions = mSortType == SORT_BY_NAME ? mSortByNameSectionPositions :
                mSortByTimeSectionPositions;
            if (positions != null) {
            final Integer[] positions = mSectionPositions;
            if (positions != null && positions.length > 0) {
                for (int i = 0; i < positions.length - 1; i++) {
                    if (p >= positions[i]
                            && p < positions[i + 1]) {
@@ -359,8 +367,7 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,

        @Override
        public Object[] getSections() {
            return mSortType == SORT_BY_NAME ? mSortByNameSectionHeaders
                    : mSortByTimeSectionHeaders;
            return mSectionHeaders;
        }

        @Override
@@ -375,6 +382,7 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,
        mFactory = LayoutInflater.from(this);
        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        mSortType = mPrefs.getInt(PREF_SORT, SORT_BY_NAME);
        mSelectedCitiesHeaderString = getString(R.string.selected_cities_label);
        if (savedInstanceState != null) {
            mQueryTextBuffer.append(savedInstanceState.getString(KEY_SEARCH_QUERY));
            mSearchMode = savedInstanceState.getBoolean(KEY_SEARCH_MODE);
@@ -398,7 +406,7 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,
        mCitiesList.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
        mUserSelectedCities = Cities.readCitiesFromSharedPrefs(
                PreferenceManager.getDefaultSharedPreferences(this));
        mAdapter = new CityAdapter(this, mUserSelectedCities, mFactory);
        mAdapter = new CityAdapter(this, mFactory);
        mCitiesList.setAdapter(mAdapter);
        ActionBar actionBar = getActionBar();
        if (actionBar != null) {
@@ -521,6 +529,7 @@ public class CitiesActivity extends Activity implements OnCheckedChangeListener,
        boolean checked = b.isChecked();
        onCheckedChanged(b, checked);
        b.setChecked(!checked);
        mAdapter.refreshSelectedCities();
    }

    @Override