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