blob: 5323c60e292214abe63c94109c79bce312f444ef [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;
79 mAccountHeaderType = (TextView) container.findViewById(R.id.account_type);
80 mAccountHeaderName = (TextView) container.findViewById(R.id.account_name);
81 mAccountHeaderIcon = (ImageView) container.findViewById(R.id.account_type_icon);
82 mAccountHeaderExpanderIcon = (ImageView) container.findViewById(R.id.account_expander_icon);
83
84 mAccountDisplayInfoFactory = AccountDisplayInfoFactory.forWritableAccounts(mContext);
85 }
86
87 public void setObserver(Observer observer) {
88 mObserver = observer;
89 }
90
91 public void setCurrentAccount(@NonNull AccountWithDataSet account) {
92 if (mCurrentAccount != null && mCurrentAccount.equals(account)) {
93 return;
94 }
95 mCurrentAccount = account;
96 if (mObserver != null) {
97 mObserver.onChange(this);
98 }
99 updateDisplayedAccount();
100 }
101
102 public AccountWithDataSet getCurrentAccount() {
103 return mCurrentAccount;
104 }
105
Marcus Hagerott73b283f2016-10-21 15:42:00 -0700106 public void onSaveInstanceState(Bundle outState) {
107 outState.putParcelable(KEY_SELECTED_ACCOUNT, mCurrentAccount);
108 }
109
110 public void onRestoreInstanceState(Bundle savedInstanceState) {
111 if (savedInstanceState == null) return;
112 if (mCurrentAccount == null) {
113 mCurrentAccount = savedInstanceState.getParcelable(KEY_SELECTED_ACCOUNT);
114 }
115 updateDisplayedAccount();
116 }
117
Marcus Hagerott819214d2016-09-29 14:58:27 -0700118 private void updateDisplayedAccount() {
119 mAccountHeaderContainer.setVisibility(View.GONE);
120 if (mCurrentAccount == null) return;
121
122 final AccountDisplayInfo account =
123 mAccountDisplayInfoFactory.getAccountDisplayInfo(mCurrentAccount);
124
125 final String accountLabel = getAccountLabel(account);
126
127 // Either the account header or selector should be shown, not both.
128 final List<AccountWithDataSet> accounts =
129 AccountTypeManager.getInstance(mContext).getAccounts(true);
130
131 if (accounts.size() > 1) {
132 addAccountSelector(accountLabel);
133 } else {
134 addAccountHeader(accountLabel);
135 }
136 }
137
138 private void addAccountHeader(String accountLabel) {
139 mAccountHeaderContainer.setVisibility(View.VISIBLE);
140
141 // Set the account name
142 mAccountHeaderName.setVisibility(View.VISIBLE);
143 mAccountHeaderName.setText(accountLabel);
144
145 // Set the account type
146 final String selectorTitle = mContext.getResources().getString(mSelectorTitle);
147 mAccountHeaderType.setText(selectorTitle);
148
149 // Set the icon
150 final AccountDisplayInfo displayInfo = mAccountDisplayInfoFactory
151 .getAccountDisplayInfo(mCurrentAccount);
152 mAccountHeaderIcon.setImageDrawable(displayInfo.getIcon());
153
154 // Set the content description
155 mAccountHeaderContainer.setContentDescription(
156 EditorUiUtils.getAccountInfoContentDescription(accountLabel,
157 selectorTitle));
158 }
159
160 private void addAccountSelector(CharSequence nameLabel) {
161 final View.OnClickListener onClickListener = new View.OnClickListener() {
162 @Override
163 public void onClick(View v) {
Marcus Hagerott73b283f2016-10-21 15:42:00 -0700164 showPopup();
Marcus Hagerott819214d2016-09-29 14:58:27 -0700165 }
166 };
167 setUpAccountSelector(nameLabel.toString(), onClickListener);
168 }
169
Marcus Hagerott73b283f2016-10-21 15:42:00 -0700170 private void showPopup() {
171 final ListPopupWindow popup = new ListPopupWindow(mContext);
172 final AccountsListAdapter adapter =
173 new AccountsListAdapter(mContext,
174 AccountsListAdapter.AccountListFilter.ACCOUNTS_CONTACT_WRITABLE,
175 mCurrentAccount);
176 popup.setWidth(mAccountHeaderContainer.getWidth());
177 popup.setAnchorView(mAccountHeaderContainer);
178 popup.setAdapter(adapter);
179 popup.setModal(true);
180 popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
181 popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
182 @Override
183 public void onItemClick(AdapterView<?> parent, View view, int position,
184 long id) {
185 UiClosables.closeQuietly(popup);
186 final AccountWithDataSet newAccount = adapter.getItem(position);
187 setCurrentAccount(newAccount);
188 }
189 });
190 mAccountHeaderContainer.post(new Runnable() {
191 @Override
192 public void run() {
193 popup.show();
194 }
195 });
196 }
197
Marcus Hagerott819214d2016-09-29 14:58:27 -0700198 private void setUpAccountSelector(String nameLabel, View.OnClickListener listener) {
199 addAccountHeader(nameLabel);
200 // Add handlers for choosing another account to save to.
201 mAccountHeaderExpanderIcon.setVisibility(View.VISIBLE);
202 mAccountHeaderContainer.setOnClickListener(listener);
203 }
204
205 private String getAccountLabel(AccountDisplayInfo account) {
206 // TODO: if used from editor this would need to be different if editing the user's profile.
207 return account.getNameLabel().toString();
208 }
209}