package org.chartsy.chatsy.chat.ui;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smackx.packet.VCard;
import org.chartsy.chatsy.chat.ChatsyManager;
import org.chartsy.chatsy.chat.UserManager;
import org.chartsy.chatsy.chat.component.TitlePanel;
import org.chartsy.chatsy.chat.component.borders.ComponentTitledBorder;
import org.chartsy.chatsy.chat.component.renderer.JPanelRenderer;
import org.chartsy.chatsy.chat.util.ModelUtil;
import org.chartsy.chatsy.chat.util.SwingWorker;
import org.chartsy.chatsy.chat.util.log.Log;
import org.chartsy.chatsy.chatimpl.plugin.gateways.Gateway;
import org.chartsy.chatsy.chatimpl.plugin.gateways.transports.Transport;
import org.chartsy.chatsy.chatimpl.plugin.gateways.transports.TransportUtils;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
public class RosterDialog implements PropertyChangeListener, ActionListener {
private JPanel panel;
private JTextField jidField;
private JTextField nicknameField;
//private final Vector<String> groupModel = new Vector<String>();
private final DefaultComboBoxModel groupModel = new DefaultComboBoxModel();
private final JPanel networkPanel = new JPanel(new GridBagLayout());
private JComboBox groupBox;
private JComboBox accounts;
private JOptionPane pane;
private JDialog dialog;
private ContactList contactList;
private JCheckBox publicBox;
public RosterDialog()
{
contactList = ChatsyManager.getWorkspace().getContactList();
panel = new JPanel();
JLabel contactIDLabel = new JLabel("Username");
jidField = new JTextField();
JLabel nicknameLabel = new JLabel("Nickname");
nicknameField = new JTextField();
JLabel groupLabel = new JLabel("Group");
groupBox = new JComboBox(groupModel);
JButton newGroupButton = new JButton("New Group");
JLabel accountsLabel = new JLabel();
accounts = new JComboBox();
publicBox = new JCheckBox("User on public access");
publicBox.setText("local network");
pane = null;
dialog = null;
panel.setLayout(new GridBagLayout());
panel.add(contactIDLabel, new GridBagConstraints(0, 0, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0));
panel.add(jidField, new GridBagConstraints(1, 0, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0));
panel.add(nicknameLabel, new GridBagConstraints(0, 1, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0));
panel.add(nicknameField, new GridBagConstraints(1, 1, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0));
ComponentTitledBorder componentBorder = new ComponentTitledBorder(publicBox, networkPanel, BorderFactory.createEtchedBorder());
networkPanel.add(accountsLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, 17, 2, new Insets(5, 5, 5, 5), 0, 0));
networkPanel.add(accounts, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, 17, 2, new Insets(5, 5, 5, 5), 0, 0));
networkPanel.setBorder(componentBorder);
networkPanel.setVisible(false);
accounts.setEnabled(false);
panel.add(groupLabel, new GridBagConstraints(0, 4, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0));
panel.add(groupBox, new GridBagConstraints(1, 4, 1, 1, 1.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0));
panel.add(newGroupButton, new GridBagConstraints(2, 4, 1, 1, 0.0D, 0.0D, 17, 2, new Insets(5, 5, 5, 5), 0, 0));
newGroupButton.addActionListener(this);
panel.add(networkPanel, new GridBagConstraints(0, 5, 2, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
accounts.setRenderer(new JPanelRenderer());
for (ContactGroup group : contactList.getContactGroups())
groupModel.addElement(group.getGroupName());
groupBox.setEditable(true);
if (groupModel.getSize() == 0)
groupBox.addItem("Friends");
if (groupModel.getSize() > 0)
groupBox.setSelectedIndex(0);
jidField.addFocusListener(new FocusListener()
{
public void focusGained(FocusEvent e)
{
}
public void focusLost(FocusEvent e)
{
String jid = getJID();
String vcardNickname = null;
if (!publicBox.isSelected())
{
String fullJID = getJID();
if (fullJID.indexOf("@") == -1)
fullJID = fullJID + "@" + ChatsyManager.getConnection().getServiceName();
VCard vCard = ChatsyManager.getVCardManager().getVCard(fullJID);
if (vCard != null && vCard.getError() == null)
{
String firstName = vCard.getFirstName();
String lastName = vCard.getLastName();
String nickname = vCard.getNickName();
if (ModelUtil.hasLength(nickname))
vcardNickname = nickname;
else if (ModelUtil.hasLength(firstName) && ModelUtil.hasLength(lastName))
vcardNickname = firstName + " " + lastName;
else if (ModelUtil.hasLength(firstName))
vcardNickname = firstName;
}
}
String nickname = nicknameField.getText();
if (!ModelUtil.hasLength(nickname) && ModelUtil.hasLength(jid))
{
nickname = StringUtils.parseName(jid);
if (!ModelUtil.hasLength(nickname))
nickname = jid;
nicknameField.setText(vcardNickname != null ? vcardNickname : nickname);
}
}
});
final List<AccountItem> accountCol = getAccounts();
for (AccountItem item : accountCol)
accounts.addItem(item);
if (accountCol.size() > 0)
{
accountsLabel.setVisible(true);
accounts.setVisible(true);
publicBox.setVisible(true);
networkPanel.setVisible(true);
}
publicBox.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
accounts.setEnabled(publicBox.isSelected());
}
});
}
public void setDefaultGroup(ContactGroup contactGroup)
{
String groupName = contactGroup.getGroupName();
if (groupModel.getIndexOf(groupName) != -1)
groupBox.setSelectedItem(groupName);
else if (groupModel.getSize() > 0)
{
groupBox.addItem(groupName);
groupBox.setSelectedItem(groupName);
}
}
public void setDefaultJID(String jid)
{
jidField.setText(jid);
}
public void setDefaultNickname(String nickname)
{
nicknameField.setText(nickname);
}
public void actionPerformed(ActionEvent e)
{
String group = JOptionPane.showInputDialog(dialog, "Group:", "New Group", 3);
if (group != null && group.length() > 0 && groupModel.getIndexOf(group) == -1)
{
ChatsyManager.getConnection().getRoster().createGroup(group);
groupModel.addElement(group);
int size = groupModel.getSize();
groupBox.setSelectedIndex(size - 1);
}
}
public void showRosterDialog(JFrame parent)
{
TitlePanel titlePanel = new TitlePanel("Add Contact", "Add a new contact to list", null, true);
JPanel mainPanel = new JPanel()
{
public Dimension getPreferredSize()
{
final Dimension size = super.getPreferredSize();
size.width = 350;
return size;
}
};
mainPanel.setLayout(new BorderLayout());
mainPanel.add(titlePanel, BorderLayout.NORTH);
Object[] options = {"Add", "Cancel"};
pane = new JOptionPane(panel, -1, 2, null, options, options[0]);
mainPanel.add(pane, BorderLayout.CENTER);
dialog = new JDialog(parent, "Add contact", false);
dialog.setContentPane(mainPanel);
dialog.pack();
dialog.setLocationRelativeTo(parent);
pane.addPropertyChangeListener(this);
dialog.setVisible(true);
dialog.toFront();
dialog.requestFocus();
jidField.requestFocus();
}
public void showRosterDialog()
{
showRosterDialog(new JFrame());
}
public void propertyChange(PropertyChangeEvent e)
{
if (pane != null && pane.getValue() instanceof Integer)
{
pane.removePropertyChangeListener(this);
dialog.dispose();
return;
}
try
{
String value = (String)pane.getValue();
String errorMessage = "Error";
if ("Cancel".equals(value))
{
dialog.setVisible(false);
}
else if ("Add".equals(value))
{
String jid = getJID();
String contact = UserManager.escapeJID(jid);
String nickname = nicknameField.getText();
String group = (String)groupBox.getSelectedItem();
Transport transport = null;
if (publicBox.isSelected())
{
AccountItem item = (AccountItem)accounts.getSelectedItem();
transport = item.getTransport();
}
if (transport == null)
if (contact.indexOf("@") == -1)
contact = contact + "@" + ChatsyManager.getConnection().getServiceName();
else
if (contact.indexOf("@") == -1)
contact = contact + "@" + transport.getServiceName();
if (!ModelUtil.hasLength(nickname) && ModelUtil.hasLength(contact))
{
VCard vcard = new VCard();
try
{
vcard.load(ChatsyManager.getConnection(), contact);
nickname = vcard.getNickName();
}
catch (XMPPException ex)
{
Log.error(ex);
}
if (!ModelUtil.hasLength(nickname))
nickname = StringUtils.parseName(contact);
nicknameField.setText(nickname);
}
if (!ModelUtil.hasLength(contact))
errorMessage = "Please specify the contact JID";
else if (StringUtils.parseBareAddress(contact).indexOf("@") == -1)
errorMessage = "The JID specified is invalid";
else if (!ModelUtil.hasLength(group))
errorMessage = "Specify contact group to add the new user to";
else if (ModelUtil.hasLength(contact) && ModelUtil.hasLength(group))
{
addEntry();
dialog.setVisible(false);
return;
}
JOptionPane.showMessageDialog(dialog, errorMessage, "Error", JOptionPane.ERROR_MESSAGE);
pane.setValue(JOptionPane.UNINITIALIZED_VALUE);
}
}
catch (NullPointerException ee)
{
Log.error(ee);
}
}
private void addEntry()
{
Transport transport = null;
AccountItem item;
if (publicBox.isSelected())
{
item = (AccountItem)accounts.getSelectedItem();
transport = item.getTransport();
}
if (transport == null)
{
String jid = getJID();
if (jid.indexOf("@") == -1)
jid = jid + "@" + ChatsyManager.getConnection().getServiceName();
String nickname = nicknameField.getText();
String group = (String)groupBox.getSelectedItem();
jid = UserManager.escapeJID(jid);
addRosterEntry(jid, nickname, group);
}
else
{
String jid = getJID();
try
{
jid = Gateway.getJID(transport.getServiceName(), jid);
}
catch (XMPPException e)
{
Log.error(e);
}
String nickname = nicknameField.getText();
String group = (String)groupBox.getSelectedItem();
addRosterEntry(jid, nickname, group);
}
}
private String getJID()
{
return jidField.getText().trim();
}
private void addRosterEntry(final String jid, final String nickname, final String group)
{
final SwingWorker rosterEntryThread = new SwingWorker()
{
public Object construct()
{
return addEntry(jid, nickname, group);
}
public void finished()
{
if (get() == null)
JOptionPane.showMessageDialog(dialog, "Unable to add contact", "Error", JOptionPane.ERROR_MESSAGE);
}
};
rosterEntryThread.start();
}
public RosterEntry addEntry(String jid, String nickname, String group)
{
String[] groups = {group};
Roster roster = ChatsyManager.getConnection().getRoster();
RosterEntry userEntry = roster.getEntry(jid);
boolean isSubscribed = true;
if (userEntry != null)
isSubscribed = userEntry.getGroups().isEmpty();
if (isSubscribed)
{
try
{
roster.createEntry(jid, nickname, new String[]{group});
}
catch (XMPPException e)
{
Log.error("Unable to add new entry " + jid, e);
}
return roster.getEntry(jid);
}
try
{
RosterGroup rosterGroup = roster.getGroup(group);
if (rosterGroup == null)
rosterGroup = roster.createGroup(group);
if (userEntry == null)
{
roster.createEntry(jid, nickname, groups);
userEntry = roster.getEntry(jid);
}
else
{
userEntry.setName(nickname);
rosterGroup.addEntry(userEntry);
}
userEntry = roster.getEntry(jid);
}
catch (XMPPException ex)
{
Log.error(ex);
}
return userEntry;
}
public List<AccountItem> getAccounts()
{
List<AccountItem> list = new ArrayList<AccountItem>();
for (Transport transport : TransportUtils.getTransports())
{
if (TransportUtils.isRegistered(ChatsyManager.getConnection(), transport))
{
AccountItem item = new AccountItem(transport.getIcon(), transport.getName(), transport);
list.add(item);
}
}
return list;
}
class AccountItem extends JPanel
{
private Transport transport;
public AccountItem(Icon icon, String name, Transport transport)
{
setLayout(new GridBagLayout());
this.transport = transport;
JLabel iconLabel = new JLabel();
iconLabel.setIcon(icon);
JLabel label = new JLabel();
label.setText(name);
label.setFont(new Font("Dialog", Font.PLAIN, 11));
label.setHorizontalTextPosition(JLabel.CENTER);
add(iconLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
GridBagConstraints.WEST, GridBagConstraints.NONE,
new Insets(0, 0, 0, 0), 0, 0));
add(label, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0,
GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
new Insets(0, 10, 0, 0), 0, 0));
setBackground(Color.white);
}
public Transport getTransport()
{
return transport;
}
}
}