--- a/src/com/beem/project/beem/ui/ContactList.java Sun Apr 22 20:39:31 2012 +0200
+++ b/src/com/beem/project/beem/ui/ContactList.java Sun Apr 22 22:49:21 2012 +0200
@@ -42,26 +42,18 @@
*/
package com.beem.project.beem.ui;
-import java.io.IOException;
-import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import org.jivesoftware.smack.util.StringUtils;
-
import android.app.Dialog;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
@@ -82,16 +74,11 @@
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
-import android.widget.Filter;
-import android.widget.Filterable;
import android.widget.Gallery;
-import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.TextView;
import com.beem.project.beem.BeemApplication;
import com.beem.project.beem.R;
-import com.beem.project.beem.providers.AvatarProvider;
import com.beem.project.beem.service.Contact;
import com.beem.project.beem.service.PresenceAdapter;
import com.beem.project.beem.service.aidl.IBeemRosterListener;
@@ -102,8 +89,12 @@
import com.beem.project.beem.ui.dialogs.builders.ChatList;
import com.beem.project.beem.ui.dialogs.builders.DeleteContact;
import com.beem.project.beem.ui.dialogs.builders.ResendSubscription;
+import com.beem.project.beem.ui.views.SectionTextView;
import com.beem.project.beem.utils.BeemBroadcastReceiver;
+import org.jivesoftware.smack.util.StringUtils;
+
+
/**
* The contact list activity displays the roster of the user.
*/
@@ -115,7 +106,7 @@
}
private static final String TAG = "ContactList";
- private final List<String> mListGroup = new ArrayList<String>();
+ private final List<GroupHolder> mListGroup = new ArrayList<GroupHolder>();
/** Map containing a list of the different contacts of a given group.
* Each list is a @{link SortedList} so there is no need to sort it again.
@@ -123,20 +114,17 @@
private final Map<String, List<Contact>> mContactOnGroup = new HashMap<String, List<Contact>>();
private final ServiceConnection mServConn = new BeemServiceConnection();
private final BeemBroadcastReceiver mReceiver = new BeemBroadcastReceiver();
+ private final BeemBanner mAdapterBanner = new BeemBanner();
+ private final Map<String, ContactListAdapter> contactListAdapters = new HashMap<String, ContactListAdapter>();
private final BeemRosterListener mBeemRosterListener = new BeemRosterListener();
- private List<Contact> mListContact;
- private String mSelectedGroup;
private IRoster mRoster;
- private Contact mSelectedContact;
private IXmppFacade mXmppFacade;
private IChatManager mChatManager;
private SharedPreferences mSettings;
private LayoutInflater mInflater;
- private BeemBanner mAdapterBanner;
private boolean mBinded;
private ViewPager viewPager;
- private Map<String, ContactListAdapter> contactListAdapters = new HashMap<String, ContactListAdapter>();
private ListPagerAdapter groupsPagesAdapter;
private Gallery groupGallery;
@@ -201,24 +189,23 @@
this.registerReceiver(mReceiver, new IntentFilter(BeemBroadcastReceiver.BEEM_CONNECTION_CLOSED));
mInflater = getLayoutInflater();
- mAdapterBanner = new BeemBanner();
- mListContact = new ArrayList<Contact>();
-
+
viewPager = (ViewPager) findViewById(R.id.pager);
+ viewPager.setOnPageChangeListener(new OnPageChangeListener());
groupsPagesAdapter = new ListPagerAdapter(getSupportFragmentManager(), viewPager);
-
- mListGroup.add(getString(R.string.contact_list_all_contact));
- mListGroup.add(getString(R.string.contact_list_no_group));
- mAdapterBanner.notifyDataSetChanged();
+
+ mListGroup.add(new GroupHolder(getString(R.string.contact_list_all_contact)));
+ mListGroup.add(new GroupHolder(getString(R.string.contact_list_no_group)));
+ mAdapterBanner.notifyDataSetChanged();
}
@Override
protected void onStart() {
super.onStart();
- if (!mSettings.getBoolean(BeemApplication.HIDE_GROUPS_KEY, false))
- showGroups();
- else
- hideGroups();
+ if (!mSettings.getBoolean(BeemApplication.HIDE_GROUPS_KEY, false))
+ showGroups();
+ else
+ hideGroups();
if (!mBinded)
mBinded = bindService(SERVICE_INTENT, mServConn, BIND_AUTO_CREATE);
@@ -253,6 +240,65 @@
}
/**
+ * Get a {@link ContactListAdapter} for a group.
+ * The {@link ContactListAdapter} will be created if it is not exist.
+ * @param group the group
+ * @return the adapter
+ */
+ ContactListAdapter getContactListAdapter(String group) {
+ synchronized (contactListAdapters) {
+ ContactListAdapter contactListAdapter = contactListAdapters.get(group);
+ if (contactListAdapter == null) {
+ contactListAdapter = new ContactListAdapter(ContactList.this);
+ contactListAdapters.put(group, contactListAdapter);
+ if (!GroupHolder.contains(mListGroup, group)) {
+ GroupHolder gh = new GroupHolder(group);
+ mListGroup.add(mListGroup.size() - 1, gh);
+ groupsPagesAdapter.notifyDataSetChanged();
+ mAdapterBanner.notifyDataSetChanged();
+ }
+ }
+ boolean hideDisconnected = mSettings.getBoolean(BeemApplication.SHOW_OFFLINE_CONTACTS_KEY, false);
+ contactListAdapter.setOnlineOnly(hideDisconnected);
+ return contactListAdapter;
+ }
+ }
+
+ /**
+ * Exectute a context menu action on a specified contact.
+ * @param itemId the id of the menu action
+ * @param contact the contact
+ */
+ void doContextMenuAction(int itemId, Contact contact) {
+ switch (itemId) {
+ case R.id.contact_list_context_menu_call_item:
+ try {
+ mXmppFacade.call(contact.getJID() + "/psi");
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ break;
+ case R.id.contact_list_context_menu_userinfo_alias:
+ Dialog alias = new Alias(ContactList.this, mRoster, contact).create();
+ alias.show();
+ break;
+ case R.id.contact_list_context_menu_userinfo_subscription:
+ Dialog subscription = new ResendSubscription(ContactList.this,
+ mXmppFacade, contact).create();
+ subscription.show();
+ break;
+ case R.id.contact_list_context_menu_userinfo_delete:
+ Dialog delete = new DeleteContact(ContactList.this, mRoster, contact).create();
+ delete.show();
+ break;
+ default:
+ Log.w(TAG, "Context menu action not supported" + itemId);
+ break;
+ }
+
+ }
+
+ /**
* Show the groups view.
*/
private void showGroups() {
@@ -269,6 +315,7 @@
groupGallery = (Gallery) findViewById(R.id.contactlist_banner);
groupGallery.setSelection(0);
}
+ GroupHolder.setUniquePrincipal(mListGroup, 0);
}
/**
@@ -280,57 +327,41 @@
v.setVisibility(View.GONE);
}
- ContactListAdapter getContactListAdapter(String group) {
- synchronized (contactListAdapters) {
- ContactListAdapter contactListAdapter = contactListAdapters.get(group);
- if (contactListAdapter == null) {
- contactListAdapter = new ContactListAdapter(ContactList.this);
- contactListAdapters.put(group, contactListAdapter);
- if (!mListGroup.contains(group)) {
- mListGroup.add(mListGroup.size() - 1, group);
- groupsPagesAdapter.notifyDataSetChanged();
- mAdapterBanner.notifyDataSetChanged();
- }
- }
- boolean hideDisconnected = mSettings.getBoolean(BeemApplication.SHOW_OFFLINE_CONTACTS_KEY, false);
- contactListAdapter.setOnlineOnly(hideDisconnected);
- return contactListAdapter;
- }
- }
-
/**
- * Remove old groups on the banner.
- * @throws RemoteException if an error occur when communicating with the service
- */
- private void cleanBannerGroup() throws RemoteException {
- if (mListGroup.size() <= 2)
- return;
- List<String> rosterGroups = mRoster.getGroupsNames();
- List<String> realGroups = mListGroup.subList(1, mListGroup.size() - 1);
- realGroups.clear();
- realGroups.addAll(rosterGroups);
- mAdapterBanner.notifyDataSetChanged();
- groupsPagesAdapter.notifyDataSetChanged();
- }
+ * Remove old groups on the banner.
+ * @throws RemoteException if an error occur when communicating with the service
+ */
+ private void cleanBannerGroup() throws RemoteException {
+ if (mListGroup.size() <= 2)
+ return;
+ List<String> rosterGroups = mRoster.getGroupsNames();
+ Collections.sort(rosterGroups);
+ List<GroupHolder> realGroups = mListGroup.subList(1, mListGroup.size() - 1);
+ realGroups.clear();
+ realGroups.addAll(GroupHolder.createFrom(rosterGroups));
+ // restore principal
+ GroupHolder.setUniquePrincipal(mListGroup, viewPager.getCurrentItem());
+ mAdapterBanner.notifyDataSetChanged();
+ groupsPagesAdapter.notifyDataSetChanged();
+ }
- /**
- * Add a contact to the special list No Group and All contacts.
- * The contact will be added if the list is not the current list otherwise
- * the list must be modified in a Handler.
- *
- * @param contact the contact to add.
- */
- private void addToSpecialList(Contact contact) {
- List<String> groups = contact.getGroups();
-
- ContactListAdapter adapter = getContactListAdapter(getString(R.string.contact_list_all_contact));
+ /**
+ * Add a contact to the special list No Group and All contacts.
+ * The contact will be added if the list is not the current list otherwise
+ * the list must be modified in a Handler.
+ *
+ * @param contact the contact to add.
+ */
+ private void addToSpecialList(Contact contact) {
+ List<String> groups = contact.getGroups();
+
+ ContactListAdapter adapter = getContactListAdapter(getString(R.string.contact_list_all_contact));
+ adapter.put(contact);
+ if (groups.isEmpty()) {
+ adapter = getContactListAdapter(getString(R.string.contact_list_no_group));
adapter.put(contact);
- if (groups.isEmpty()) {
- adapter = getContactListAdapter(getString(R.string.contact_list_no_group));
- adapter.put(contact);
- }
-
}
+ }
/**
* Listener on service event.
@@ -357,7 +388,6 @@
final Contact contact = mRoster.getContact(StringUtils.parseBareAddress(newName));
putContactInList(contact);
}
-
}
/**
@@ -373,16 +403,16 @@
for (String cToDelete : addresses) {
final Contact contact = new Contact(cToDelete);
for (final ContactListAdapter adapter : contactListAdapters.values()) {
- runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- adapter.remove(contact);
- }
- });
+ runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ adapter.remove(contact);
+ }
+ });
}
}
- cleanBannerGroup();
+ cleanBannerGroup();
}
@@ -401,14 +431,14 @@
for (String cToDelete : addresses) {
Contact contact = new Contact(cToDelete);
for (ContactListAdapter adapter : contactListAdapters.values()) {
- adapter.remove(contact);
+ adapter.remove(contact);
}
}
for (String newName : addresses) {
- final Contact contact = mRoster.getContact(StringUtils.parseBareAddress(newName));
- putContactInList(contact);
+ final Contact contact = mRoster.getContact(StringUtils.parseBareAddress(newName));
+ putContactInList(contact);
}
- cleanBannerGroup();
+ cleanBannerGroup();
}
/**
@@ -427,29 +457,33 @@
putContactInList(contact);
}
- private void putContactInList(final Contact contact) {
- List<String> groups = contact.getGroups();
- for (final String group : groups) {
- runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- ContactListAdapter contactListAdapter = getContactListAdapter(group);
- contactListAdapter.put(contact);
- }
- });
- }
-
- runOnUiThread(new Runnable() {
-
- @Override
- public void run() {
- addToSpecialList(contact);
- }
- });
- }
+ /**
+ * Put a contact in the different group list.
+ * @param contact the contact
+ */
+ private void putContactInList(final Contact contact) {
+ List<String> groups = contact.getGroups();
+ for (final String group : groups) {
+ runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ ContactListAdapter contactListAdapter = getContactListAdapter(group);
+ contactListAdapter.put(contact);
+ }
+ });
+ }
+
+ runOnUiThread(new Runnable() {
+
+ @Override
+ public void run() {
+ addToSpecialList(contact);
+ }
+ });
+ }
}
-
+
/**
* Adapter banner list.
*/
@@ -478,11 +512,13 @@
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- View v = convertView;
+ SectionTextView v = (SectionTextView) convertView;
if (convertView == null) {
- v = mInflater.inflate(R.layout.contactlist_group, null);
+ v = (SectionTextView) mInflater.inflate(R.layout.contactlist_group, null);
}
- ((TextView) v).setText(mListGroup.get(position));
+ GroupHolder gh = (GroupHolder) getItem(position);
+ v.setText(gh.group);
+ v.setPrincipal(gh.isPrincipal);
return v;
}
}
@@ -505,19 +541,14 @@
mRoster = mXmppFacade.getRoster();
if (mRoster != null) {
List<String> tmpGroupList = mRoster.getGroupsNames();
- Collections.sort(tmpGroupList);
cleanBannerGroup();
- mListGroup.addAll(1, tmpGroupList);
synchronized (contactListAdapters) {
- for (ContactListAdapter ca : contactListAdapters.values()) {
- ca.clear();
- }
+ for (ContactListAdapter ca : contactListAdapters.values()) {
+ ca.clear();
}
- groupsPagesAdapter.notifyDataSetChanged();
- mAdapterBanner.notifyDataSetChanged();
+ }
+ assignContactToGroups(mRoster.getContactList(), tmpGroupList);
- assignContactToGroups(mRoster.getContactList(), tmpGroupList);
-
mRoster.addRosterListener(mBeemRosterListener);
Log.d(TAG, "add roster listener");
mChatManager = mXmppFacade.getChatManager();
@@ -537,7 +568,6 @@
mXmppFacade = null;
mChatManager = null;
mRoster = null;
- mListContact.clear();
mListGroup.clear();
mContactOnGroup.clear();
mBinded = false;
@@ -553,21 +583,39 @@
*/
private void assignContactToGroups(List<Contact> contacts, List<String> groupNames) {
for (Contact c : contacts) {
- addToSpecialList(c);
+ addToSpecialList(c);
List<String> groups = c.getGroups();
- for (String currentGroup : groups) {
- ContactListAdapter cl = getContactListAdapter(currentGroup);
+ for (String currentGroup : groups) {
+ ContactListAdapter cl = getContactListAdapter(currentGroup);
cl.put(c);
- }
-
+ }
}
}
}
+ /**
+ * Listener on page change event.
+ */
+ private class OnPageChangeListener extends ViewPager.SimpleOnPageChangeListener {
+
+ /**
+ * Create a {@link OnPageChangeListener}.
+ */
+ public OnPageChangeListener() {
+ }
+ @Override
+ public void onPageSelected(int position) {
+ GroupHolder.setUniquePrincipal(mListGroup, position);
+ if (groupGallery != null) {
+ groupGallery.setSelection(position);
+ }
+ mAdapterBanner.notifyDataSetChanged();
+ }
+ }
/**
* Event simple click on middle groupe name.
@@ -586,55 +634,92 @@
}
}
+ /**
+ * PagerAdapter for the contact list.
+ */
private class ListPagerAdapter extends FragmentPagerAdapter {
- public ListPagerAdapter(FragmentManager fm, ViewPager viewPager) {
- super(fm);
- viewPager.setAdapter(this);
- }
+ /**
+ * Create a {@link ListPagerAdapter}.
+ * @param fm the {@link FragmentManager}
+ * @param viewPager the {@link ViewPager} associate with this adapter
+ */
+ public ListPagerAdapter(final FragmentManager fm, final ViewPager viewPager) {
+ super(fm);
+ viewPager.setAdapter(this);
+ }
- @Override
- public Fragment getItem(int position) {
- String group = mListGroup.get(position);
- ContactListFragment f = ContactListFragment.newInstance(group);
- f.setListAdapter(getContactListAdapter(group));
- return f;
- }
+ @Override
+ public Fragment getItem(int position) {
+ String group = mListGroup.get(position).group;
+ ContactListFragment f = ContactListFragment.newInstance(group);
+ f.setListAdapter(getContactListAdapter(group));
+ return f;
+ }
- @Override
- public int getCount() {
- return mListGroup.size();
- }
-
+ @Override
+ public int getCount() {
+ return mListGroup.size();
+ }
+
}
- void doContextMenuAction(int itemId, Contact contact) {
- switch (itemId) {
- case R.id.contact_list_context_menu_call_item:
- try {
- mXmppFacade.call(contact.getJID() + "/psi");
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- break;
- case R.id.contact_list_context_menu_userinfo_alias:
- Dialog alias = new Alias(ContactList.this, mRoster, contact).create();
- alias.show();
- break;
- case R.id.contact_list_context_menu_userinfo_subscription:
- Dialog subscription = new ResendSubscription(ContactList.this,
- mXmppFacade, contact).create();
- subscription.show();
- break;
- case R.id.contact_list_context_menu_userinfo_delete:
- Dialog delete = new DeleteContact(ContactList.this, mRoster, contact).create();
- delete.show();
- break;
- default:
- Log.w(TAG, "Context menu action not supported" + itemId);
- break;
+ /**
+ * A holder for a group name and is principal state.
+ * It is an helper class to manage the state of the tabs.
+ */
+ private static class GroupHolder {
+
+ String group;
+ boolean isPrincipal;
+
+ /**
+ * Create a {@link GroupHolder}.
+ * @param group the group name
+ */
+ public GroupHolder(final String group) {
+ this.group = group;
+ }
+
+ /**
+ * Create a list of GroupHolder.
+ * @param groups list of group name
+ * @return a list of {@link GroupHolder}
+ */
+ public static List<GroupHolder> createFrom(List<String> groups) {
+ List<GroupHolder> result = new ArrayList<ContactList.GroupHolder>();
+ for (String s : groups) {
+ result.add(new GroupHolder(s));
}
-
+ return result;
}
+ /**
+ * Test if a group exist in a list of {@link GroupHolder}.
+ * @param list the list
+ * @param group the group
+ * @return true if the group is in the list false otherwise
+ */
+ public static boolean contains(List<GroupHolder> list, String group) {
+ for (GroupHolder groupHolder : list) {
+ if (groupHolder.group.equals(group))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Set a unique principal in the {@link GroupHolder} list.
+ * @param groups the list
+ * @param position the position of the principal
+ */
+ public static void setUniquePrincipal(List<GroupHolder> groups, int position) {
+ for (GroupHolder gh : groups) {
+ gh.isPrincipal = false;
+ }
+ groups.get(position).isPrincipal = true;
+ }
+ }
+
+
}