/**
* $RCSfile: ,v $
* $Revision: $
* $Date: $
*
* Copyright (C) 2004-2011 Jive Software. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.sparkimpl.plugin.chat;
import org.jivesoftware.resource.Res;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.spark.PresenceManager;
import org.jivesoftware.spark.SparkManager;
import org.jivesoftware.spark.plugin.ContextMenuListener;
import org.jivesoftware.spark.plugin.Plugin;
import org.jivesoftware.spark.ui.ContactGroup;
import org.jivesoftware.spark.ui.ContactItem;
import org.jivesoftware.spark.ui.ContactList;
import org.jivesoftware.spark.util.SwingWorker;
import org.jivesoftware.spark.util.UIComponentRegistry;
import org.jivesoftware.spark.util.log.Log;
import org.jivesoftware.sparkimpl.settings.local.LocalPreferences;
import org.jivesoftware.sparkimpl.settings.local.PreferenceListener;
import org.jivesoftware.sparkimpl.settings.local.SettingsManager;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Adds extra functionallity to the <code>ContactList</code>. This includes copying and moving of <code>ContactItem</code>.
*/
public class ContactListAssistantPlugin implements Plugin {
private JMenu moveToMenu;
private JMenu copyToMenu;
private LocalPreferences localPreferences;
@Override
public void initialize() {
moveToMenu = new JMenu(Res.getString("menuitem.move.to"));
copyToMenu = new JMenu(Res.getString("menuitem.copy.to"));
localPreferences = new LocalPreferences();
final ContactList contactList = SparkManager.getContactList();
contactList.addContextMenuListener(new ContextMenuListener() {
@Override
public void poppingUp(Object object, final JPopupMenu popup) {
final Collection<ContactItem> contactItems = Collections.unmodifiableCollection(contactList.getSelectedUsers());
if (!contactItems.isEmpty()) {
final List<ContactGroup> contactGroups = contactList.getContactGroups();
Collections.sort(contactGroups, ContactList.GROUP_COMPARATOR);
for (final ContactGroup group : contactGroups) {
if (group.isUnfiledGroup() || group.isOfflineGroup()) {
continue;
}
if (isContactItemInGroup(contactItems, group)) {
continue;
}
final Action moveAction = new AbstractAction() {
private static final long serialVersionUID = 6542011870221162331L;
@Override
public void actionPerformed(ActionEvent actionEvent) {
moveItems(contactItems, group.getGroupName());
}
};
final Action copyAction = new AbstractAction() {
private static final long serialVersionUID = 2232885525630977329L;
@Override
public void actionPerformed(ActionEvent actionEvent) {
copyItems(contactItems, group.getGroupName());
}
};
moveAction.putValue(Action.NAME, group.getGroupName());
moveToMenu.add(moveAction);
copyAction.putValue(Action.NAME, group.getGroupName());
copyToMenu.add(copyAction);
}
popup.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent popupMenuEvent) {
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent popupMenuEvent) {
moveToMenu.removeAll();
copyToMenu.removeAll();
popup.removePopupMenuListener(this);
}
@Override
public void popupMenuCanceled(PopupMenuEvent popupMenuEvent) {
moveToMenu.removeAll();
copyToMenu.removeAll();
popup.removePopupMenuListener(this);
}
});
int index = -1;
for (int i = 0; i < popup.getComponentCount(); i++) {
Object o = popup.getComponent(i);
if (o instanceof JMenuItem && ((JMenuItem)o).getText().equals(Res.getString("menuitem.rename"))) {
index = i;
break;
}
}
if (contactItems.size() == 1) {
// Add right after the rename item.
if (index != -1) {
popup.add(moveToMenu, index + 1);
popup.add(copyToMenu, index + 2);
}
}
else if (contactItems.size() > 1) {
popup.addSeparator();
popup.add(moveToMenu);
popup.add(copyToMenu);
popup.addSeparator();
}
}
}
@Override
public void poppingDown(JPopupMenu popup) {
}
@Override
public boolean handleDefaultAction(MouseEvent e) {
return false;
}
});
updateAvatarsInContactList();
SettingsManager.addPreferenceListener(new PreferenceListener() {
@Override
public void preferencesChanged(LocalPreferences preference) {
updateAvatarsInContactList();
}
});
}
private boolean isContactItemInGroup(Collection<ContactItem> contactItems, ContactGroup group) {
boolean contactInGroup = false;
for (ContactItem ci : contactItems) {
if (group.getContactItemByJID(ci.getJID(), true) != null) {
contactInGroup = true;
break;
}
}
return contactInGroup;
}
/**
* Moves a collection of <code>ContactItem</code>s to the specified group.
*
* @param contactItems the contact items to move.
* @param groupName the name of the group to move to.
*/
private void moveItems(Collection<ContactItem> contactItems, String groupName) {
final ContactGroup contactGroup = getContactGroup(groupName);
ContactGroup oldGroup = null;
for (ContactItem contactItem : contactItems) {
oldGroup = getContactGroup(contactItem.getGroupName());
if (oldGroup.isSharedGroup()) {
continue;
}
addContactItem(contactGroup, contactItem, true);
}
}
/**
* Copies a collection of <code>ContactItem</code>s to a specified group.
*
* @param contactItems the collection of contact items.
* @param groupName the name of the group to move to.
*/
private void copyItems(Collection<ContactItem> contactItems, String groupName) {
final ContactGroup contactGroup = getContactGroup(groupName);
for (ContactItem contactItem : contactItems) {
addContactItem(contactGroup, contactItem, false);
}
}
@Override
public void shutdown() {
}
@Override
public boolean canShutDown() {
return false;
}
@Override
public void uninstall() {
}
private void updateContactItem(ContactItem contactItem) {
contactItem.updateAvatarInSideIcon();
}
private void updateAvatarsInContactList() {
final ContactList contactList = SparkManager.getContactList();
for (ContactGroup contactGroup : contactList.getContactGroups()) {
if (contactGroup.isOfflineGroup()) {
continue;
}
for (ContactItem contactItem : contactGroup.getContactItems()) {
updateContactItem(contactItem);
}
}
}
/**
* Copies or moves a new <code>ContactItem</code> into the <code>ContactGroup</code>.
*
* @param contactGroup the ContactGroup.
* @param item the ContactItem to move.
* @param move true if the ContactItem should be moved, otherwise false.
*/
private void addContactItem(final ContactGroup contactGroup, final ContactItem item, final boolean move) {
ContactItem newContact = UIComponentRegistry.createContactItem(item.getAlias(), item.getNickname(), item.getJID());
newContact.setPresence(item.getPresence());
newContact.setIcon(item.getIcon());
newContact.getNicknameLabel().setFont(item.getNicknameLabel().getFont());
boolean groupHadAvailableContacts = false;
// Do not copy/move a contact item only if it is not already in the Group.
if (contactGroup.getContactItemByJID(item.getJID(), true) != null) {
return;
}
if (!PresenceManager.isOnline(item.getJID())) {
contactGroup.addOfflineContactItem(item.getAlias(), item.getNickname(), item.getJID(), null);
}
else {
groupHadAvailableContacts = contactGroup.hasAvailableContacts();
contactGroup.addContactItem(newContact);
}
contactGroup.clearSelection();
contactGroup.fireContactGroupUpdated(); //Updating group title
final ContactGroup oldGroup = getContactGroup(item.getGroupName());
final boolean groupAvailableContacts = groupHadAvailableContacts;
SwingWorker worker = new SwingWorker() {
@Override
public Object construct() {
Roster roster = SparkManager.getConnection().getRoster();
RosterEntry entry = roster.getEntry(item.getJID());
RosterGroup groupFound = null;
for (RosterGroup group : roster.getGroups()) {
if (group.getName().equals(contactGroup.getGroupName())) {
try {
groupFound = group;
if (!groupAvailableContacts)
{
SparkManager.getContactList().toggleGroupVisibility(groupFound.getName(), true);
}
group.addEntry(entry);
}
catch (XMPPException e1) {
Log.error(e1);
return false;
}
}
}
// This is a new group
if (groupFound == null) {
groupFound = roster.createGroup(contactGroup.getGroupName());
try {
groupFound.addEntry(entry);
if (!groupAvailableContacts)
{
SparkManager.getContactList().toggleGroupVisibility(groupFound.getName(), true);
}
}
catch (XMPPException e) {
Log.error(e);
}
}
return true;
}
@Override
public void finished() {
if ((Boolean)get()) {
// Now try and remove the group from the old one.
if (move) {
removeContactItem(oldGroup, item);
if (!localPreferences.isEmptyGroupsShown() && !oldGroup.hasAvailableContacts())
{
SparkManager.getContactList().toggleGroupVisibility(oldGroup.getGroupName(),false);
}
}
}
}
};
worker.start();
}
public boolean removeContactItem(ContactGroup contactGroup, ContactItem item) {
if (contactGroup.isSharedGroup()) {
return false;
}
if (contactGroup.isUnfiledGroup()) {
contactGroup.removeContactItem(item);
contactGroup.fireContactGroupUpdated();
return true;
}
// Remove entry from Roster Group
Roster roster = SparkManager.getConnection().getRoster();
RosterEntry entry = roster.getEntry(item.getJID());
RosterGroup rosterGroup = null;
for (RosterGroup group : roster.getGroups()) {
if (group.getName().equals(contactGroup.getGroupName())) {
try {
rosterGroup = group;
group.removeEntry(entry);
}
catch (XMPPException e1) {
return false;
}
}
}
if (rosterGroup == null) {
return false;
}
if (!rosterGroup.contains(entry)) {
contactGroup.removeContactItem(item);
contactGroup.fireContactGroupUpdated(); //Updating group title
return true;
}
return false;
}
private ContactGroup getContactGroup(String groupName) {
ContactList contactList = SparkManager.getWorkspace().getContactList();
return contactList.getContactGroup(groupName);
}
}