/*
* Gamers Own Instant Messenger
* Copyright (C) 2005-2006 Herbert Poul (kahless@sphene.net)
* http://goim.sphene.net
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
package net.sphene.goim.rcp.simpleui;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import net.sphene.goim.rcp.GOIMPlugin;
import net.sphene.goim.rcp.beans.GOIMAccount;
import net.sphene.goim.rcp.beans.GOIMAccountList;
import net.sphene.goim.rcp.beans.GOIMGameItem;
import net.sphene.goim.rcp.beans.GOIMRosterListener;
import net.sphene.goim.rcp.extensionpoints.IContactListView;
import net.sphene.goim.rcp.extensionpoints.GameExtensionPoint.GameExtensionProxy;
import net.sphene.goim.rcp.extensionpoints.IGame.IGameExtension;
import net.sphene.goim.rcp.preferences.PreferenceConstants;
import net.sphene.goim.rcp.ui.AbstractContactList;
import net.sphene.goim.rcp.ui.GOIMIcons;
import net.sphene.goim.rcp.ui.ContactList.EntryMenu;
import net.sphene.goim.rcp.xmpp.StatusChangedEvent;
import net.sphene.libs.SpheneEvent;
import net.sphene.libs.SpheneListener;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.custom.TreeEditor;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowData;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.util.StringUtils;
/**
* This is the default contact list. Called 'simple' because it simply uses
* a TreeView and not a custom widget, or a a combination of widgets like the 'fancy'
* contact list ({@link net.sphene.goim.rcp.ui.ContactList})<br><br>
*
* It uses a {@link org.eclipse.swt.custom.TreeEditor} to overlay gaim icons.
*/
public class SimpleContactList extends AbstractContactList implements
IContactListView {
public static final String NO_GROUP_NAME = "Default";
public static final String NO_GROUP_COMPONENT = "Components (Transports)";
/**
* If this SimpleContactList handles all accounts in one list .. this list of accounts
* is set.
* @see #account
*/
GOIMAccountList accountList;
public GOIMAccountList getAccountList() { return accountList; }
private Tree contactList;
/**
* The GOIMAccount - only set if this SimpleContactList handles only ONE account ..
* @see #accountList
* @see AbstractContactList#getActiveAccount()
*/
GOIMAccount account;
IContactListView container;
boolean wasInit = false;
boolean hideOffline = false;
EntryMenu entryMenu;
public void setColorsFromStore() {
IPreferenceStore store = GOIMPlugin.getDefault().getPreferenceStore();
// should not happen.. but .. it does.. so .. test it..
if(contactList.isDisposed()) return;
if(store.getBoolean(PreferenceConstants.P_SIMPLE_CONTACTLIST_CUSTOMIZE_COLORS)) {
RGB rgb = PreferenceConverter.getColor(store,PreferenceConstants.P_SIMPLE_CONTACTLIST_COLORS_BACKGROUND);
contactList.getParent().setBackground(new Color(contactList.getDisplay(),rgb));
contactList.setBackground(new Color(contactList.getDisplay(),rgb));
rgb = PreferenceConverter.getColor(store,PreferenceConstants.P_SIMPLE_CONTACTLIST_COLORS_TEXT);
contactList.setForeground(new Color(contactList.getDisplay(),rgb));
} else {
contactList.setBackground(null);
contactList.getParent().setBackground(contactList.getBackground());
contactList.setForeground(null);
}
if(store.getBoolean(PreferenceConstants.P_SIMPLE_CONTACTLIST_CUSTOMIZE_FONTS)) {
contactList.setFont(new Font(contactList.getDisplay(),PreferenceConverter.getFontData(store,PreferenceConstants.P_SIMPLE_CONTACTLIST_FONTS_DEFAULT)));
} else {
contactList.setFont(null);
}
}
public class TreeGroup {
public RosterGroup group;
public String groupname;
public List<TreeEntry> entries;
public GOIMAccount account;
public TreeItem item;
public TreeItem parent;
public TreeGroup(GOIMAccount account, TreeItem parent, RosterGroup group, String groupName) {
this.account = account;
this.group = group;
this.parent = parent;
this.groupname = groupName;
this.entries = new LinkedList<TreeEntry>();
this.item = null;
}
public void remove(RosterEntry entry) {
ListIterator<TreeEntry> i = entries.listIterator();
while (i.hasNext()) {
TreeEntry treeEntryCompare = i.next();
if (treeEntryCompare.entry.getUser().equals(entry.getUser())) {
i.remove();
treeEntryCompare.dispose();
break;
}
}
}
public boolean updateSelf(Roster roster, RosterGroup group) {
Iterator i;
if(group == null) {
if(this.group != null) {
item.dispose();
return true;
}
i = roster.getUnfiledEntries();
} else
i = group.getEntries();
this.group = group;
LinkedList<TreeEntry> oldEntries = new LinkedList<TreeEntry>(this.entries);
while(i.hasNext()) {
RosterEntry entry = (RosterEntry)i.next();
if(group == null) {
if(groupname.equals(NO_GROUP_COMPONENT)) {
if(entry.getUser().indexOf('@') > -1 && !entry.getUser().equals(GOIMAccount.STATSCONTACTJID))
continue;
} else if(groupname.equals(NO_GROUP_NAME)) {
if(entry.getUser().indexOf('@') < 0 || entry.getUser().equals(GOIMAccount.STATSCONTACTJID))
continue;
}
}
Iterator<TreeEntry> j = oldEntries.iterator();
boolean found = false;
while(j.hasNext()) {
TreeEntry treeEntry = j.next();
if(treeEntry.entry.getUser().equals(entry.getUser())) {
j.remove();
update(treeEntry);
found = true;
break;
}
}
if(!found)
update(new TreeEntry(account,this,entry));
}
if(oldEntries.size() > 0) {
Iterator<TreeEntry> j = oldEntries.iterator();
while(j.hasNext()) {
TreeEntry treeEntry = j.next();
entries.remove(treeEntry);
treeEntry.dispose();
}
}
return false;
}
public void update(TreeEntry treeEntry) {
ListIterator<TreeEntry> i = entries.listIterator();
boolean found = false;
while (i.hasNext()) {
TreeEntry treeEntryCompare = i.next();
if (treeEntryCompare.equals(treeEntry)) {
found = true;
treeEntry = treeEntryCompare;
if(!treeEntry.wantsToBeVisible()) {
// i.remove();
// treeEntry.dispose();
} else {
if(treeEntry.item != null && !treeEntry.item.isDisposed()) {
RosterEntry entry = treeEntry.entry;
Roster roster = account.xmpp.getRoster();
Presence presence = (roster == null ? null : roster.getPresence(entry.getUser()));
if(item.getData("presence") == presence) return;
// updatePresenceOfItem(item, entry, (roster == null ? null : presence));
// return;
}
}
i.remove();
treeEntry.dispose();
break;
}
}
if (!found) {
}
if (treeEntry.wantsToBeVisible()) {
// Find place to insert treeEntry
testVisibility(true);
i = entries.listIterator();
int j = 0;
while (i.hasNext()) {
TreeEntry treeEntryCompare = i.next();
if (treeEntry.comesBefore(treeEntryCompare)) {
i.previous();
break;
}
j++;
}
i.add(treeEntry);
treeEntry.createTreeItem(j);
item.setExpanded(true);
} else {
testVisibility(false);
}
}
public int getIndexOfItem() {
TreeItem[] items;
if (parent != null)
items = parent.getItems();
else
items = contactList.getItems();
if (groupname.equals(NO_GROUP_COMPONENT))
return items.length;
int i = 0;
for (TreeItem item : items) {
if (item.getData("entryjid") == null
&& // Own Presence Entry is always first in the list
(item.getText().compareToIgnoreCase(groupname) > 0 || item
.getText().equals(NO_GROUP_COMPONENT))) // Components
// are
// last
return i;
i++;
}
return i;
}
public void testVisibility(boolean needsCreation) {
if (needsCreation && item == null) {
int index = getIndexOfItem();
if (parent != null) {
item = new TreeItem(parent, SWT.NULL, index);
} else {
item = new TreeItem(contactList, SWT.NULL, index);
}
item.setData("account",account);
item.setText(groupname);
item.setImage(GOIMIcons.getImage(GOIMIcons.FOLDER_ICON));
} else if (!needsCreation && item != null) {
if (entries.size() < 1) {
item.dispose();
item = null;
}
}
}
}
public class TreeEntry {
protected GOIMAccount account;
protected RosterEntry entry;
protected TreeItem item;
protected TreeGroup parent;
public TreeEntry(GOIMAccount account, TreeGroup parent,
RosterEntry entry) {
this.account = account;
this.entry = entry;
this.parent = parent;
}
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof TreeEntry) {
return (((TreeEntry) obj).entry.getUser().equals(entry
.getUser()));
}
return false;
}
public void dispose() {
if (item != null) {
item.dispose();
item = null;
}
}
// public boolean wantsToBeVisible() {
// boolean visible = wantsToBeVisibleInt();
// if(!visible && item != null) {
// item.dispose(); item = null;
// }
// return visible;
// }
// private boolean wantsToBeVisibleInt() {
public boolean wantsToBeVisible() {
if (!hideOffline || entry.getUser().indexOf('@') < 0)
return true;
Roster roster = account.xmpp.getRoster();
if (roster == null)
return false;
Presence p = roster.getPresence(entry.getUser());
if (p == null || p.getType() != Presence.Type.AVAILABLE)
return false;
return true;
}
public boolean comesBefore(TreeEntry treeEntry) {
int p1val = 0;
int p2val = 0;
Roster roster = account.xmpp.getRoster();
if (roster != null) {
p1val = getPresenceValue(roster.getPresence(entry.getUser()));
p2val = getPresenceValue(roster.getPresence(treeEntry.entry
.getUser()));
}
if (p1val > p2val)
return true;
if (p1val == p2val)
return getRosterLabel(entry).compareToIgnoreCase(
getRosterLabel(treeEntry.entry)) < 0;
return false;
}
public void createTreeItem(int index) {
item = new TreeItem(parent.item, SWT.NULL, index);
item.setText(getRosterLabel(entry));
item.setData("entry", entry);
item.setData("account", account);
Roster roster = account.xmpp.getRoster();
Presence presence = roster == null ? null : roster.getPresence(entry.getUser());
item.setData("presence",presence);
updatePresenceOfItem(item, entry, presence);
}
}
public SimpleContactList(Composite parent, int style,
IContactListView container) {
super(parent, style);
this.container = container;
}
public void init() {
if(wasInit)
for(Control control : getChildren()) control.dispose();
setLayout(new GridLayout(1,false));
// Composite topComposite = new Composite(this,SWT.NULL);
// RowLayout topCompositeLayout = new RowLayout();
// topComposite.setLayout(topCompositeLayout);
// final Button hideOfflineContacts = new Button(topComposite,SWT.TOGGLE);
// hideOfflineContacts.setText("Hide Offline Contacts");
// hideOfflineContacts.setSelection(hideOffline);
// hideOfflineContacts.addListener(SWT.Selection,new Listener(){
// public void handleEvent(Event event) {
// setHideOfflineContacts(!getHideOfflineContacts());
// }});
// Group contactListGroup = new Group(this,SWT.SHADOW_NONE);
Composite contactListGroup = new Composite(this,SWT.BORDER);
contactListGroup.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));
GridLayout contactListGroupLayout = new GridLayout(1,false);
contactListGroupLayout.marginHeight =
contactListGroupLayout.marginWidth = 5;
contactListGroup.setLayout(contactListGroupLayout);
contactList = new Tree(contactListGroup,SWT.FULL_SELECTION);
contactList.setLayoutData(new GridData(SWT.FILL,SWT.FILL,true,true));
contactListGroup.setBackground(contactList.getBackground());
entryMenu = new EntryMenu(contactList);
final TreeColumn jid = new TreeColumn(contactList,SWT.LEFT);
jid.setText("JID");
contactList.addListener(SWT.Resize,new Listener() {
public void handleEvent(Event event) {
jid.setWidth(contactList.getClientArea().width-10);
} });
contactList.addListener(SWT.KeyDown,new Listener() {
public void handleEvent(Event event) {
switch(event.keyCode) {
case SWT.DEL:
TreeItem[] items = contactList.getSelection();
if(items == null || items.length < 1) return;
RosterEntry entry = (RosterEntry)items[0].getData("entry");
if(entry != null)
getActiveAccount().xmpp.removeContact(entry,contactList.getShell());
break;
}
}
});
// TreeColumn games = new TreeColumn(contactList,SWT.CENTER);
// games.setText("Games");
// jid.pack();
// jid.setWidth(200);
// games.pack();
contactList.setHeaderVisible(false);
createMenu(getShell());
ContactListMouseListener mouseListener = new ContactListMouseListener();
contactList.addMouseListener(mouseListener);
contactList.addMouseMoveListener(mouseListener);
IPreferenceStore store = GOIMPlugin.getDefault().getPreferenceStore();
final IPropertyChangeListener propertyChangeListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
setColorsFromStore();
} };
store.addPropertyChangeListener(propertyChangeListener);
contactList.addListener(SWT.Dispose,new Listener() {
public void handleEvent(Event event) {
IPreferenceStore store = GOIMPlugin.getDefault().getPreferenceStore();
store.removePropertyChangeListener(propertyChangeListener);
}
});
setColorsFromStore();
}
public class ContactListMouseListener implements MouseMoveListener, MouseListener {
Point dragLastPoint;
//Point relativeMousePosition;
Rectangle shellPosition;
public void mouseDoubleClick(MouseEvent e) {
TreeItem[] items = contactList.getSelection();
if(items.length < 1) return;
TreeItem item = items[0];
RosterEntry entry = (RosterEntry)item.getData("entry");
GOIMAccount account = (GOIMAccount)item.getData("account");
if(entry == null) return;
account.chatWindowExtensionManager.openChatWindow(entry.getUser(),true);
}
public void mouseDown(MouseEvent e) {
if(e.button == 1) {
Point point = new Point(e.x,e.y);
// TreeItem item = contactList.getItem(point);
// if(item == null) {
dragLastPoint = point;
shellPosition = contactList.getShell().getBounds();
// }
// } else if((e.stateMask & SWT.BUTTON3) != 0 ||
// (e.stateMask & SWT.BUTTON2) != 0) {
} else if(e.button == 3 || e.button == 2) {
TreeItem item = contactList.getItem(new Point(e.x,e.y));
// TreeItem[] items = contactList.getSelection();
if(item == null) {
contactList.setSelection(new TreeItem[]{});
contextMenu.setVisible(true);
return;
}
contactList.setSelection(new TreeItem[]{item});
// TreeItem item = items[0];
setActiveAccount((GOIMAccount)item.getData("account"));
if(getActiveAccount() == null) {
contextMenu.setVisible(true);
return;
}
RosterEntry entry = (RosterEntry) item.getData("entry");
GOIMAccount account = (GOIMAccount) item.getData("account");
if(entry == null)
contextMenu.setVisible(true);
else {
entryMenu.open(account,entry,null);
}
}
}
public void mouseUp(MouseEvent e) {
dragLastPoint = null;
}
public void mouseMove(MouseEvent e) {
if(dragLastPoint != null) {
Shell shell = contactList.getShell();
//Rectangle bounds = shell.getBounds();
//System.out.println("Moved: " + (e.x - dragLastPoint.x) + " / " + (e.y - dragLastPoint.y));
shellPosition.x += e.x - dragLastPoint.x;
shellPosition.y += e.y - dragLastPoint.y;
shell.setBounds(shellPosition);
// shell.setBounds(e.x,e.y,bounds.width,bounds.height);
// shell.setBounds(bounds.x + (e.x - dragLastPoint.x),
// bounds.y + (e.y - dragLastPoint.y),
// bounds.width,bounds.height);
// dragLastPoint.x = e.x;
// dragLastPoint.y = e.y;
} else {
TreeItem item = contactList.getItem(new Point(e.x,e.y));
if(item != null) {
GOIMAccount account = (GOIMAccount)item.getData("account");
RosterEntry entry = (RosterEntry)item.getData("entry");
if(entry != null) {
String toolTipText = getToolTipTextForEntry(account,entry);
if(!toolTipText.equals(contactList.getToolTipText())) {
contactList.setToolTipText(toolTipText);
}
} else
contactList.setToolTipText(null);
} else {
contactList.setToolTipText(null);
}
}
}
}
public String getToolTipTextForEntry(GOIMAccount account, RosterEntry entry) {
StringBuffer buf = new StringBuffer();
if (entry.getName() != null) {
buf.append(entry.getName()).append("\n");
}
buf.append('[').append(entry.getUser()).append("]\nSubscription: ");
buf.append(entry.getType().toString());
Roster roster = account.xmpp.getRoster();
if (roster != null) {
Iterator i = roster.getPresences(entry.getUser());
if (i == null)
buf.append("\n\nOffline");
else
while (i.hasNext()) {
Presence p = (Presence) i.next();
buf.append("\n\nPresence: ").append(p.getFrom()).append(
"\n").append(p.getType().toString()).append(" ")
.append(p.getMode().toString()).append("\n");
if (p.getStatus() != null)
buf.append(p.getStatus());
}
}
return buf.toString();
}
public void initWithAccountList(GOIMAccountList list) {
GOIMPlugin.getDefault().registerContactListOfAllAccounts(container);
init();
this.accountList = list;
loadList();
layout(true);
}
public void initWithAccount(final GOIMAccount account) {
GOIMPlugin.getDefault().registerContactList(account, container);
init();
this.account = account;
Composite presenceComposite = new Group(this, SWT.SHADOW_NONE);
presenceComposite.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
GridLayout presenceCompositeLayout = new GridLayout(3, false);
// presenceCompositeLayout.marginHeight = 0;
// presenceCompositeLayout.marginWidth = 0;
presenceComposite.setLayout(presenceCompositeLayout);
final Label presence = new Label(presenceComposite, SWT.NULL);
GridData presenceData = new GridData(SWT.CENTER,SWT.CENTER,false,false);
presence.setLayoutData(presenceData);
final Label presenceLabel = new Label(presenceComposite, SWT.NULL);
presenceLabel.setLayoutData(new GridData(SWT.FILL,SWT.CENTER,true,false));
Button presenceButton = new Button(presenceComposite, SWT.ARROW | SWT.DOWN);
presence.setImage(GOIMIcons.getImageForPresence(null, account.xmpp
.getOwnPresence()));
presenceLabel.setText(GOIMIcons.getShowTextForPresence(account.xmpp
.getOwnPresence()));
presenceLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
false));
setActiveAccount(account);
SpheneListener<StatusChangedEvent> ownPresenceChangedListener = new SpheneListener<StatusChangedEvent>() {
public void handleEvent(StatusChangedEvent arg0) {
presence.getDisplay().asyncExec(new Runnable() {
public void run() {
Presence p = account.xmpp.getOwnPresence();
presence.setImage(GOIMIcons
.getImageForPresence(null, p));
presenceLabel.setText(GOIMIcons
.getShowTextForPresence(account.xmpp
.getOwnPresence()));
}
});
}
};
account.xmpp.ownPresenceChanged.addListener(ownPresenceChangedListener);
presence.setMenu(contextMenu);
presenceLabel.setMenu(contextMenu);
Listener showMenuListener;
presence.addListener(SWT.MouseDown, showMenuListener = new Listener() {
public void handleEvent(Event event) {
contextMenu.setVisible(true);
}
});
presenceLabel.addListener(SWT.MouseDown, showMenuListener);
presenceButton.addListener(SWT.MouseDown, showMenuListener);
presenceComposite.addListener(SWT.MouseDown, showMenuListener);
addAccount(account);
layout(true);
this.addListener(SWT.Dispose, RemoveListener.getRemoveListener(
account.xmpp.ownPresenceChanged, ownPresenceChangedListener));
}
public void initWithout() {
wasInit = true;
this.setLayout(new RowLayout(SWT.VERTICAL));
Button button = new Button(this, SWT.PUSH);
button.setText("Manage all Accounts");
Listener listener = new Listener() {
public void handleEvent(Event event) {
GOIMAccount account = (GOIMAccount) event.widget
.getData("account");
if (account == null)
container.initWithAccountList(GOIMPlugin
.getPreferenceObject(GOIMAccountList.class));
else
container.initWithAccount(account);
}
};
button.addListener(SWT.Selection, listener);
for (GOIMAccount account : GOIMPlugin
.getPreferenceObject(GOIMAccountList.class)) {
button = new Button(this, SWT.PUSH);
button.setText("Manage Account: " + account.name);
button.setData("account", account);
button.addListener(SWT.Selection, listener);
}
}
public void loadList() {
if (accountList == null)
return;
for (GOIMAccount acc : accountList) {
addAccount(acc);
}
}
public void addAccount(final GOIMAccount account) {
// account.defaultWorkbenchPage =
// PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
final TreeItem accItem = (accountList == null ? null : new TreeItem(contactList, SWT.NULL));
if (accountList != null) {
accItem.setData("account", account);
accItem.setText(account.name);
accItem.setImage(GOIMIcons.getImageForPresence(null, account.xmpp
.getOwnPresence()));
}
SpheneListener<StatusChangedEvent> ownPresenceChangedListener;
account.xmpp.ownPresenceChanged
.addListener(ownPresenceChangedListener = new SpheneListener<StatusChangedEvent>() {
public void handleEvent(final StatusChangedEvent event) {
getDisplay().asyncExec(new Runnable() {
public void run() {
if(event.previousPresence == null) {
Map<String, TreeGroup> groupTreeItems = getGroupTreeItems(accItem);
for(TreeGroup treeGroup : groupTreeItems.values())
if(treeGroup.item != null)
treeGroup.item.dispose();
groupTreeItems.clear();
}
Presence p = account.xmpp.getOwnPresence();
if(accItem != null) {
accItem.setImage(GOIMIcons
.getImageForPresence(null,p));
}
for (TreeItem item : (accItem == null ? contactList.getItems() : accItem.getItems())) {
if (item.getData("entryjid") != null
&& item.getData("entryjid").equals(
account.jid + "/"
+ account.resource)) {
updatePresenceOfItem(item, null, p);
}
}
}
});
}
});
GOIMRosterListener rosterListener = new GOIMRosterListener() {
public void rosterModified() {
getDisplay().asyncExec(new Runnable() {
public void run() {
updateAccountRoster(account);
// System.out.println("RosterModified (asyncExec): "
// + Thread.currentThread().toString());
}
});
}
public void presenceChanged(final String jid) {
getDisplay().asyncExec(new Runnable() {
public void run() {
// updateAccountRoster(account);
// System.out.println("presenceChanged: " + jid);
String id = StringUtils.parseBareAddress(jid);
RosterEntry entry = account.xmpp.getRoster().getEntry(
id);
if (entry == null)
entry = account.xmpp.getRoster().getEntry(jid);
updateRosterEntry(account,
getGroupTreeItems(getAccountTreeItem(account)),
entry);
}
});
}
};
account.xmpp.rosterListener.addListener(rosterListener);
updateAccountRoster(account);
this.addListener(SWT.Dispose, RemoveListener.getRemoveListener(
account.xmpp.ownPresenceChanged, ownPresenceChangedListener));
this.addListener(SWT.Dispose, RemoveListener.getRemoveListener(
account.xmpp.rosterListener, rosterListener));
}
protected TreeItem getAccountTreeItem(GOIMAccount account) {
if (accountList == null)
return null;
for (TreeItem item : contactList.getItems())
if (item.getData("account") == account)
return item;
return null;
}
@SuppressWarnings("unchecked")
protected Map<String, TreeGroup> getGroupTreeItems(TreeItem item) {
Map<String, TreeGroup> groupTreeItems = null;
if (item == null) {
groupTreeItems = (Map<String, TreeGroup>) contactList
.getData("groupTreeItems");
if (groupTreeItems == null)
contactList.setData("groupTreeItems",
groupTreeItems = new HashMap<String, TreeGroup>());
} else {
groupTreeItems = (Map<String, TreeGroup>) item
.getData("groupTreeItems");
if (groupTreeItems == null)
item.setData("groupTreeItems",
groupTreeItems = new HashMap<String, TreeGroup>());
}
return groupTreeItems;
}
protected void updateAccountRoster(final GOIMAccount account) {
Roster roster = account.xmpp.getRoster();
TreeItem item = null;
boolean createOwnPresence = false;
if (managesAllAccounts()) {
item = getAccountTreeItem(account);
// item.removeAll();
createOwnPresence = item.getItemCount() < 1;
} else {
createOwnPresence = contactList.getItemCount() < 1;
// contactList.removeAll();
}
Map<String, TreeGroup> groupTreeItems = getGroupTreeItems(item);
if (createOwnPresence) {
final TreeItem ownPresence = (item == null ? new TreeItem(
contactList, SWT.NULL) : new TreeItem(item, SWT.NULL));
ownPresence.setText(account.getUsername() + " (Self)");
// ownPresence.setImage(GOIMIcons.getImageForPresence(null,account.xmpp.getOwnPresence()));
ownPresence.setData("account",account);
ownPresence.setData("entryjid", account.jid + "/"
+ account.resource);
updatePresenceOfItem(ownPresence, null, account.xmpp
.getOwnPresence());
SpheneListener<SpheneEvent> changeListener;
account.changeListenerList
.addListener(changeListener = new SpheneListener<SpheneEvent>() {
public void handleEvent(SpheneEvent event) {
ownPresence.setText(account.getUsername()
+ " (Self)");
ownPresence.setData("entryjid", account.jid + "/"
+ account.resource);
}
});
ownPresence.addListener(SWT.Dispose, RemoveListener
.getRemoveListener(account.changeListenerList,
changeListener));
}
if (roster == null)
return;
List<String> displayedGroups = new ArrayList<String>(groupTreeItems.keySet());
Iterator groups = roster.getGroups();
while (groups.hasNext()) {
RosterGroup group = (RosterGroup) groups.next();
updateRosterGroup(account, roster, groupTreeItems, item, group, group
.getName());
displayedGroups.remove(group.getName());
}
updateRosterGroup(account, roster, groupTreeItems, item, null, NO_GROUP_NAME);
displayedGroups.remove(NO_GROUP_NAME);
updateRosterGroup(account, roster, groupTreeItems, item, null,
NO_GROUP_COMPONENT);
displayedGroups.remove(NO_GROUP_COMPONENT);
for(String remainingGroup : displayedGroups)
if(groupTreeItems.get(remainingGroup).updateSelf(roster,null))
groupTreeItems.remove(remainingGroup);
// createRosterGroup(account, contactList, item, null, roster
// .getUnfiledEntries());
}
protected void updateRosterGroup(GOIMAccount account, Roster roster,
Map<String, TreeGroup> groupTreeItems, TreeItem parent,
RosterGroup group, String name) {
// String name = (group == null ? NO_GROUP_NAME :group.getName());
TreeGroup treeGroup = groupTreeItems.get(name);
if (treeGroup == null) {
// TreeItem item = (parent == null ? new
// TreeItem(contactList,SWT.NULL) :
// new TreeItem(parent,SWT.NULL));
// item.setText(name);
treeGroup = new TreeGroup(account, parent, group, name);
if(!treeGroup.updateSelf(roster,group))
groupTreeItems.put(name, treeGroup);
} else {
if(treeGroup.updateSelf(roster,group))
groupTreeItems.remove(name);
}
}
protected void updateRosterEntry(GOIMAccount account,
Map<String, TreeGroup> groupTreeItems, RosterEntry entry) {
Iterator i = entry.getGroups();
int count = 0;
while (i.hasNext()) {
RosterGroup group = (RosterGroup) i.next();
insertRosterEntryIntoGroup(account, groupTreeItems, entry, group
.getName());
count++;
}
if (count == 0)
if (entry.getUser().indexOf('@') > -1 && !entry.getUser().equals(GOIMAccount.STATSCONTACTJID))
insertRosterEntryIntoGroup(account, groupTreeItems, entry,
NO_GROUP_NAME);
else
insertRosterEntryIntoGroup(account, groupTreeItems, entry,
NO_GROUP_COMPONENT);
}
protected void insertRosterEntryIntoGroup(GOIMAccount account,
Map<String, TreeGroup> groupTreeItems, RosterEntry entry,
String groupName) {
TreeGroup treeGroup = groupTreeItems.get(groupName);
if(treeGroup == null)
throw new RuntimeException("treeGroup is null ?! " + groupName);
treeGroup.update(new TreeEntry(account, treeGroup, entry));
}
public int getPresenceValue(Presence p) {
if (p == null)
return -1;
if (p.getType() == Presence.Type.UNAVAILABLE)
return -1;
if (p.getType() != Presence.Type.AVAILABLE)
return -2;
if (p.getMode() == Presence.Mode.INVISIBLE)
return 0;
if (p.getMode() == Presence.Mode.AVAILABLE)
return 10;
if (p.getMode() == Presence.Mode.CHAT)
return 9;
if (p.getMode() == Presence.Mode.AWAY)
return 8;
if (p.getMode() == Presence.Mode.EXTENDED_AWAY)
return 7;
if (p.getMode() == Presence.Mode.DO_NOT_DISTURB)
return 6;
return 0;
}
protected String getRosterLabel(RosterEntry entry) {
return entry.getName() == null ? entry.getUser() : entry.getName();
}
public boolean managesAllAccounts() {
return accountList != null;
}
public GOIMAccount getAccount() {
return getActiveAccount();
}
public void closeContactList() {
if (accountList != null)
GOIMPlugin.getDefault().unregisterContactListOfAllAccounts(
container);
else
GOIMPlugin.getDefault().unregisterContactList(account, container);
}
private void updatePresenceOfItem(TreeItem item, RosterEntry entry,
Presence presence) {
item.setImage(GOIMIcons.getImageForPresence(entry, presence));
int extensions = 0;
TreeEditor editor = getEditor(item, false);
if (presence != null) {
Iterator iterator = presence.getExtensions();
if (editor != null)
if (editor.getEditor() == null) {
System.err.println("editor.getEditor() is null !! "
+ this.getClass().toString());
} else {
for (Control control : ((Composite) editor.getEditor())
.getChildren())
control.dispose();
}
while (iterator.hasNext()) {
PacketExtension ex = (PacketExtension) iterator.next();
if (ex instanceof IGameExtension) {
extensions++;
if (editor == null)
editor = getEditor(item, true);
final IGameExtension gameEx = (IGameExtension) ex;
final GOIMGameItem game = gameEx.getGameItem();
final GameExtensionProxy proxy = gameEx.getGameExtension();
// final InetSocketAddress target = gameEx.getDestination();
Label label = new Label((Composite) editor.getEditor(),
SWT.NULL);
// Button label = new
// Button((Composite)editor.getEditor(),SWT.PUSH);
try {
label.setImage(proxy.getIcon().createImage());
} catch(SWTError error) {
error.printStackTrace();
// Since we still want the user to know about the error .. i throw an exception for now ..
throw new RuntimeException("An SWT Error occurred during setting game icon",error);
}
label.setToolTipText(proxy.getTooltipText(game, gameEx));
System.out.println("Addin label with image: " + proxy.icon
+ ": " + label.computeSize(-1, -1));
// label.setEnabled(true);
// label.setText("Muh");
label.setLayoutData(new RowData(16,16));
if (game != null) {
label.addListener(SWT.MouseUp, new Listener() {
public void handleEvent(Event event) {
//System.out.println("mouseup");
proxy.execute(game, gameEx);
}
});
label.setFocus();
} else {
label.setToolTipText("Game not installed: "
+ label.getToolTipText());
}
((Composite) editor.getEditor()).layout(true, true);
((Composite) editor.getEditor()).pack(true);
editor.minimumWidth = editor.getEditor().getSize().x;
editor.layout();
}
}
}
if (extensions < 1 && editor != null) {
editor.getEditor().dispose();
editor.dispose();
item.setData("editor",null);
}
contactList.redraw();
}
public TreeEditor getEditor(TreeItem item, boolean create) {
TreeEditor editor = (TreeEditor) item.getData("editor");
if (create && (editor == null || editor.getEditor() == null)) {
if (item.getParent() == null)
System.err.println("tree is null ?!");
item.setData("editor", editor = new TreeEditor(item.getParent()));
final Composite c = new Composite(contactList, SWT.NULL);
c.setBackground(contactList.getBackground());
RowLayout rowLayout = new RowLayout(SWT.HORIZONTAL);
rowLayout.marginBottom = rowLayout.marginLeft = rowLayout.marginTop = rowLayout.marginRight = 0;
rowLayout.spacing = 2;
rowLayout.wrap = rowLayout.pack = false;
rowLayout.pack = true;
c.setLayout(rowLayout);
editor.setEditor(c, item, 0);
editor.grabHorizontal = false;editor.horizontalAlignment = SWT.RIGHT;
final TreeEditor _editor = editor;
item.addListener(SWT.Dispose, new Listener() {
public void handleEvent(Event event) {
if (!c.isDisposed()) {
c.dispose();
}
if (_editor.getEditor() == null)
System.out.println("TreeEditor already disposed ?!");
else
_editor.dispose();
}
});
}
return editor;
}
@Override
public void setHideOfflineContacts(boolean hideOfflineContacts) {
hideOffline = hideOfflineContacts;//hideOfflineContacts.getSelection();
if(accountList != null)
for(GOIMAccount acc : accountList)
updateAccountRoster(acc);
else
updateAccountRoster(account);
}
@Override
public boolean getHideOfflineContacts() {
return hideOffline;
}
}