blob: 440df940fa541ce2db7df8c4f9ce659291d6c431 [file] [log] [blame]
Marcus Hagerott819214d2016-09-29 14:58:27 -07001/*
2 * Copyright (C) 2016 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 */
16package com.android.contacts.editor;
17
18import android.content.Context;
Marcus Hagerott73b283f2016-10-21 15:42:00 -070019import android.os.Bundle;
Marcus Hagerott819214d2016-09-29 14:58:27 -070020import android.support.annotation.NonNull;
21import android.support.annotation.StringRes;
22import android.view.View;
23import android.widget.AdapterView;
24import android.widget.ImageView;
25import android.widget.ListPopupWindow;
26import android.widget.TextView;
27
28import com.android.contacts.R;
29import com.android.contacts.common.model.AccountTypeManager;
30import com.android.contacts.common.model.account.AccountDisplayInfo;
31import com.android.contacts.common.model.account.AccountDisplayInfoFactory;
32import com.android.contacts.common.model.account.AccountWithDataSet;
33import com.android.contacts.common.util.AccountsListAdapter;
34import com.android.contacts.util.UiClosables;
35
36import java.util.List;
37
38/**
39 * Controls the display of an account selector or header.
40 *
41 * TODO: This was mostly copied from {@link RawContactEditorView}. The code in that class
42 * should probably be modified to use this instead of leaving it duplicated.
43 */
44public class AccountHeaderPresenter {
45
Marcus Hagerott73b283f2016-10-21 15:42:00 -070046 private static final String KEY_SELECTED_ACCOUNT = "accountHeaderSelectedAccount";
47
Marcus Hagerott819214d2016-09-29 14:58:27 -070048 public interface Observer {
49 void onChange(AccountHeaderPresenter sender);
50
51 public static final Observer NONE = new Observer() {
52 @Override
53 public void onChange(AccountHeaderPresenter sender) {
54 }
55 };
56 }
57
58 private final Context mContext;
59 private AccountDisplayInfoFactory mAccountDisplayInfoFactory;
60
61 private AccountWithDataSet mCurrentAccount;
62
63 // Account header
64 private final View mAccountHeaderContainer;
65 private TextView mAccountHeaderType;
66 private TextView mAccountHeaderName;
67 private ImageView mAccountHeaderIcon;
68 private ImageView mAccountHeaderExpanderIcon;
69
70 // This would be different if the account was readonly
71 @StringRes
72 private int mSelectorTitle = R.string.editor_account_selector_title;
73
74 private Observer mObserver = Observer.NONE;
75
76 public AccountHeaderPresenter(View container) {
77 mContext = container.getContext();
78 mAccountHeaderContainer = container;
Marcus Hagerott7217e692016-11-10 10:18:28 -080079 // mAccountHeaderType is optional and may not be in the container view in which case
80 // the variable will be null
Marcus Hagerott819214d2016-09-29 14:58:27 -070081 mAccountHeaderType = (TextView) container.findViewById(R.id.account_type);
82 mAccountHeaderName = (TextView) container.findViewById(R.id.account_name);
83 mAccountHeaderIcon = (ImageView) container.findViewById(R.id.account_type_icon);
84 mAccountHeaderExpanderIcon = (ImageView) container.findViewById(R.id.account_expander_icon);
85
86 mAccountDisplayInfoFactory = AccountDisplayInfoFactory.forWritableAccounts(mContext);
87 }
88
89 public void setObserver(Observer observer) {
90 mObserver = observer;
91 }
92
93 public void setCurrentAccount(@NonNull AccountWithDataSet account) {
94 if (mCurrentAccount != null && mCurrentAccount.equals(account)) {
95 return;
96 }
97 mCurrentAccount = account;
98 if (mObserver != null) {
99 mObserver.onChange(this);
100 }
101 updateDisplayedAccount();
102 }
103
104 public AccountWithDataSet getCurrentAccount() {
105 return mCurrentAccount;
106 }
107
Marcus Hagerott73b283f2016-10-21 15:42:00 -0700108 public void onSaveInstanceState(Bundle outState) {
109 outState.putParcelable(KEY_SELECTED_ACCOUNT, mCurrentAccount);
110 }
111
112 public void onRestoreInstanceState(Bundle savedInstanceState) {
113 if (savedInstanceState == null) return;
114 if (mCurrentAccount == null) {
115 mCurrentAccount = savedInstanceState.getParcelable(KEY_SELECTED_ACCOUNT);
116 }
117 updateDisplayedAccount();
118 }
119
Marcus Hagerott819214d2016-09-29 14:58:27 -0700120 private void updateDisplayedAccount() {
121 mAccountHeaderContainer.setVisibility(View.GONE);
122 if (mCurrentAccount == null) return;
123
124 final AccountDisplayInfo account =
125 mAccountDisplayInfoFactory.getAccountDisplayInfo(mCurrentAccount);
126
127 final String accountLabel = getAccountLabel(account);
128
129 // Either the account header or selector should be shown, not both.
130 final List<AccountWithDataSet> accounts =
131 AccountTypeManager.getInstance(mContext).getAccounts(true);
132
133 if (accounts.size() > 1) {
134 addAccountSelector(accountLabel);
135 } else {
136 addAccountHeader(accountLabel);
137 }
138 }
139
140 private void addAccountHeader(String accountLabel) {
141 mAccountHeaderContainer.setVisibility(View.VISIBLE);
142
143 // Set the account name
144 mAccountHeaderName.setVisibility(View.VISIBLE);
145 mAccountHeaderName.setText(accountLabel);
146
147 // Set the account type
148 final String selectorTitle = mContext.getResources().getString(mSelectorTitle);
Marcus Hagerott7217e692016-11-10 10:18:28 -0800149 if (mAccountHeaderType != null) {
150 mAccountHeaderType.setText(selectorTitle);
151 }
Marcus Hagerott819214d2016-09-29 14:58:27 -0700152
153 // Set the icon
154 final AccountDisplayInfo displayInfo = mAccountDisplayInfoFactory
155 .getAccountDisplayInfo(mCurrentAccount);
156 mAccountHeaderIcon.setImageDrawable(displayInfo.getIcon());
157
158 // Set the content description
159 mAccountHeaderContainer.setContentDescription(
160 EditorUiUtils.getAccountInfoContentDescription(accountLabel,
161 selectorTitle));
162 }
163
164 private void addAccountSelector(CharSequence nameLabel) {
165 final View.OnClickListener onClickListener = new View.OnClickListener() {
166 @Override
167 public void onClick(View v) {
Marcus Hagerott73b283f2016-10-21 15:42:00 -0700168 showPopup();
Marcus Hagerott819214d2016-09-29 14:58:27 -0700169 }
170 };
171 setUpAccountSelector(nameLabel.toString(), onClickListener);
172 }
173
Marcus Hagerott73b283f2016-10-21 15:42:00 -0700174 private void showPopup() {
175 final ListPopupWindow popup = new ListPopupWindow(mContext);
176 final AccountsListAdapter adapter =
177 new AccountsListAdapter(mContext,
178 AccountsListAdapter.AccountListFilter.ACCOUNTS_CONTACT_WRITABLE,
179 mCurrentAccount);
180 popup.setWidth(mAccountHeaderContainer.getWidth());
181 popup.setAnchorView(mAccountHeaderContainer);
182 popup.setAdapter(adapter);
183 popup.setModal(true);
184 popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
185 popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
186 @Override
187 public void onItemClick(AdapterView<?> parent, View view, int position,
188 long id) {
189 UiClosables.closeQuietly(popup);
190 final AccountWithDataSet newAccount = adapter.getItem(position);
191 setCurrentAccount(newAccount);
192 }
193 });
194 mAccountHeaderContainer.post(new Runnable() {
195 @Override
196 public void run() {
197 popup.show();
198 }
199 });
200 }
201
Marcus Hagerott819214d2016-09-29 14:58:27 -0700202 private void setUpAccountSelector(String nameLabel, View.OnClickListener listener) {
203 addAccountHeader(nameLabel);
204 // Add handlers for choosing another account to save to.
205 mAccountHeaderExpanderIcon.setVisibility(View.VISIBLE);
Marcus Hagerott4b112322016-11-18 10:09:32 -0800206 // Add the listener to the icon so that it will be announced by talkback as a clickable
207 // element
208 mAccountHeaderExpanderIcon.setOnClickListener(listener);
Marcus Hagerott819214d2016-09-29 14:58:27 -0700209 mAccountHeaderContainer.setOnClickListener(listener);
210 }
211
212 private String getAccountLabel(AccountDisplayInfo account) {
213 // TODO: if used from editor this would need to be different if editing the user's profile.
214 return account.getNameLabel().toString();
215 }
216}