Home | History | Annotate | Download | only in list
      1 /*
      2  * Copyright (C) 2010 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 package com.android.contacts.list;
     17 
     18 import android.content.Context;
     19 import android.content.SharedPreferences;
     20 import android.preference.PreferenceManager;
     21 
     22 import com.android.contacts.logging.ListEvent;
     23 import com.android.contacts.model.AccountTypeManager;
     24 import com.android.contacts.model.account.AccountWithDataSet;
     25 
     26 import java.util.ArrayList;
     27 import java.util.List;
     28 
     29 /**
     30  * Manages {@link ContactListFilter}. All methods must be called from UI thread.
     31  */
     32 public abstract class ContactListFilterController {
     33 
     34     // singleton to cache the filter controller
     35     private static ContactListFilterControllerImpl sFilterController = null;
     36 
     37     public interface ContactListFilterListener {
     38         void onContactListFilterChanged();
     39     }
     40 
     41     public static ContactListFilterController getInstance(Context context) {
     42         // We may need to synchronize this in the future if background task will call this.
     43         if (sFilterController == null) {
     44             sFilterController = new ContactListFilterControllerImpl(context);
     45         }
     46         return sFilterController;
     47     }
     48 
     49     public abstract void addListener(ContactListFilterListener listener);
     50 
     51     public abstract void removeListener(ContactListFilterListener listener);
     52 
     53     /**
     54      * Return the currently-active filter.
     55      */
     56     public abstract ContactListFilter getFilter();
     57 
     58     public abstract int getFilterListType();
     59 
     60     /** Whether the persisted filter is a custom filter. */
     61     public abstract boolean isCustomFilterPersisted();
     62 
     63     /** Returns the persisted filter. */
     64     public abstract ContactListFilter getPersistedFilter();
     65 
     66     /**
     67      * @param filter the filter
     68      * @param persistent True when the given filter should be saved soon. False when the filter
     69      * should not be saved. The latter case may happen when some Intent requires a certain type of
     70      * UI (e.g. single contact) temporarily.
     71      */
     72     public abstract void setContactListFilter(ContactListFilter filter, boolean persistent);
     73 
     74     public abstract void selectCustomFilter();
     75 
     76     /**
     77      * Checks if the current filter is valid and reset the filter if not. It may happen when
     78      * an account is removed while the filter points to the account with
     79      * {@link ContactListFilter#FILTER_TYPE_ACCOUNT} type, for example. It may also happen if
     80      * the current filter is {@link ContactListFilter#FILTER_TYPE_SINGLE_CONTACT}, in
     81      * which case, we should switch to the last saved filter in {@link SharedPreferences}.
     82      */
     83     public abstract void checkFilterValidity(boolean notifyListeners);
     84 }
     85 
     86 /**
     87  * Stores the {@link ContactListFilter} selected by the user and saves it to
     88  * {@link SharedPreferences} if necessary.
     89  */
     90 class ContactListFilterControllerImpl extends ContactListFilterController {
     91     private final Context mContext;
     92     private final List<ContactListFilterListener> mListeners =
     93             new ArrayList<ContactListFilterListener>();
     94     private ContactListFilter mFilter;
     95 
     96     public ContactListFilterControllerImpl(Context context) {
     97         mContext = context.getApplicationContext();
     98         mFilter = ContactListFilter.restoreDefaultPreferences(getSharedPreferences());
     99         checkFilterValidity(true /* notify listeners */);
    100     }
    101 
    102     @Override
    103     public void addListener(ContactListFilterListener listener) {
    104         mListeners.add(listener);
    105     }
    106 
    107     @Override
    108     public void removeListener(ContactListFilterListener listener) {
    109         mListeners.remove(listener);
    110     }
    111 
    112     @Override
    113     public ContactListFilter getFilter() {
    114         return mFilter;
    115     }
    116 
    117     @Override
    118     public int getFilterListType() {
    119         return mFilter == null ? ListEvent.ListType.UNKNOWN_LIST : mFilter.toListType();
    120     }
    121 
    122     @Override
    123     public boolean isCustomFilterPersisted() {
    124         final ContactListFilter filter = getPersistedFilter();
    125         return filter != null && filter.filterType == ContactListFilter.FILTER_TYPE_CUSTOM;
    126     }
    127 
    128     @Override
    129     public ContactListFilter getPersistedFilter() {
    130         return ContactListFilter.restoreDefaultPreferences(getSharedPreferences());
    131     }
    132 
    133     private SharedPreferences getSharedPreferences() {
    134         return PreferenceManager.getDefaultSharedPreferences(mContext);
    135     }
    136 
    137     @Override
    138     public void setContactListFilter(ContactListFilter filter, boolean persistent) {
    139         setContactListFilter(filter, persistent, /* notifyListeners */ true);
    140     }
    141 
    142     private void setContactListFilter(ContactListFilter filter, boolean persistent,
    143             boolean notifyListeners) {
    144         if (!filter.equals(mFilter)) {
    145             mFilter = filter;
    146             if (persistent) {
    147                 ContactListFilter.storeToPreferences(getSharedPreferences(), mFilter);
    148             }
    149             if (notifyListeners && !mListeners.isEmpty()) {
    150                 notifyContactListFilterChanged();
    151             }
    152         }
    153     }
    154 
    155     @Override
    156     public void selectCustomFilter() {
    157         setContactListFilter(ContactListFilter.createFilterWithType(
    158                 ContactListFilter.FILTER_TYPE_CUSTOM), /* persistent */ true);
    159     }
    160 
    161     private void notifyContactListFilterChanged() {
    162         for (ContactListFilterListener listener : mListeners) {
    163             listener.onContactListFilterChanged();
    164         }
    165     }
    166 
    167     @Override
    168     public void checkFilterValidity(boolean notifyListeners) {
    169         if (mFilter == null) {
    170             return;
    171         }
    172 
    173         switch (mFilter.filterType) {
    174             case ContactListFilter.FILTER_TYPE_SINGLE_CONTACT:
    175                 setContactListFilter(
    176                         ContactListFilter.restoreDefaultPreferences(getSharedPreferences()),
    177                         false, notifyListeners);
    178                 break;
    179             case ContactListFilter.FILTER_TYPE_ACCOUNT:
    180                 if (!filterAccountExists()) {
    181                     // The current account filter points to invalid account. Use "all" filter
    182                     // instead.
    183                     setContactListFilter(ContactListFilter.createFilterWithType(
    184                             ContactListFilter.FILTER_TYPE_ALL_ACCOUNTS), true, notifyListeners);
    185                 }
    186                 break;
    187         }
    188     }
    189 
    190     /**
    191      * @return true if the Account for the current filter exists.
    192      */
    193     private boolean filterAccountExists() {
    194         final AccountTypeManager accountTypeManager = AccountTypeManager.getInstance(mContext);
    195         final AccountWithDataSet filterAccount = new AccountWithDataSet(
    196                 mFilter.accountName, mFilter.accountType, mFilter.dataSet);
    197         return accountTypeManager.exists(filterAccount);
    198     }
    199 }
    200