Implements tab in ContactListActivity.
authorDa Risk <da_risk@beem-project.com>
Sun, 22 Apr 2012 22:49:21 +0200
changeset 995 ab5691925a0d
parent 994 7483a66399de
child 996 8f2689fb8488
Implements tab in ContactListActivity.
res/layout/contactlist_group.xml
res/layout/contactlist_groupstub.xml
src/com/beem/project/beem/ui/ContactList.java
src/com/beem/project/beem/ui/ContactListFragment.java
--- a/res/layout/contactlist_group.xml	Sun Apr 22 20:39:31 2012 +0200
+++ b/res/layout/contactlist_group.xml	Sun Apr 22 22:49:21 2012 +0200
@@ -1,5 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    BEEM is a videoconference application on the Android Platform.
 
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    Copyright (C) 2009-2011 by Frederic-Charles Barthelery,
+                               Nikita Kozlov,
+                               Vincent Veronis.
+
+    This file is part of BEEM.
+
+    BEEM is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    BEEM is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.
+
+    Please send bug reports with examples or suggestions to
+    contact@beem-project.com or http://www.beem-project.com/
+
+-->
+<com.beem.project.beem.ui.views.SectionTextView xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:beem="http://schemas.android.com/apk/res/com.beem.project.beem"
 	android:textColor="@color/white" android:textColorHighlight="@color/red"
 	android:textSize="18sp" android:typeface="normal" android:textStyle="bold"
-	android:id="@+id/contactlist_group"></TextView>
\ No newline at end of file
+	android:paddingLeft="20dp" android:paddingRight="20dp"
+	beem:principalColor="@color/vert_manu"
+	android:id="@+id/contactlist_group"
+	/>
--- a/res/layout/contactlist_groupstub.xml	Sun Apr 22 20:39:31 2012 +0200
+++ b/res/layout/contactlist_groupstub.xml	Sun Apr 22 22:49:21 2012 +0200
@@ -1,10 +1,36 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+    BEEM is a videoconference application on the Android Platform.
+
+    Copyright (C) 2009-2011 by Frederic-Charles Barthelery,
+                               Nikita Kozlov,
+                               Vincent Veronis.
+
+    This file is part of BEEM.
+
+    BEEM is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    BEEM is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.
+
+    Please send bug reports with examples or suggestions to
+    contact@beem-project.com or http://www.beem-project.com/
+
+-->
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 	android:id="@+id/contactlist_groupstub" android:layout_width="wrap_content"
 	android:layout_height="wrap_content">
 	<Gallery xmlns:android="http://schemas.android.com/apk/res/android"
 		android:id="@+id/contactlist_banner" android:layout_width="fill_parent"
-		android:layout_height="40dp" android:spacing="25dp"
+		android:layout_height="40dp" android:spacing="0dp"
 		android:unselectedAlpha="0.4" android:background="#222222" />
 	<View android:layout_width="fill_parent" android:layout_height="2dp"
 		android:fadingEdge="horizontal" android:background="#555555" />
--- 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;
+	}
+    }
+
+
 }
--- a/src/com/beem/project/beem/ui/ContactListFragment.java	Sun Apr 22 20:39:31 2012 +0200
+++ b/src/com/beem/project/beem/ui/ContactListFragment.java	Sun Apr 22 22:49:21 2012 +0200
@@ -1,30 +1,22 @@
 package com.beem.project.beem.ui;
 
-import java.util.LinkedList;
 import java.util.List;
 
 import android.app.Activity;
-import android.app.Dialog;
 import android.content.Intent;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.support.v4.app.ListFragment;
-import android.util.Log;
 import android.view.ContextMenu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.widget.AdapterView;
 import android.widget.AdapterView.AdapterContextMenuInfo;
-import android.widget.Filter;
 import android.widget.ListAdapter;
 import android.widget.ListView;
 
 import com.beem.project.beem.R;
 import com.beem.project.beem.service.Contact;
-import com.beem.project.beem.ui.dialogs.builders.Alias;
-import com.beem.project.beem.ui.dialogs.builders.DeleteContact;
-import com.beem.project.beem.ui.dialogs.builders.ResendSubscription;
 
 public class ContactListFragment extends ListFragment {
 	private String group;