/* ContactListAdapter.java
*
* Copyright 2011 Aleksey Konovalov
* All Rights Reserved.
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ru.chatty.app;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import ru.chatty.engine.AccountsManager;
import ru.chatty.im.Account;
import ru.chatty.im.Contact;
import ru.chatty.im.ContactListListener;
import ru.chatty.im.MessagesListener;
import ru.chatty.im.ProtocolFeatures;
import ru.chatty.service.ChattyService;
import ru.chatty.service.Preferences;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.BaseExpandableListAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class ContactListAdapter extends BaseExpandableListAdapter implements
ContactListListener, MessagesListener, OnSharedPreferenceChangeListener {
private static final String LOG_TAG = "Chatty:ContactListAdapter";
//
private HashMap<String, Integer> groupsIndex = new HashMap<String, Integer>();
// , .
// , ,
//
private HashMap<Contact, Integer> contactsIndex = new HashMap<Contact, Integer>();
//
private List<Group> groups = new ArrayList<Group>();
private LayoutInflater inflater;
private final AlphaAnimation unreadMessageAnim;
// private final Activity activity;
private AccountsManager accountsManager = null;
private SharedPreferences preferences;
private volatile boolean hideOfflineContacts;
private final Activity mActivity;
Comparator<Contact> contactsComparator = new Comparator<Contact>() {
@Override
public int compare(Contact c1, Contact c2) {
if (c1.unreadMessages())
return c2.unreadMessages() ? 0 : -1;
if (c2.unreadMessages())
return 1;
Boolean c1Online = c1.getMainStatus() != Contact.MAIN_STATUS_OFFLINE;
Boolean c2Online = c2.getMainStatus() != Contact.MAIN_STATUS_OFFLINE;
return c2Online.compareTo(c1Online);
}
};
private final class Group {
public String groupName;
public List<Contact> contacts = new ArrayList<Contact>();
public int onlineCount = 0;
public Group(String name) {
groupName = name;
}
}
public ContactListAdapter(Activity activity) {
// this.activity = activity;
inflater = LayoutInflater.from(activity);
mActivity = activity;
preferences = PreferenceManager.getDefaultSharedPreferences(activity);
preferences.registerOnSharedPreferenceChangeListener(this);
hideOfflineContacts = preferences.getBoolean(
Preferences.PREF_HIDE_OFFLINE_CONTACTS, false);
unreadMessageAnim = new AlphaAnimation(1.0f, 0.6f);
unreadMessageAnim.setRepeatCount(Animation.INFINITE);
unreadMessageAnim.setRepeatMode(Animation.REVERSE);
unreadMessageAnim.setDuration(300);
unreadMessageAnim.start();
final ChattyApplication app = ChattyApplication
.getApplication(activity);
app.callWhenServiceConnected(new Runnable() {
@Override
public void run() {
ChattyService service = app.getService();
if (service != null) {
accountsManager = service.getAccountsManager();
accountsManager
.registerContactListListener(ContactListAdapter.this);
accountsManager
.registerMessagesListener(ContactListAdapter.this);
notifyDataSetChanged();
} else
Log.e(LOG_TAG, "Service loaded, but equals null");
}
});
}
private synchronized int getGroupIndexByName(String groupName) {
Integer groupId = groupsIndex.get(groupName);
if (groupId != null)
return groupId;
groups.add(new Group(groupName));
int pos = groups.size() - 1;
groupsIndex.put(groupName, pos);
return pos;
}
private void sortContacts(List<Contact> contacts) {
Collections.sort(contacts, contactsComparator);
}
public final void uninitialize() {
if (accountsManager != null)
accountsManager.unregisterContactListListener(this);
preferences.unregisterOnSharedPreferenceChangeListener(this);
}
/*
* public static View getItemViewIfVisible(AdapterView<?> holder, int
* itemPos) { int firstPosition = holder.getFirstVisiblePosition(); int
* wantedChild = itemPos - firstPosition; if (wantedChild < 0 || wantedChild
* >= holder.getChildCount()) return null; return
* holder.getChildAt(wantedChild); }
*
* public static void invalidateByPos(AdapterView<?> parent, int position) {
* final View itemView = getItemViewIfVisible(parent, position); if
* (itemView != null) itemView.invalidate(); }
*/
public final void update() {
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
notifyDataSetInvalidated();
}
});
}
@Override
public synchronized Contact getChild(int groupPosition, int childPosition) {
return groups.get(groupPosition).contacts.get(childPosition);
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = inflater.inflate(R.layout.contact_list_item, null);
Contact contact;
synchronized (this) {
Group g = groups.get(groupPosition);
if (g == null) {
Log.w(LOG_TAG, "getChildView: group not found");
return convertView;
}
contact = g.contacts.get(childPosition);
}
ProtocolFeatures features = contact.getAccount().getProtocolFeatures();
TextView contactName = (TextView) convertView
.findViewById(R.id.ContactName);
contactName.setText(contact.getNick());
ImageView statusImage = (ImageView) convertView
.findViewById(R.id.StatusImage);
int statusPictId = features.getMainStatusPictureId(contact
.getMainStatus());
statusImage.setImageResource(statusPictId);
statusImage.setAnimation(contact.unreadMessages() ? unreadMessageAnim
: null);
Contact.AdditionalStatus additionalStatus = contact
.getAdditionalStatus();
ImageView additionalStatusImage = (ImageView) convertView
.findViewById(R.id.AdditionalStatusImage);
int additionalStatusResId = features
.getAdditionalStatusPictureId(additionalStatus.status);
additionalStatusImage.setImageResource(additionalStatusResId);
String statusText = "";
if (!TextUtils.isEmpty(additionalStatus.title))
statusText = additionalStatus.title + ' ';
if (!TextUtils.isEmpty(additionalStatus.description))
statusText += additionalStatus.description;
TextView additionalStatusText = (TextView) convertView
.findViewById(R.id.AdditionalStatusText);
if (!TextUtils.isEmpty(statusText)) {
additionalStatusText.setText(statusText);
additionalStatusText.setVisibility(TextView.VISIBLE);
} else
additionalStatusText.setVisibility(TextView.INVISIBLE);
return convertView;
}
@Override
public synchronized int getChildrenCount(int groupPosition) {
Group group = groups.get(groupPosition);
return hideOfflineContacts ? group.onlineCount : group.contacts.size();
}
@Override
public synchronized Group getGroup(int groupPosition) {
return groups.get(groupPosition);
}
@Override
public synchronized int getGroupCount() {
return groups.size();
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.contact_list_group, null);
}
TextView groupNameView = (TextView) convertView
.findViewById(R.id.GroupName);
TextView groupStatView = (TextView) convertView
.findViewById(R.id.GroupStat);
String groupName;
String groupStat;
synchronized (this) {
Group group = getGroup(groupPosition);
groupName = group.groupName;
groupStat = group.onlineCount + "/" + group.contacts.size();
}
groupNameView.setText(groupName);
groupStatView.setText(groupStat);
return convertView;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
// ContactListListener
@Override
public void onAddUser(Account account, Contact user) {
synchronized (this) {
int groupIndex = getGroupIndexByName(user.getGroupName());
Group group = groups.get(groupIndex);
List<Contact> contacts = group.contacts;
if (user.getMainStatus() != Contact.MAIN_STATUS_OFFLINE)
++group.onlineCount;
contacts.add(user);
contactsIndex.put(user, groupIndex);
sortContacts(contacts);
}
update();
}
@Override
public void onDeleteUser(Account account, Contact user) {
// TODO Auto-generated method stub
}
@Override
public final void onStatusChanged(Account account, Contact user, int oldStatus) {
boolean oldStatusIsOffline = oldStatus == Contact.MAIN_STATUS_OFFLINE;
boolean newStatusIsOffline = user.getMainStatus() == Contact.MAIN_STATUS_OFFLINE;
if (oldStatusIsOffline != newStatusIsOffline) {
synchronized (this) {
Integer groupIndex = contactsIndex.get(user);
if (groupIndex != null) {
Group group = groups.get(groupIndex);
sortContacts(group.contacts);
if (oldStatusIsOffline)
++group.onlineCount;
else
--group.onlineCount;
}
}
}
if (oldStatus != user.getMainStatus())
update();
}
@Override
public final void onAdditionalStatusChanged(Account account, Contact user) {
update();
}
@Override
public void onChangeUserInfo(Account account, Contact user) {
// TODO Auto-generated method stub
}
@Override
public void onUpdateContactList(Account account, List<Contact> contactList) {
synchronized (this) {
for (Contact contact : contactList) {
// ,
Integer oldGroupIndex = contactsIndex.get(contact);
if (oldGroupIndex != null) {
Group oldGroup = groups.get(oldGroupIndex);
oldGroup.contacts.remove(contact);
contactsIndex.remove(contact);
}
int groupIndex = getGroupIndexByName(contact.getGroupName());
Group group = groups.get(groupIndex);
group.contacts.add(contact);
if (contact.getMainStatus() != Contact.MAIN_STATUS_OFFLINE)
++group.onlineCount;
contactsIndex.put(contact, groupIndex);
}
for (Group group : groups)
sortContacts(group.contacts);
}
update();
}
// MessagesListener
@Override
public synchronized void onMessage(String accountID, String message,
Contact contact) {
Integer groupIndex = contactsIndex.get(contact);
if (groupIndex != null) {
List<Contact> contacts = groups.get(groupIndex).contacts;
sortContacts(contacts);
update();
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
if (key.equals(Preferences.PREF_HIDE_OFFLINE_CONTACTS)) {
hideOfflineContacts = prefs.getBoolean(key, false);
update();
}
}
}
|