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