Refactor the ContactList activity.
authorDa Risk <darisk972@gmail.com>
Tue, 01 Jun 2010 21:32:39 +0200
changeset 760 97451b0f4f09
parent 759 5f7bbb0c2731
child 761 6c83317a3c84
Refactor the ContactList activity. Use an insertion sorted list to manage the sort.
src/com/beem/project/beem/ui/ContactList.java
src/com/beem/project/beem/utils/SortedList.java
--- a/src/com/beem/project/beem/ui/ContactList.java	Mon May 31 00:56:26 2010 +0200
+++ b/src/com/beem/project/beem/ui/ContactList.java	Tue Jun 01 21:32:39 2010 +0200
@@ -50,7 +50,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Iterator;
 
 import org.jivesoftware.smack.util.StringUtils;
 
@@ -96,6 +95,7 @@
 import com.beem.project.beem.ui.dialogs.builders.ResendSubscription;
 import com.beem.project.beem.utils.BeemBroadcastReceiver;
 import com.beem.project.beem.utils.Status;
+import com.beem.project.beem.utils.SortedList;
 
 /**
  * The contact list activity displays the roster of the user.
@@ -107,11 +107,14 @@
 	SERVICE_INTENT.setComponent(new ComponentName("com.beem.project.beem", "com.beem.project.beem.BeemService"));
     }
 
-    private static final int REQUEST_CODE = 1;
     private static final String SETTINGS_HIDDEN_CONTACT = "settings_key_hidden_contact";
     private static final String TAG = "ContactList";
     private final BeemContactList mAdapterContactList = new BeemContactList();
     private final List<String> mListGroup = new ArrayList<String>();
+
+    /** 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.
+     * */
     private final Map<String, List<Contact>> mContactOnGroup = new HashMap<String, List<Contact>>();
     private final BeemContactListOnClick mOnContactClick = new BeemContactListOnClick();
     private final Handler mHandler = new Handler();
