package cz.cuni.mff.inetpaint;
import cz.cuni.mff.inetpaint.swing.StatusSelectorMenu;
import cz.cuni.mff.inetpaint.swing.AvatarPanel;
import cz.cuni.mff.inetpaint.dialog.VCardDialog;
import cz.cuni.mff.inetpaint.communications.CommunicationFrame;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.Collection;
import java.util.ResourceBundle;
import javax.imageio.ImageIO;
import javax.swing.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.Presence.Mode;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smackx.packet.*;
/**
* Panel, který se zobrazí po připojení a přihlášení k serveru. Obsahuje seznam kontaktů
* a status panel, který zobrazuje požadavky od ostatních uživatelů (příchozí zprávy,
* požadavky na autorizaci, offline zprávy)
*
* @author Jindřich Helcl
*/
public class RosterPanel extends JPanel implements ConnectionStateListener, RosterListener {
private static final int AVATAR_WIDTH = 50;
private static final int AVATAR_HEIGHT = 50;
private static final int STATUS_BAR_HEIGHT = 22;
private boolean offlineContactsVisible;
private AvatarPanel avatarPanel;
//private JLabel jidLabel;
private JButton statusSelector;
private JTextField statusField;
private JSeparator separator;
private ContactList contactPanel;
private JPopupMenu statusPopupMenu;
private StatusBar statusBar;
@Override
public void entriesAdded(Collection<String> addresses) {
// refreshnout contactList.
setUpContactList();
setOfflineContactsVisible(offlineContactsVisible);
}
@Override
public void entriesDeleted(Collection<String> addresses) {
setUpContactList();
setOfflineContactsVisible(offlineContactsVisible);
}
@Override
public void entriesUpdated(Collection<String> addresses) { }
@Override
public void presenceChanged(Presence presence) { }
@Override
public void connectionStateChanged(int state) {
final ResourceBundle rb = Program.getStringsBundle();
if(state == STATE_CONNECTED) {
statusBar.setListener();
}
if(state == STATE_STARTING) {
setAvatarNicknameAndStatus();
boolean visible = UserPreferences.getShowOfflineUsersEnabled();
setOfflineContactsVisible(visible);
setStatusSelector(ConnectionManager.getInstance().getLastPresence().getMode());
String status = UserPreferences.getLastStatus();
if(status != null && !status.isEmpty()) {
statusField.setForeground(Color.BLACK);
statusField.setText(status);
}
else {
statusField.setText(rb.getString("rosterPanelWriteNote"));
statusField.setForeground(Color.GRAY);
}
}
if(state == STATE_DISCONNECTED || state == STATE_DISCONNECTED_ON_ERROR) {
// bývalá metoda resetPanel();
contactPanel.removeAll();
}
if(state == STATE_SETTING_PRESENCE) {
setUpContactList();
ConnectionManager.getInstance().addRosterListener(this);
}
}
private void setStatusSelector(Presence.Mode mode) {
statusSelector.setIcon(Program.getPresenceIcon(mode));
statusSelector.setText(Program.getPresenceName(mode));
}
private void setUpContactList() {
ContactList cl = new ContactList();
cl.loadRoster();
//setOfflineContactsVisible(offlineContactsVisible);
ConnectionManager.getInstance().addRosterListener(cl);
ConnectionManager.getInstance().removeRosterListener(contactPanel);
GroupLayout layout = (GroupLayout) getLayout();
layout.replace(contactPanel, cl);
setLayout(layout);
invalidate();
contactPanel = cl;
}
private void initComponents() {
final ResourceBundle rb = Program.getStringsBundle();
avatarPanel = new AvatarPanel();
avatarPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
avatarPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
Frame f = Program.getMainFrame();
VCardDialog vc = new VCardDialog(f);
vc.setLocationRelativeTo(f);
vc.setVisible(true);
}
});
avatarPanel.setToolTipText(rb.getString("rosterAvatarTT"));
statusBar = new StatusBar();
contactPanel = new ContactList();
//jidLabel = new JLabel();
separator = new JSeparator(JSeparator.HORIZONTAL);
statusField = new JTextField();
statusField.setBackground(getBackground());
statusField.setFocusable(false);
statusField.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
statusField.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Object[] nullObj = null;
Object strO = JOptionPane.showInputDialog(RosterPanel.this,
rb.getString("rosterPanelNewStatusDialog"),
rb.getString("rosterPanelNewStatusDialogTitle"),
JOptionPane.PLAIN_MESSAGE,
null,
nullObj,
statusField.getText());
if(strO == null)
return;
String str = strO.toString();
if (str.isEmpty()) {
statusField.setText(rb.getString("rosterPanelWriteNote"));
statusField.setForeground(Color.GRAY);
}
else {
statusField.setForeground(Color.BLACK);
statusField.setText(str);
}
ConnectionManager.getInstance().updatePresence(str);
UserPreferences.setLastStatus(str);
}
});
statusField.setToolTipText(rb.getString("rosterStatusTT"));
statusSelector = new JButton();
statusSelector.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
StatusSelectorMenu menu = new StatusSelectorMenu();
menu.addPresenceChangedListener(new StatusSelectorMenu.PresenceChangedListener() {
@Override
public void presenceModeUpdated(Mode mode) {
setStatusSelector(mode);
//udelat status field
String status = (statusField.getForeground() == Color.gray) ? "" : statusField.getText();
ConnectionManager.getInstance().updatePresence(Presence.Type.available, status, 20, mode);
}
});
menu.show(statusSelector, 2, statusSelector.getHeight() + 2);
}
});
statusSelector.setFocusable(false);
statusSelector.setRolloverEnabled(true);
// design
Dimension avatarPanelDim = new Dimension(AVATAR_WIDTH, AVATAR_HEIGHT);
GroupLayout layout = new GroupLayout(this);
setLayout(layout);
layout.setAutoCreateGaps(true);
//layout.setAutoCreateContainerGaps(true);
layout.setHorizontalGroup(layout.createParallelGroup()
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup()
.addGroup(layout.createSequentialGroup()
.addComponent(avatarPanel, avatarPanelDim.width, GroupLayout.DEFAULT_SIZE, avatarPanelDim.width)
.addGroup(layout.createParallelGroup()
//.addComponent(jidLabel)
.addComponent(statusField, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(statusSelector, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
)
.addComponent(separator)
.addComponent(contactPanel)
)
.addContainerGap()
)
.addComponent(statusBar)
);
layout.setVerticalGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup()
.addComponent(avatarPanel, avatarPanelDim.height, GroupLayout.DEFAULT_SIZE, avatarPanelDim.height)
.addGroup(layout.createSequentialGroup()
//.addComponent(jidLabel)
.addComponent(statusSelector)
.addComponent(statusField, 19, 19, 19)))
.addComponent(separator, 1, GroupLayout.DEFAULT_SIZE, 1)
.addComponent(contactPanel)
.addComponent(statusBar, STATUS_BAR_HEIGHT, STATUS_BAR_HEIGHT, STATUS_BAR_HEIGHT)
);
}
/**
* Nastaví viditelnost offline kontaktů
* @param visible Viditelnost ({@literal true} => viditelné, {@literal false} => neviditelné)
*/
public void setOfflineContactsVisible(boolean visible) {
this.offlineContactsVisible = visible;
contactPanel.setOfflineContactsVisible(visible);
}
/**
* Nastaví avatar, přezdívku a status. Volá se po přihlášení k serveru.
*/
public void setAvatarNicknameAndStatus() {
ConnectionManager manager = ConnectionManager.getInstance();
final ResourceBundle rb = Program.getStringsBundle();
try {
VCard vc = manager.getVCard();
byte[] avatarBytes = vc.getAvatar();
if(avatarBytes != null) {
ByteArrayInputStream bais = new ByteArrayInputStream(avatarBytes);
try {
final Image image = ImageIO.read(bais);
avatarPanel.setAvatar(image);
}
catch (IOException e) {
System.err.println("Nelze nacist avatar.");
e.printStackTrace(System.err);
}
} else {
avatarPanel.setNoAvatar();
}
//jidLabel.setText("<html><b>" + manager.getLocalName());
}
catch (XMPPException xmp ) {
System.err.println("Nelze nacist vizitku");
xmp.printStackTrace(System.err);
JOptionPane.showMessageDialog(this, rb.getString("errorVCard"), rb.getString("errorTitle"), JOptionPane.WARNING_MESSAGE);
}
}
/**
* Vytvoří novou instanci panelu. Vytváří se jen jendou, při spuštění programu.
*/
public RosterPanel() {
initComponents();
}
}