@@ -133,7 +136,6 @@
      * Constructor.
      */
     public ContactList() {
-
     }
 
     /**
@@ -226,7 +228,8 @@
 		    result = true;
 		    break;
 		case R.id.contact_list_context_menu_userinfo_subscription:
-		    Dialog subscription = new ResendSubscription(ContactList.this, mXmppFacade, mSelectedContact).create();
+		    Dialog subscription = new ResendSubscription(ContactList.this,
+			    mXmppFacade, mSelectedContact).create();
 		    subscription.show();
 		    result = true;
 		    break;
@@ -300,37 +303,17 @@
     }
 
     /**
-     * Comparator Contact by status and name.
-     */
-    private static class ComparatorContactListByStatusAndName<T> implements Comparator<T> {
-	/**
-	 * Constructor.
-	 */
-	public ComparatorContactListByStatusAndName() {
-	}
-
-	@Override
-	public int compare(T c1, T c2) {
-	    if (((Contact) c1).getStatus() < ((Contact) c2).getStatus()) {
-		return 1;
-	    } else if (((Contact) c1).getStatus() > ((Contact) c2).getStatus()) {
-		return -1;
-	    } else
-		return ((Contact) c1).getName().compareToIgnoreCase(((Contact) c2).getName());
-	}
-    }
-
-    /**
-     * Contact List construction.
+     * Build and display the contact list.
+     * @param group name of the contact list.
      */
     private void buildContactList(String group) {
 	mListContact = mContactOnGroup.get(group);
 	Log.d(TAG, "buildContactList for group " + group);
-	sortBeemContactList();
+	mAdapterContactList.notifyDataSetChanged();
     }
 
     /**
-     * showGroups.
+     * Show the groups view.
      */
     private void showGroups() {
 
@@ -340,57 +323,21 @@
 	    Gallery g = (Gallery) v.findViewById(R.id.contactlist_banner);
 	    g.setOnItemClickListener(new OnItemClickGroupName());
 	    g.setAdapter(mAdapterBanner);
-	} else
+	    g.setSelection(0);
+	} else {
 	    ((LinearLayout) findViewById(R.id.contactlist_groupstub)).setVisibility(View.VISIBLE);
-    }
-
-    /**
-     * Event simple click on item of the contact list.
-     */
-    private class BeemContactListOnClick implements OnItemClickListener {
-	/**
-	 * Constructor.
-	 */
-	public BeemContactListOnClick() {
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	@Override
-	public void onItemClick(AdapterView<?> arg0, View v, int pos, long lpos) {
-	    Contact c = mListContact.get(pos);
-	    Intent i = new Intent(ContactList.this, Chat.class);
-	    i.setData(c.toUri());
-	    startActivity(i);
+	    Gallery g = (Gallery) findViewById(R.id.contactlist_banner);
+	    g.setSelection(0);
 	}
     }
 
     /**
-     * Event simple click on middle groupe name.
+     * Hide the groups view.
      */
-    private class OnItemClickGroupName implements OnItemClickListener {
-
-	/**
-	 * Constructor.
-	 */
-	public OnItemClickGroupName() {
-	}
-
-	@Override
-	public void onItemClick(AdapterView<?> arg0, View v, int i, long l) {
-	    String group = mListGroup.get(i);
-	    buildContactList(group);
-	}
-    }
-
-    /**
-     * Sort the contact list.
-     */
-    private void sortBeemContactList() {
-	Log.d(TAG, "Sort ");
-	Collections.sort(mListContact, mComparator);
-	mAdapterContactList.notifyDataSetChanged();
+    private void hideGroups() {
+	View v = findViewById(R.id.contactlist_groupstub);
+	if (v != null)
+	    v.setVisibility(View.GONE);
     }
 
     /**
@@ -404,133 +351,210 @@
 	}
 
 	/**
-	 * Refresh the contact list.
+	 * {@inheritDoc}
+	 * Simple stategy to handle the onEntriesAdded event.
+	 * if contact has to be shown :
+	 * <ul>
+	 * <li> add him to his groups</li>
+	 * <li> add him to the specials groups</>
+	 * </ul>
 	 */
-	private class RunnableChange implements Runnable {
-	    /**
-	     * Constructor.
-	     */
-	    public RunnableChange() {
+	@Override
+	public void onEntriesAdded(final List<String> addresses) throws RemoteException {
+	    final boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+	    for (String newName : addresses) {
+		Contact contact = mRoster.getContact(newName);
+		boolean visible = !hideDisconnected || Status.statusOnline(contact.getStatus());
+		List<String> groups = contact.getGroups();
+		if (visible) {
+		    for (String group : groups) {
+			if (!mListGroup.contains(group)) {
+			    mListGroup.add(mListGroup.size() - 1, group);
+			    List<Contact> tmplist = new SortedList<Contact>(new LinkedList<Contact>(), mComparator);
+			    mContactOnGroup.put(group, tmplist);
+			}
+			List<Contact> contactByGroups = mContactOnGroup.get(group);
+			if (contactByGroups == mListContact) {
+			    updateCurrentList(group, contact);
+			    continue;
+			}
+			contactByGroups.add(contact);
+		    }
 
-	    }
-
-	    /**
-	     * {@inheritDoc}
-	     */
-	    @Override
-	    public void run() {
-		sortBeemContactList();
-		mAdapterContactList.notifyDataSetChanged();
-		mAdapterBanner.notifyDataSetChanged();
+		    // add the contact to all and no groups
+		    addToSpecialList(contact);
+		}
 	    }
 	}
 
 	/**
 	 * {@inheritDoc}
+	 * Simple stategy to handle the onEntriesDeleted event.
+	 * <ul>
+	 * <li> Remove the contact from all groups</li>
+	 * </ul>
 	 */
 	@Override
-	public void onEntriesAdded(List<String> addresses) throws RemoteException {
-	    boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
-	    for (String newName : addresses) {
-		Contact c = mRoster.getContact(newName);
-		if (!hideDisconnected || Status.statusOnline(c.getStatus())) {
-		    mContactOnGroup.get(getString(R.string.contact_list_all_contact)).add(c);
-		    if (c.getGroups().size() == 0)
-			mContactOnGroup.get(getString(R.string.contact_list_no_group)).add(c);
-		    for (String group : c.getGroups()) {
-			if (!mListGroup.contains(group)) {
-			    mListGroup.add(mListGroup.size() - 1, group);
-			    List<Contact> tmplist = new LinkedList<Contact>();
-			    mContactOnGroup.put(group, tmplist);
-			}
-			mContactOnGroup.get(group).add(c);
+	public void onEntriesDeleted(final List<String> addresses) throws RemoteException {
+	    Log.d(TAG, "onEntries deleted " + addresses);
+	    for (String cToDelete : addresses) {
+		Contact contact = new Contact(cToDelete);
+		for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
+		    List<Contact> contactByGroups = entry.getValue();
+		    if (contactByGroups == mListContact) {
+			updateCurrentList(entry.getKey(), contact);
+			continue;
 		    }
+		    contactByGroups.remove(contact);
 		}
+		cleanBannerGroup();
 	    }
-	    mHandler.post(new RunnableChange());
+
+	    mHandler.post(new Runnable() {
+		public void run() {
+		    mListContact = mContactOnGroup.get(getString(R.string.contact_list_all_contact));
+		    mAdapterContactList.notifyDataSetChanged();
+		}
+	    });
+
 	}
 
 	/**
 	 * {@inheritDoc}
+	 * Simple stategy to handle the onEntriesUpdated event.
+	 * <ul>
+	 * <li> Remove the contact from all groups</li>
+	 * <li> if contact has to be shown add it to his groups</li>
+	 * <li> if contact has to be shown add it to the specials groups</li>
+	 * </ul>
 	 */
 	@Override
-	public void onEntriesDeleted(List<String> addresses) throws RemoteException {
-	    Log.d(TAG, "onEntries deleted " + addresses);
-	    for (String cToDelete : addresses) {
-		Contact contact = mRoster.getContact(cToDelete);
-		for (List<Contact> contactByGroups : mContactOnGroup.values()) {
+	public void onEntriesUpdated(final List<String> addresses) throws RemoteException {
+	    final boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+	    for (String adr : addresses) {
+		Contact contact = mRoster.getContact(adr);
+		boolean visible = !hideDisconnected || Status.statusOnline(contact.getStatus());
+		List<String> groups = contact.getGroups();
+		for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
+		    List<Contact> contactByGroups = entry.getValue();
+		    if (contactByGroups == mListContact) {
+			updateCurrentList(entry.getKey(), contact);
+			continue;
+		    }
 		    contactByGroups.remove(contact);
+		    if (visible) {
+			for (String group : groups) {
+			    if (!mListGroup.contains(group)) {
+				mListGroup.add(mListGroup.size() - 1, group);
+				List<Contact> tmplist = new SortedList<Contact>(
+					new LinkedList<Contact>(), mComparator);
+				mContactOnGroup.put(group, tmplist);
+			    }
+			    mContactOnGroup.get(group).remove(contact);
+			}
+		    }
+
 		}
-		cleanBannerGroup();
+
+		// add the contact to all and no groups
+		if (visible) {
+		    addToSpecialList(contact);
+		}
 	    }
-	    mListContact = mContactOnGroup.get(getString(R.string.contact_list_all_contact));
-	    mHandler.post(new RunnableChange());
+	    cleanBannerGroup();
 	}
 
 	/**
 	 * {@inheritDoc}
+	 * Simple stategy to handle the onPresenceChanged event.
+	 * <ul>
+	 * <li> Remove the contact from all groups</li>
+	 * <li> if contact has to be shown add it to his groups</li>
+	 * <li> if contact has to be shown add it to the specials groups</li>
+	 * </ul>
 	 */
 	@Override
-	public void onEntriesUpdated(List<String> addresses) throws RemoteException {
-	    boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
-	    for (String adr : addresses) {
-		Contact c = mRoster.getContact(adr);
-		List<String> groups = c.getGroups();
-		for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
-		    List<Contact> contactByGroups = entry.getValue();
-		    contactByGroups.remove(c);
+	public void onPresenceChanged(PresenceAdapter presence) throws RemoteException {
+	    Log.d(TAG, "presence");
+	    String from = presence.getFrom();
+	    final boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+	    final Contact contact = mRoster.getContact(StringUtils.parseBareAddress(from));
+	    boolean visible = !hideDisconnected || Status.statusOnline(contact.getStatus());
+	    List<String> groups = contact.getGroups();
+	    for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
+		List<Contact> contactByGroups = entry.getValue();
+		if (contactByGroups == mListContact) {
+		    updateCurrentList(entry.getKey(), contact);
+		    continue;
 		}
-		if (!hideDisconnected || Status.statusOnline(c.getStatus())) {
-		    mContactOnGroup.get(getString(R.string.contact_list_all_contact)).add(c);
-		    if (c.getGroups().size() == 0)
-			mContactOnGroup.get(getString(R.string.contact_list_no_group)).add(c);
-		    for (String group : c.getGroups()) {
-			if (!mListGroup.contains(group)) {
-			    mListGroup.add(mListGroup.size() - 1, group);
-			    List<Contact> tmplist = new LinkedList<Contact>();
-			    mContactOnGroup.put(group, tmplist);
-			}
-			mContactOnGroup.get(group).add(c);
+		contactByGroups.remove(contact);
+		if (visible) {
+		    if (groups.contains(entry.getKey())) {
+			contactByGroups.add(contact);
 		    }
 		}
 	    }
-	    cleanBannerGroup();
-	    mHandler.post(new RunnableChange());
+	    if (visible) {
+		addToSpecialList(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();
+	    List<Contact> list = mContactOnGroup.get(getString(R.string.contact_list_all_contact));
+	    if (list != mListContact) {
+		list.add(contact);
+	    }
+	    list = mContactOnGroup.get(getString(R.string.contact_list_no_group));
+	    if (list != mListContact && groups.isEmpty()) {
+		list.add(contact);
+	    }
 	}
 
-	@Override
-	public void onPresenceChanged(PresenceAdapter presence) throws RemoteException {
-	    String from = presence.getFrom();
-	    boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
-	    Contact contact = mRoster.getContact(StringUtils.parseBareAddress(from));
-	    for (Map.Entry<String, List<Contact>> entry : mContactOnGroup.entrySet()) {
-		List<Contact> contactByGroups = entry.getValue();
-		if (contactByGroups.contains(contact)) {
-		    contactByGroups.remove(contact);
-		    if (!hideDisconnected || Status.statusOnline(contact.getStatus())) {
-			contactByGroups.add(contact);
+	/**
+	 * Update the current list with the status of contact.
+	 *
+	 * @param listName name of the current list
+	 * @param contact contact to update
+	 */
+	private void updateCurrentList(String listName, final Contact contact) {
+	    final boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+	    final List<String> groups = contact.getGroups();
+	    String noGroup = getString(R.string.contact_list_no_group);
+	    String allGroup = getString(R.string.contact_list_all_contact);
+	    final boolean add = ((!hideDisconnected || Status.statusOnline(contact.getStatus())) &&	// must show and
+		    (
+		     (listName.equals(noGroup) && groups.isEmpty()) ||			// in no group
+		     groups.contains(listName) ||					// or in current
+		     listName.equals(allGroup)						// or in all
+		    ));
+	    mHandler.post(new Runnable() {
+		public void run() {
+		    mListContact.remove(contact);
+		    if (add) {
+			mListContact.add(contact);
 		    }
-		} else {
-		    if (Status.statusOnline(contact.getStatus())) {
-			List<String> groups = contact.getGroups();
-			if (groups.contains(entry.getKey())) {
-			    contactByGroups.add(contact);
-			}
-		    }
+		    mAdapterContactList.notifyDataSetChanged();
 		}
-	    }
-	    Log.d(TAG, "presence");
-	    mHandler.post(new RunnableChange());
+	    });
+
 	}
 
-	private void cleanBannerGroup() {
-	    for (Iterator<String> it = mListGroup.iterator(); it.hasNext(); ){
-		String group = it.next();
-		if (mContactOnGroup.get(group).size() == 0) {
-		    mContactOnGroup.remove(group);
-		    it.remove();
-		}
-	    }
+	/**
+	 * Remove old groups on the banner.
+	 * @throws RemoteException if an error occur when communicating with the service
+	 */
+	private void cleanBannerGroup() throws RemoteException {
+	    List<String> rosterGroups = mRoster.getGroupsNames();
+	    List<String> realGroups = mListGroup.subList(1, mListContact.size() - 1);
+	    realGroups.retainAll(rosterGroups);
 	}
 
     }
@@ -600,7 +624,8 @@
 
 	    if (curContact != null) {
 		TextView v = (TextView) view.findViewById(R.id.contactlistpseudo);
-		LevelListDrawable mStatusDrawable = (LevelListDrawable) getResources().getDrawable(R.drawable.status_icon);
+		LevelListDrawable mStatusDrawable = (LevelListDrawable) getResources()
+		    .getDrawable(R.drawable.status_icon);
 		mStatusDrawable.setLevel(curContact.getStatus());
 		v.setCompoundDrawablesWithIntrinsicBounds(mStatusDrawable, null, null, null);
 		v.setText(curContact.getName());
@@ -619,8 +644,10 @@
 
 	/**
 	 * Constructor.
+	 * @param inflater the inflater use to create the view for the banner
+	 * @param groups list of the differents groups to adapt
 	 */
-	public BeemBanner(LayoutInflater inflater, List<String> groups) {
+	public BeemBanner(final LayoutInflater inflater, final List<String> groups) {
 	    mGroups = groups;
 	    mInflater = inflater;
 	}
@@ -668,22 +695,23 @@
 	    try {
 		mRoster = mXmppFacade.getRoster();
 		if (mRoster != null) {
-		    mRoster.addRosterListener(mBeemRosterListener);
 		    List<Contact> tmpContactList = mRoster.getContactList();
 		    List<String> tmpGroupList = mRoster.getGroupsNames();
 		    Collections.sort(tmpGroupList);
-		    if (mListGroup.size() > 0)
-			mListGroup.clear();
+		    mListGroup.clear();
 		    mListGroup.add(getString(R.string.contact_list_all_contact));
 		    mListGroup.addAll(tmpGroupList);
 		    mListGroup.add(getString(R.string.contact_list_no_group));
 		    assignContactToGroups(mRoster.getContactList(), tmpGroupList);
+		    makeSortedList(mContactOnGroup);
 		    if (!mSettings.getBoolean("settings_key_hide_groups", false))
 			showGroups();
 		    else
 			hideGroups();
 		    String group = getString(R.string.contact_list_all_contact);
 		    buildContactList(group);
+		    mRoster.addRosterListener(mBeemRosterListener);
+		    Log.d(TAG, "add rester listneer");
 		}
 	    } catch (RemoteException e) {
 		e.printStackTrace();
@@ -704,46 +732,116 @@
 	    mContactOnGroup.clear();
 	    mBinded = false;
 	}
+
+	/**
+	 * Assign the differents contact to their groups.
+	 * This methods will fill the mContactOnGroup map.
+	 *
+	 * @param contacts list of contacts
+	 * @param groupNames list of existing groups
+	 */
+	private void assignContactToGroups(List<Contact> contacts, List<String> groupNames) {
+	    boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
+	    mContactOnGroup.clear();
+	    List<Contact> all = new LinkedList<Contact>();
+	    List<Contact> noGroups = new LinkedList<Contact>();
+	    for (String group : groupNames) {
+		mContactOnGroup.put(group, new LinkedList<Contact>());
+	    }
+	    for (Contact c : contacts) {
+		if (hideDisconnected && !Status.statusOnline(c.getStatus())) {
+		    continue;
+		}
+		all.add(c);
+		List<String> groups = c.getGroups();
+		if (groups.isEmpty())
+		    noGroups.add(c);
+		else {
+		    for (String currentGroup : groups) {
+			List<Contact> contactsByGroups = mContactOnGroup.get(currentGroup);
+			contactsByGroups.add(c);
+		    }
+		}
+	    }
+	    mContactOnGroup.put(getString(R.string.contact_list_no_group), noGroups);
+	    mContactOnGroup.put(getString(R.string.contact_list_all_contact), all);
+	}
+
+	/**
+	 * Make the List of the map became Insertion sorted list.
+	 *
+	 * @param map the map to convert.
+	 */
+	private void makeSortedList(Map<String, List<Contact>> map) {
+	    for (Map.Entry<String, List<Contact>> entry : map.entrySet()) {
+		List<Contact> l = entry.getValue();
+		entry.setValue(new SortedList<Contact>(l, mComparator));
+	    }
+	}
     }
 
-    @Override
-    protected void finalize() {
-	Log.e(TAG, "FINALIZE");
+
+
+
+    /**
+     * Comparator Contact by status and name.
+     */
+    private static class ComparatorContactListByStatusAndName<T> implements Comparator<T> {
+	/**
+	 * Constructor.
+	 */
+	public ComparatorContactListByStatusAndName() {
+	}
+
+	@Override
+	public int compare(T c1, T c2) {
+	    if (((Contact) c1).getStatus() < ((Contact) c2).getStatus()) {
+		return 1;
+	    } else if (((Contact) c1).getStatus() > ((Contact) c2).getStatus()) {
+		return -1;
+	    } else
+		return ((Contact) c1).getName().compareToIgnoreCase(((Contact) c2).getName());
+	}
     }
 
     /**
-     * Hide the groups view.
+     * Event simple click on item of the contact list.
      */
-    private void hideGroups() {
-	View v = findViewById(R.id.contactlist_groupstub);
-	if (v != null)
-	    v.setVisibility(View.GONE);
+    private class BeemContactListOnClick implements OnItemClickListener {
+	/**
+	 * Constructor.
+	 */
+	public BeemContactListOnClick() {
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void onItemClick(AdapterView<?> arg0, View v, int pos, long lpos) {
+	    Contact c = mListContact.get(pos);
+	    Intent i = new Intent(ContactList.this, Chat.class);
+	    i.setData(c.toUri());
+	    startActivity(i);
+	}
     }
 
-    private void assignContactToGroups(List<Contact> contacts, List<String> groupNames) {
-	boolean hideDisconnected = mSettings.getBoolean(SETTINGS_HIDDEN_CONTACT, false);
-	mContactOnGroup.clear();
-	List<Contact> all = new LinkedList<Contact>();
-	List<Contact> noGroups = new LinkedList<Contact>();
-	for (String group: groupNames) {
-	    mContactOnGroup.put(group, new LinkedList<Contact>());
+    /**
+     * Event simple click on middle groupe name.
+     */
+    private class OnItemClickGroupName implements OnItemClickListener {
+
+	/**
+	 * Constructor.
+	 */
+	public OnItemClickGroupName() {
 	}
-	for (Contact c : contacts) {
-	    if (hideDisconnected && !Status.statusOnline(c.getStatus())) {
-		continue;
-	    }
-	    all.add(c);
-	    List<String> groups = c.getGroups();
-	    if (groups.size() == 0)
-		noGroups.add(c);
-	    else {
-		for (String currentGroup : groups) {
-		    List<Contact> contactsByGroups = mContactOnGroup.get(currentGroup);
-		    contactsByGroups.add(c);
-		}
-	    }
+
+	@Override
+	public void onItemClick(AdapterView<?> arg0, View v, int i, long l) {
+	    String group = mListGroup.get(i);
+	    buildContactList(group);
 	}
-	mContactOnGroup.put(getString(R.string.contact_list_no_group), noGroups);
-	mContactOnGroup.put(getString(R.string.contact_list_all_contact), all);
     }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/utils/SortedList.java	Tue Jun 01 21:32:39 2010 +0200
@@ -0,0 +1,312 @@
+/*
+    BEEM is a videoconference application on the Android Platform.
+
+    Copyright (C) 2009 by Frederic-Charles Barthelery,
+                          Jean-Manuel Da Silva,
+                          Nikita Kozlov,
+                          Philippe Lago,
+                          Jean Baptiste Vergely,
+                          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://dev.beem-project.com/
+
+*/
+package com.beem.project.beem.utils;
+
+import java.util.List;
+import java.util.Comparator;
+import java.util.ListIterator;
+import java.util.Iterator;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * This class add a sort by insertion to a List.
+ * All methods which allow you to insert an object at a specific index
+ * will throw an UnsupportedOperationException.
+ *
+ * @author Da Risk <da_risk@beem-project.com>
+ * @param <E> the type of elements maintained by this list
+ */
+public class SortedList<E> implements List<E> {
+
+    private final List<E> mBackend;
+    private final Comparator<? super E> mComparator;
+
+    /**
+     * Create a SortedList. The existing elements will be sorted.
+     *
+     * @param list list to sort
+     * @param mComparator mComparator to use.
+     */
+    public SortedList(final List<E> list, final Comparator<? super E> mComparator) {
+	this.mComparator = mComparator;
+	this.mBackend = list;
+	Collections.sort(mBackend, mComparator);
+    }
+
+    @Override
+    public int size() {
+	return mBackend.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+	return mBackend.isEmpty();
+    }
+
+    @Override
+    public boolean contains(Object o) {
+	return mBackend.contains(o);
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+	return new SortedListIterator<E>(mBackend.listIterator());
+    }
+
+    @Override
+    public Object[] toArray() {
+	return mBackend.toArray();
+    }
+
+    @Override
+    public <T> T[] toArray(T[] a) {
+	return mBackend.toArray(a);
+    }
+
+    @Override
+    public boolean add(E e) {
+	for (ListIterator<E> it = mBackend.listIterator(); it.hasNext();) {
+	    if (mComparator.compare(e, it.next()) < 0) {
+		if (it.hasPrevious()) {
+		    it.previous();
+		}
+		it.add(e);
+		return true;
+	    }
+	}
+	mBackend.add(e);
+	return true;
+    }
+
+    @Override
+    public boolean remove(Object o) {
+	return mBackend.remove(o);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+	return mBackend.containsAll(c);
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends E> c) {
+	boolean result = false;
+	for (E e : c) {
+	    boolean t = add(e);
+	    if (t) {
+		result = t;
+	    }
+	}
+	return result;
+    }
+
+    /**
+     * Add all the elements in the specified collection.
+     * The index param is ignored.
+     *
+     * @param index ignored
+     * @param c collection containing elements to be added to this list
+     * @return true if this list changed as a result of the call
+     */
+    @Override
+    public boolean addAll(int index, Collection<? extends E> c) {
+	return addAll(c);
+    }
+
+    /**
+     * Add all the elements in the specified collection.
+     * The index param is ignored.
+     *
+     * @param l collection containing elements to be added to this list
+     * @return true if this list changed as a result of the call
+     * @see addAll(Collection)
+     */
+    public boolean addAll(SortedList<? extends E> l) {
+	if (!l.isEmpty()) {
+	    if (mBackend.isEmpty()) {
+		return mBackend.addAll(l);
+	    }
+	    boolean result = false;
+	    E myfirst = mBackend.get(0);
+	    E last = l.get(l.size() - 1);
+	    E mylast = mBackend.get(mBackend.size() - 1);
+	    E first = l.get(0);
+	    if (mComparator.compare(last, myfirst) < 0) {
+		result = mBackend.addAll(0, l);
+	    } else if (mComparator.compare(first, mylast) > 0) {
+		result = mBackend.addAll(l);
+	    } else {
+		Collection<? extends E> c = l;
+		result = addAll(c);
+	    }
+	    return result;
+	}
+	return false;
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+	return mBackend.removeAll(c);
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+	return mBackend.retainAll(c);
+    }
+
+    @Override
+    public void clear() {
+	mBackend.clear();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+	return mBackend.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+	return mBackend.hashCode();
+    }
+
+    @Override
+    public E get(int index) {
+	return mBackend.get(index);
+    }
+
+    @Override
+    public E set(int index, E element) {
+	throw new UnsupportedOperationException("set() is not supported in SortedList");
+    }
+
+    @Override
+    public void add(int index, E element) {
+	throw new UnsupportedOperationException("add at specific index is not supported in SortedList");
+    }
+
+    @Override
+    public E remove(int index) {
+	return mBackend.remove(index);
+    }
+
+    @Override
+    public int indexOf(Object o) {
+	return mBackend.indexOf(o);
+    }
+
+    @Override
+    public int lastIndexOf(Object o) {
+	return mBackend.lastIndexOf(o);
+    }
+
+    @Override
+    public ListIterator<E> listIterator() {
+	return new SortedListIterator<E>(mBackend.listIterator());
+    }
+
+    @Override
+    public ListIterator<E> listIterator(int index) {
+	return new SortedListIterator<E>(mBackend.listIterator(index));
+    }
+
+    @Override
+    public List<E> subList(int fromIndex, int toIndex) {
+	return mBackend.subList(fromIndex, toIndex);
+    }
+
+    @Override
+    public String toString() {
+	return mBackend.toString();
+    }
+
+    /**
+     * A SortedList.iterator don't allow list modification.
+     * It use the mBackend iterator for the other operations.
+     */
+    private class SortedListIterator<E> implements ListIterator<E> {
+
+	private ListIterator<E> mIt;
+
+	/**
+	 * Construct SortedList.Iterator.
+	 *
+	 * @param iterator the iterator of the backend list
+	 */
+	SortedListIterator(final ListIterator<E> iterator) {
+	    mIt = iterator;
+	}
+
+	@Override
+	public void add(E e) {
+	    throw new UnsupportedOperationException("add() not supported in SortedList iterator");
+	}
+
+	@Override
+	public boolean hasNext() {
+	    return mIt.hasNext();
+	}
+
+	@Override
+	public E next() {
+	    return mIt.next();
+	}
+
+	@Override
+	public boolean hasPrevious() {
+	    return mIt.hasPrevious();
+	}
+
+	@Override
+	public E previous() {
+	    return mIt.previous();
+	}
+
+	@Override
+	public int nextIndex() {
+	    return mIt.nextIndex();
+	}
+
+	@Override
+	public int previousIndex() {
+	    return mIt.previousIndex();
+	}
+
+	@Override
+	public void remove() {
+	    mIt.remove();
+	}
+
+	@Override
+	public void set(E e) {
+	    throw new UnsupportedOperationException("set () not supported in SortedList iterator");
+	}
+    }
+}