aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/net/java/sip/communicator/impl/gui/main/contactlist/ContactRightButtonMenu.java50
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/ContactInfoActivator.java71
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/ContactInfoContactPanel.java185
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDetailsPanel.java490
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDialog.java83
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/ContactInfoMenuItem.java67
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/Resources.java87
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/contactinfo.manifest.mf27
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/resources.properties22
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/resources/personPhoto.pngbin0 -> 4045 bytes
-rw-r--r--src/net/java/sip/communicator/plugin/contactinfo/resources/userInfo16x16.pngbin0 -> 465 bytes
11 files changed, 1036 insertions, 46 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactRightButtonMenu.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactRightButtonMenu.java
index adfd2e5..796b840 100644
--- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactRightButtonMenu.java
+++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactRightButtonMenu.java
@@ -49,9 +49,6 @@ public class ContactRightButtonMenu
private I18NString moveSubcontactString
= Messages.getI18NString("moveSubcontact");
- private I18NString userInfoString
- = Messages.getI18NString("userInfo");
-
private I18NString addSubcontactString
= Messages.getI18NString("addSubcontact");
@@ -79,9 +76,6 @@ public class ContactRightButtonMenu
private SIPCommMenu moveSubcontactMenu
= new SIPCommMenu(moveSubcontactString.getText());
- private SIPCommMenu userInfoMenu
- = new SIPCommMenu(userInfoString.getText());
-
private SIPCommMenu addSubcontactMenu
= new SIPCommMenu(addSubcontactString.getText());
@@ -120,8 +114,6 @@ public class ContactRightButtonMenu
private String moveSubcontactPrefix = "moveSubcontact:";
- private String infoSubcontactPrefix = "infoSubcontact:";
-
private Contact contactToMove;
private boolean moveAllContacts = false;
@@ -166,9 +158,6 @@ public class ContactRightButtonMenu
this.moveSubcontactMenu.setIcon(new ImageIcon(ImageLoader
.getImage(ImageLoader.MOVE_CONTACT_ICON)));
-
- this.userInfoMenu.setIcon(new ImageIcon(ImageLoader
- .getImage(ImageLoader.INFO_16x16_ICON)));
//Initialize the addSubcontact menu.
Iterator providers = this.mainFrame.getProtocolProviders();
@@ -255,7 +244,6 @@ public class ContactRightButtonMenu
JMenuItem contactItem = new JMenuItem(contactDisplayName);
JMenuItem contactItem1 = new JMenuItem(contactDisplayName);
- JMenuItem contactItem2 = new JMenuItem(contactDisplayName);
Icon protocolIcon = new ImageIcon(
createContactStatusImage(contact));
@@ -269,25 +257,14 @@ public class ContactRightButtonMenu
contactItem1.setName(moveSubcontactPrefix + contact.getAddress()
+ protocolProvider.getProtocolName());
- contactItem2.setName(infoSubcontactPrefix + contact.getAddress()
- + protocolProvider.getProtocolName());
-
contactItem.addActionListener(this);
contactItem1.addActionListener(this);
- contactItem2.addActionListener(this);
-
+
this.removeContactMenu.add(contactItem);
this.moveSubcontactMenu.add(contactItem1);
OperationSetWebContactInfo wContactInfo
= mainFrame.getWebContactInfoOpSet(protocolProvider);
-
- if(wContactInfo == null) {
- contactItem2.setEnabled(false);
- contactItem2.setToolTipText(
- Messages.getI18NString("dontSupportWebInfo").getText());
- }
- this.userInfoMenu.add(contactItem2);
}
this.add(sendMessageItem);
@@ -311,7 +288,6 @@ public class ContactRightButtonMenu
this.addSeparator();
this.add(viewHistoryItem);
- this.add(userInfoMenu);
this.initPluginComponents();
@@ -322,14 +298,12 @@ public class ContactRightButtonMenu
this.addSubcontactMenu.setName("addSubcontact");
this.renameContactItem.setName("renameContact");
this.viewHistoryItem.setName("viewHistory");
- this.userInfoMenu.setName("userInfo");
this.sendMessageItem.addActionListener(this);
this.callItem.addActionListener(this);
this.sendFileItem.addActionListener(this);
this.renameContactItem.addActionListener(this);
this.viewHistoryItem.addActionListener(this);
- this.userInfoMenu.addActionListener(this);
// Disable all menu items that do nothing.
if (contactItem.getDefaultContact(OperationSetFileTransfer.class)
@@ -340,7 +314,7 @@ public class ContactRightButtonMenu
this.callItem.setEnabled(false);
if (contactItem.getDefaultContact(OperationSetBasicInstantMessaging.class)
== null)
- this.sendMessageItem.setEnabled(false);
+ this.sendMessageItem.setEnabled(false);
}
private void initPluginComponents()
@@ -375,7 +349,6 @@ public class ContactRightButtonMenu
this.removeContactMenu.setMnemonic(removeContactString.getMnemonic());
this.renameContactItem.setMnemonic(renameContactString.getMnemonic());
this.viewHistoryItem.setMnemonic(viewHistoryString.getMnemonic());
- this.userInfoMenu.setMnemonic(userInfoString.getMnemonic());
this.moveSubcontactMenu.setMnemonic(moveSubcontactString.getMnemonic());
}
@@ -477,23 +450,8 @@ public class ContactRightButtonMenu
history.setVisible(true);
}
}
- else if (itemName.startsWith(infoSubcontactPrefix)) {
-
- Contact contact = getContactFromMetaContact(
- itemName.substring(infoSubcontactPrefix.length()));
-
- ProtocolProviderService contactProvider
- = contact.getProtocolProvider();
-
- OperationSetWebContactInfo wContactInfo
- = mainFrame.getWebContactInfoOpSet(contactProvider);
-
- GuiActivator.getBrowserLauncher().openURL(
- wContactInfo.getWebContactInfo(contact)
- .toString());
- }
- else if (itemName.startsWith(moveToPrefix)) {
-
+ else if (itemName.startsWith(moveToPrefix))
+ {
MetaContactGroup group
= mainFrame.getGroupByID(
itemName.substring(moveToPrefix.length()));
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoActivator.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoActivator.java
new file mode 100644
index 0000000..0b1c88d
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoActivator.java
@@ -0,0 +1,71 @@
+package net.java.sip.communicator.plugin.contactinfo;
+
+import net.java.sip.communicator.service.browserlauncher.*;
+import net.java.sip.communicator.service.gui.*;
+
+import org.osgi.framework.*;
+
+/**
+ * The Activator of the Contact Info bundle.
+ *
+ * @author Adam Goldstein
+ * @author Yana Stamcheva
+ */
+public class ContactInfoActivator implements BundleActivator
+{
+ private static BrowserLauncherService browserLauncherService;
+
+ private static BundleContext bundleContext;
+
+ /**
+ * Starts this bundle.
+ */
+ public void start(BundleContext bc) throws Exception
+ {
+ bundleContext = bc;
+
+ ServiceReference uiServiceRef
+ = bc.getServiceReference(UIService.class.getName());
+
+ UIService uiService
+ = (UIService) bc.getService(uiServiceRef);
+
+ // Check if the desired place, where we would like to add
+ // our menu item is supported from the current UIService implementation.
+ if (uiService.isContainerSupported(
+ UIService.CONTAINER_CONTACT_RIGHT_BUTTON_MENU))
+ {
+ ContactInfoMenuItem cinfoMenuItem = new ContactInfoMenuItem();
+
+ // We add the example plugin menu item in the right button menu
+ // for a contact.
+ uiService.addComponent(
+ UIService.CONTAINER_CONTACT_RIGHT_BUTTON_MENU,
+ cinfoMenuItem);
+ }
+ }
+
+ public void stop(BundleContext bc) throws Exception
+ {
+ }
+
+ /**
+ * Returns the <tt>BrowserLauncherService</tt> obtained from the bundle
+ * context.
+ * @return the <tt>BrowserLauncherService</tt> obtained from the bundle
+ * context
+ */
+ public static BrowserLauncherService getBrowserLauncher()
+ {
+ if (browserLauncherService == null)
+ {
+ ServiceReference serviceReference = bundleContext
+ .getServiceReference(BrowserLauncherService.class.getName());
+
+ browserLauncherService = (BrowserLauncherService) bundleContext
+ .getService(serviceReference);
+ }
+
+ return browserLauncherService;
+ }
+} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoContactPanel.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoContactPanel.java
new file mode 100644
index 0000000..3e709c4
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoContactPanel.java
@@ -0,0 +1,185 @@
+package net.java.sip.communicator.plugin.contactinfo;
+
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license. See terms of license at gnu.org.
+ */
+
+import java.awt.*;
+import java.util.*;
+
+import javax.swing.*;
+import javax.swing.event.*;
+
+import net.java.sip.communicator.service.protocol.*;
+
+/**
+ * The left side panel of ContactInfoDialog. Display all associated subcontacts
+ * and their respective protocols in a JList. If a user is selected, the
+ * ContactInfoDetailsPanel will be updated to the current contact.
+ *
+ * @author Adam Goldstein
+ * @author Yana Stamcheva
+ */
+public class ContactInfoContactPanel
+ extends JPanel
+{
+ /**
+ * The list of all subcontacts related to the selected contact.
+ */
+ private JList contactList = new JList();
+
+ /**
+ * The scroll pane containing the list of all sub contacts of a selected
+ * contact.
+ */
+ private JScrollPane contactScrollPane = new JScrollPane();
+
+ private DefaultListModel contactListModel = new DefaultListModel();
+
+ /**
+ * The associated ProtocolPanel on our parent ContactInfoDialog.
+ */
+ private ContactInfoDetailsPanel protocolPanel;
+
+ /**
+ * The parent dialog that makes the connection between the contacts and
+ * the details panel.
+ */
+ private ContactInfoDialog contactInfoDialog;
+
+ /**
+ * Create a panel with a list of all sub-contacts associated with the
+ * contact that was originally selected. Whenever a sub-contact is picked,
+ * notifies the protocolPanel of the change and it will update the displayed
+ * details.
+ *
+ * @param contacts the list of contacts
+ * @param dialog the contact info dialog
+ */
+ public ContactInfoContactPanel( Iterator<Contact> contacts,
+ ContactInfoDialog dialog)
+ {
+ super(new BorderLayout());
+
+ this.contactInfoDialog = dialog;
+
+ this.setBorder(BorderFactory.createCompoundBorder(BorderFactory
+ .createTitledBorder(Resources.getString("contacts")),
+ BorderFactory.createEmptyBorder(5, 5, 5, 5)));
+
+ this.contactList.setOpaque(false);
+ this.contactList.setModel(contactListModel);
+ this.contactList.setCellRenderer(new ContactPanelCellRenderer());
+ this.contactList.addListSelectionListener(new ListSelectionListener()
+ {
+ public void valueChanged(ListSelectionEvent e)
+ {
+ // When the user release the mouse button and completes the
+ // selection, getValueIsAdjusting() becomes false
+ if (!e.getValueIsAdjusting())
+ {
+ JList list = (JList) e.getSource();
+
+ Contact selectedContact
+ = (Contact) list.getSelectedValue();
+
+ contactInfoDialog.loadContactDetails(selectedContact);
+ }
+ }
+ });
+
+ boolean isFirstIter = true;
+ while (contacts.hasNext())
+ {
+ Contact contact = contacts.next();
+
+ this.contactListModel.addElement(contact);
+
+ if (isFirstIter)
+ {
+ isFirstIter = false;
+ contactInfoDialog.loadContactDetails(contact);
+ contactList.setSelectedIndex(0);
+ }
+ }
+
+ this.contactScrollPane.setPreferredSize(new Dimension(100, 200));
+ this.contactScrollPane.getViewport().add(contactList);
+ this.add(contactScrollPane);
+ }
+
+ /**
+ * A cell renderer that allows both text and icons in our contactList.
+ */
+ private class ContactPanelCellRenderer
+ extends DefaultListCellRenderer
+ {
+ private boolean isSelected;
+
+ private Color blueGreyBorderColor = new Color(131, 149, 178);
+
+ private Color selectedColor = new Color(209, 212, 225);
+
+ public ContactPanelCellRenderer()
+ {
+ this.setOpaque(false);
+ }
+
+ /**
+ * Renders a <tt>Contact</tt> object in a JList, by visualizing
+ * the contact name and the protocol icon.
+ *
+ * @param list the rendered JList
+ * @param value the object to be rendered
+ * @param index the index of the object in the list
+ * @param isSelected indicates if the rendered object is selected
+ * @param cellHasFocus indicates if the rendered object is in a focused
+ * cell
+ */
+ public Component getListCellRendererComponent( JList list,
+ Object value,
+ int index,
+ boolean isSelected,
+ boolean cellHasFocus)
+ {
+ super.getListCellRendererComponent(list, value, index, isSelected,
+ cellHasFocus);
+
+ this.isSelected = isSelected;
+
+ Contact contact = (Contact) value;
+
+ this.setIcon(new ImageIcon(contact.getProtocolProvider()
+ .getProtocolIcon().getIcon(ProtocolIcon.ICON_SIZE_16x16)));
+ this.setText(((Contact) value).getDisplayName());
+
+ return this;
+ }
+
+ /**
+ * Paint a round blue border and background when a cell is selected.
+ */
+ public void paintComponent(Graphics g)
+ {
+ Graphics2D g2 = (Graphics2D) g;
+
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ if (this.isSelected)
+ {
+ g2.setColor(selectedColor);
+ g2.fillRoundRect(1, 0, this.getWidth(), this.getHeight(), 7, 7);
+
+ g2.setColor(blueGreyBorderColor);
+ g2.setStroke(new BasicStroke(1.5f));
+ g2.drawRoundRect(1, 0, this.getWidth() - 2, this.getHeight() - 1,
+ 7, 7);
+ }
+
+ super.paintComponent(g);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDetailsPanel.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDetailsPanel.java
new file mode 100644
index 0000000..d3a9be0
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDetailsPanel.java
@@ -0,0 +1,490 @@
+package net.java.sip.communicator.plugin.contactinfo;
+
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license. See terms of license at gnu.org.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+
+import java.util.*;
+import java.text.DateFormat;
+
+import javax.swing.*;
+import javax.swing.event.*;
+
+import net.java.sip.communicator.service.protocol.*;
+import net.java.sip.communicator.service.protocol.ServerStoredDetails.*;
+
+/**
+ * The right side panel of ContactInfoDialog. Shows one tab of a summary of
+ * contact information for the selected subcontact, and has an extended tab
+ * listing all of the details.
+ *
+ * @author Adam Goldstein
+ * @author Yana Stamcheva
+ */
+public class ContactInfoDetailsPanel
+ extends JPanel
+{
+ /**
+ * The tabbed pane containing the two different tabs for details.
+ */
+ private JTabbedPane tabbedPane = new JTabbedPane();
+
+ /**
+ * The operation set giving access to the server stored contact details.
+ */
+ private OperationSetServerStoredContactInfo contactInfoOpSet;
+
+ /**
+ * The currently selected sub-contact we are displaying information about.
+ */
+ private Contact contact;
+
+ /**
+ * Construct a tabbed pane that will have one tab with a summary of info for
+ * the selected subcontact and one tab for all of the extended details.
+ */
+ public ContactInfoDetailsPanel()
+ {
+ this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
+ this.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+ this.setPreferredSize(new Dimension(400, 300));
+
+ this.tabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
+ }
+
+ /**
+ * Retrieve and display the information for the newly selected contact, c.
+ *
+ * @param c the sub-contact we are now focusing on.
+ */
+ public void loadContactDetails(Contact c)
+ {
+ this.contact = c;
+
+ ProtocolProviderService pps = contact.getProtocolProvider();
+ contactInfoOpSet =
+ (OperationSetServerStoredContactInfo) pps
+ .getOperationSet(OperationSetServerStoredContactInfo.class);
+
+ this.removeAll();
+
+ if (contactInfoOpSet == null || !pps.isRegistered())
+ {
+ JPanel unsupportedPanel = createUnsupportedPanel();
+
+ this.add(unsupportedPanel);
+
+ this.revalidate();
+ this.repaint();
+
+ return;
+ }
+
+ this.tabbedPane.removeAll();
+
+ ImageIcon icon =
+ new ImageIcon(contact.getProtocolProvider().getProtocolIcon()
+ .getIcon(ProtocolIcon.ICON_SIZE_16x16));
+
+ JPanel summaryPanel = createSummaryInfoPanel();
+
+ JPanel extendedPanel = createExtendedInfoPanel();
+
+ JScrollPane extendedScrollPane = new JScrollPane(extendedPanel);
+
+ this.tabbedPane.addTab(Resources.getString("summary"), icon,
+ summaryPanel, Resources.getString("summaryDesc")
+ + contact.getDisplayName());
+
+ this.tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);
+
+ this.tabbedPane.addTab(Resources.getString("extended"), icon,
+ extendedScrollPane, Resources.getString("extendedDesc")
+ + contact.getDisplayName());
+
+ this.tabbedPane.setMnemonicAt(1, KeyEvent.VK_2);
+
+ this.add(tabbedPane);
+
+ this.revalidate();
+ this.repaint();
+ }
+
+ /**
+ * Creates the panel that indicates to the user that the currently selected
+ * contact does not support server stored contact info.
+ *
+ * @return the panel that is added and shows a message that the selected
+ * sub-contact does not have the operation set for server stored
+ * contact info supported.
+ */
+ private JPanel createUnsupportedPanel()
+ {
+ JTextArea unsupportedTextArea =
+ new JTextArea(Resources.getString("notSupported"));
+
+ unsupportedTextArea.setEditable(false);
+ unsupportedTextArea.setLineWrap(true);
+
+ JPanel unsupportedPanel = new JPanel(new BorderLayout());
+
+ unsupportedPanel.add(unsupportedTextArea);
+
+ return unsupportedPanel;
+ }
+
+ /**
+ * Creates a panel that can be added as the summary tab that displays the
+ * following details: -
+ * <p>
+ * Avatar(Contact image) - FirstNameDetail - MiddleNameDetail -
+ * LastNameDetail - BirthdateDetail (and calculate age) - GenderDetail -
+ * EmailAddressDetail - PhoneNumberDetail. All other details will be* added
+ * to our list of extended details.
+ *
+ * @return the panel that will be added as the summary tab.
+ */
+ private JPanel createSummaryInfoPanel()
+ {
+ JPanel summaryPanel = new JPanel();
+
+ summaryPanel.setLayout(new BorderLayout(10, 5));
+ summaryPanel.setSize(this.getWidth(), this.getHeight());
+
+ // Create the avatar panel.
+ JPanel avatarPanel = new JPanel();
+
+ avatarPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+ byte[] bytes = this.contact.getImage();
+
+ ImageIcon avatarImage = null;
+ // If the user has a contact image, let's use it. If not, add the
+ // default
+ if (bytes != null)
+ avatarImage = new ImageIcon(bytes);
+ else
+ avatarImage = Resources.getImage("defaultPersonIcon");
+
+ ImageIcon scaledImage =
+ new ImageIcon(avatarImage.getImage().getScaledInstance(105, 130,
+ Image.SCALE_SMOOTH));
+
+ JLabel label = new JLabel(scaledImage);
+ avatarPanel.add(label);
+ summaryPanel.add(avatarPanel, BorderLayout.WEST);
+
+ // Create the summary details panel.
+ JPanel detailsPanel = new JPanel();
+ detailsPanel.setLayout(new BorderLayout());
+ detailsPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+ summaryPanel.add(detailsPanel);
+
+ // Labels panel.
+ JPanel labelsPanel = new JPanel(new GridLayout(0, 1, 5, 5));
+ labelsPanel.add(new JLabel(Resources.getString("firstNameNS")));
+ labelsPanel.add(new JLabel(Resources.getString("middleNameNS")));
+ labelsPanel.add(new JLabel(Resources.getString("lastNameNS")));
+ labelsPanel.add(new JLabel(Resources.getString("genderNS")));
+ labelsPanel.add(new JLabel(Resources.getString("ageNS")));
+ labelsPanel.add(new JLabel(Resources.getString("bdayNS")));
+ labelsPanel.add(new JLabel(Resources.getString("emailNS")));
+ labelsPanel.add(new JLabel(Resources.getString("phoneNS")));
+
+ detailsPanel.add(labelsPanel, BorderLayout.WEST);
+
+ // Values panel.
+ JPanel valuesPanel = new JPanel(new GridLayout(0, 1, 5, 5));
+
+ detailsPanel.add(valuesPanel, BorderLayout.CENTER);
+
+ Iterator contactDetails;
+ GenericDetail genericDetail;
+
+ // First name details.
+ contactDetails =
+ contactInfoOpSet.getDetails(contact, FirstNameDetail.class);
+
+ String firstNameDetail = "";
+ while (contactDetails.hasNext())
+ {
+ genericDetail = (FirstNameDetail) contactDetails.next();
+
+ firstNameDetail =
+ firstNameDetail + " " + genericDetail.getDetailValue();
+ }
+
+ if (firstNameDetail.equals(""))
+ firstNameDetail = Resources.getString("notSpecified");
+
+ valuesPanel.add(new JLabel(firstNameDetail));
+
+ // Middle name details.
+ contactDetails =
+ contactInfoOpSet.getDetails(contact, MiddleNameDetail.class);
+
+ String middleNameDetail = "";
+ while (contactDetails.hasNext())
+ {
+ genericDetail = (MiddleNameDetail) contactDetails.next();
+ middleNameDetail =
+ middleNameDetail + " " + genericDetail.getDetailValue();
+ }
+
+ if (middleNameDetail.trim().equals(""))
+ middleNameDetail = Resources.getString("notSpecified");
+
+ valuesPanel.add(new JLabel(middleNameDetail));
+
+ // Last name details.
+ contactDetails =
+ contactInfoOpSet.getDetails(contact, LastNameDetail.class);
+
+ String lastNameDetail = "";
+ while (contactDetails.hasNext())
+ {
+ genericDetail = (LastNameDetail) contactDetails.next();
+
+ lastNameDetail =
+ lastNameDetail + " " + genericDetail.getDetailValue();
+ }
+
+ if (lastNameDetail.trim().equals(""))
+ lastNameDetail = Resources.getString("notSpecified");
+
+ valuesPanel.add(new JLabel(lastNameDetail));
+
+ // Gender details.
+ contactDetails =
+ contactInfoOpSet.getDetails(contact, GenderDetail.class);
+
+ String genderDetail = "";
+ while (contactDetails.hasNext())
+ {
+ genericDetail = (GenderDetail) contactDetails.next();
+ genderDetail = genderDetail + " " + genericDetail.getDetailValue();
+ }
+
+ if (genderDetail.trim().equals(""))
+ genderDetail = Resources.getString("notSpecified");
+
+ valuesPanel.add(new JLabel(genderDetail));
+
+ // Birthday details.
+ contactDetails =
+ contactInfoOpSet.getDetails(contact, BirthDateDetail.class);
+
+ String birthDateDetail = "";
+ String ageDetail = "";
+ if (contactDetails.hasNext())
+ {
+ genericDetail = (BirthDateDetail) contactDetails.next();
+
+ Calendar calendarDetail =
+ (Calendar) genericDetail.getDetailValue();
+
+ Date birthDate = calendarDetail.getTime();
+ DateFormat dateFormat = DateFormat.getDateInstance();
+
+ birthDateDetail = dateFormat.format(birthDate).trim();
+
+ Calendar c = Calendar.getInstance();
+ int age = c.get(Calendar.YEAR) - calendarDetail.get(Calendar.YEAR);
+
+ if (c.get(Calendar.MONTH) < calendarDetail.get(Calendar.MONTH))
+ age--;
+
+ ageDetail = new Integer(age).toString().trim();
+ }
+
+ if (birthDateDetail.equals(""))
+ birthDateDetail = Resources.getString("notSpecified");
+
+ if (ageDetail.equals(""))
+ ageDetail = Resources.getString("notSpecified");
+
+ valuesPanel.add(new JLabel(birthDateDetail));
+ valuesPanel.add(new JLabel(ageDetail));
+
+ // Email details.
+ contactDetails =
+ contactInfoOpSet.getDetails(contact, EmailAddressDetail.class);
+
+ String emailDetail = "";
+ while (contactDetails.hasNext())
+ {
+ genericDetail = (EmailAddressDetail) contactDetails.next();
+ emailDetail = emailDetail + " " + genericDetail.getDetailValue();
+ }
+
+ if (emailDetail.trim().equals(""))
+ emailDetail = Resources.getString("notSpecified");
+
+ valuesPanel.add(new JLabel(emailDetail));
+
+ // Phone number details.
+ contactDetails =
+ contactInfoOpSet.getDetails(contact, PhoneNumberDetail.class);
+
+ String phoneNumberDetail = "";
+ while (contactDetails.hasNext())
+ {
+ genericDetail = (PhoneNumberDetail) contactDetails.next();
+ phoneNumberDetail =
+ phoneNumberDetail + " " + genericDetail.getDetailValue();
+ }
+
+ if (phoneNumberDetail.trim().equals(""))
+ phoneNumberDetail = Resources.getString("notSpecified");
+
+ valuesPanel.add(new JLabel(phoneNumberDetail));
+
+ return summaryPanel;
+ }
+
+ /**
+ * A panel that displays all of the details retrieved from the opSet.
+ *
+ * @return a panel that will be added as the extended tab.
+ */
+ private JPanel createExtendedInfoPanel()
+ {
+ JPanel mainExtendedPanel = new JPanel(new BorderLayout());
+
+ JPanel extendedPanel = new JPanel();
+ extendedPanel.setLayout(new BoxLayout(extendedPanel, BoxLayout.Y_AXIS));
+
+ JPanel imagePanel = new JPanel();
+
+ // The imagePanel will be used for any BinaryDetails and will be added at
+ // the bottom so we don't disrupt the standard look of the other details
+ imagePanel.setLayout(new BoxLayout(imagePanel, BoxLayout.LINE_AXIS));
+ imagePanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory
+ .createTitledBorder(Resources.getString("userPictures")),
+ BorderFactory.createEmptyBorder(0, 5, 5, 5)));
+
+ // Obtain all the details for a contact.
+ Iterator iter = contactInfoOpSet.getAllDetailsForContact(contact);
+
+ GenericDetail detail;
+ JLabel detailLabel;
+ JTextArea detailValueArea;
+ JPanel detailPanel;
+
+ while (iter.hasNext())
+ {
+ detail = (GenericDetail) iter.next();
+
+ if (detail.getDetailValue().toString().equals(""))
+ continue;
+
+ detailLabel = new JLabel();
+ detailValueArea = new JTextArea();
+ detailPanel = new JPanel(new BorderLayout(10, 10));
+
+ detailValueArea.setAlignmentX(JTextArea.CENTER_ALIGNMENT);
+ detailValueArea.setEditable(false);
+ detailValueArea.setLineWrap(true);
+
+ detailPanel.add(detailLabel, BorderLayout.WEST);
+ detailPanel.add(detailValueArea, BorderLayout.CENTER);
+ detailPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+
+ extendedPanel.add(detailPanel);
+
+ if (detail instanceof BinaryDetail)
+ {
+ JLabel imageLabel =
+ new JLabel(new ImageIcon((byte[]) detail
+ .getDetailValue()));
+
+ imagePanel.add(imageLabel);
+ }
+ else if (detail instanceof CalendarDetail)
+ {
+ detailLabel.setText(detail.getDetailDisplayName() + ": ");
+
+ Date detailDate =
+ ((Calendar) detail.getDetailValue()).getTime();
+ DateFormat df = DateFormat.getDateInstance();
+
+ detailValueArea.setText(df.format(detailDate).trim());
+ }
+ else if (detail instanceof LocaleDetail)
+ {
+ detailLabel.setText(detail.getDetailDisplayName() + ": ");
+
+ detailValueArea.setText(((Locale) detail.getDetailValue())
+ .getDisplayName().trim());
+ }
+ else if (detail instanceof TimeZoneDetail)
+ {
+ detailLabel.setText(detail.getDetailDisplayName() + ": ");
+
+ detailValueArea.setText(((TimeZone) detail.getDetailValue())
+ .getDisplayName().trim());
+ }
+ else
+ {
+ detailLabel.setText(detail.getDetailDisplayName() + ": ");
+
+ detailValueArea.setText(
+ detail.getDetailValue().toString().trim());
+ }
+ }
+
+ // If the contact's protocol supports web info, give them a button to
+ // get it
+ if (contact.getProtocolProvider().getOperationSet(
+ OperationSetWebContactInfo.class) != null)
+ {
+ final String urlString = ((OperationSetWebContactInfo) contact
+ .getProtocolProvider().getOperationSet(
+ OperationSetWebContactInfo.class))
+ .getWebContactInfo(contact).toString();
+
+ JLabel webInfoLabel = new JLabel("Click to see web info: ");
+ JEditorPane webInfoValue = new JEditorPane();
+ JPanel webInfoPanel = new JPanel(new BorderLayout());
+
+ webInfoPanel.add(webInfoLabel, BorderLayout.WEST);
+ webInfoPanel.add(webInfoValue, BorderLayout.CENTER);
+
+ extendedPanel.add(webInfoPanel);
+
+ webInfoValue.setOpaque(false);
+ webInfoValue.setContentType("text/html");
+ webInfoValue.setEditable(false);
+ webInfoValue.setText( "<a href='"
+ + urlString + "'>"
+ + contact.getDisplayName()
+ + " web info</a>");
+
+ webInfoValue.addHyperlinkListener(new HyperlinkListener()
+ {
+ public void hyperlinkUpdate(HyperlinkEvent e)
+ {
+ if (e.getEventType()
+ .equals(HyperlinkEvent.EventType.ACTIVATED))
+ {
+ ContactInfoActivator
+ .getBrowserLauncher().openURL(urlString);
+ }
+ }
+ });
+ }
+
+ if (imagePanel.getComponentCount() > 0)
+ mainExtendedPanel.add(imagePanel, BorderLayout.CENTER);
+
+ mainExtendedPanel.add(extendedPanel, BorderLayout.NORTH);
+
+ return mainExtendedPanel;
+ }
+} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDialog.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDialog.java
new file mode 100644
index 0000000..c4ea25a
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDialog.java
@@ -0,0 +1,83 @@
+package net.java.sip.communicator.plugin.contactinfo;
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+import java.awt.*;
+import java.util.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.service.contactlist.*;
+import net.java.sip.communicator.service.protocol.*;
+
+/**
+ * A GUI plug-in for SIP Communicator that will allow cross protocol contact
+ * information viewing and editing.
+ *
+ * @author Adam Goldstein
+ * @author Yana Stamcheva
+ */
+public class ContactInfoDialog
+ extends JFrame
+{
+ /**
+ * The right side of this frame that contains protocol specific contact
+ * details.
+ */
+ protected ContactInfoDetailsPanel detailsPanel
+ = new ContactInfoDetailsPanel();
+
+ /**
+ * The left side of this frame that contains a list of all sub-contacts
+ * associated with the selected contact.
+ */
+ protected ContactInfoContactPanel contactPanel;
+
+ /**
+ * The contact that was right clicked on. The sub-contacts of contactItem
+ * will be the ones selectable in contactPanel.
+ */
+ protected MetaContact metaContact;
+
+ /**
+ * Accepts a MetaContact and constructs a frame with ContactInfoSearchPanel
+ * on the left and an information interface, ContactInfoDetailsPanel,
+ * on the right.
+ * @param metaContact the sub-contacts of this MetaContact that was right
+ * clicked on will be the ones selectable in contactPanel.
+ */
+ public ContactInfoDialog(MetaContact metaContact)
+ {
+ super(Resources.getString("contactInfo"));
+
+ this.metaContact = metaContact;
+
+ this.setTitle(Resources.getString("contactInfo")
+ + ": "
+ + metaContact.getDisplayName());
+
+ Iterator<Contact> subContacts = metaContact.getContacts();
+
+ this.contactPanel
+ = new ContactInfoContactPanel(subContacts, this);
+
+ this.getContentPane().add(contactPanel, BorderLayout.WEST);
+ this.getContentPane().add(detailsPanel, BorderLayout.CENTER);
+
+ this.pack();
+ }
+
+ /**
+ * Loads the details of the given contact.
+ *
+ * @param contact the <tt>Contact</tt>, which details we load
+ */
+ public void loadContactDetails(Contact contact)
+ {
+ this.detailsPanel.loadContactDetails(contact);
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoMenuItem.java b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoMenuItem.java
new file mode 100644
index 0000000..dbddc90
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/ContactInfoMenuItem.java
@@ -0,0 +1,67 @@
+package net.java.sip.communicator.plugin.contactinfo;
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+import java.awt.*;
+import java.awt.event.*;
+
+import javax.swing.*;
+
+import net.java.sip.communicator.service.contactlist.*;
+import net.java.sip.communicator.service.gui.*;
+
+/**
+ *
+ * @author Adam Goldstein
+ */
+public class ContactInfoMenuItem
+ extends JMenuItem
+ implements ContactAwareComponent,
+ ActionListener
+{
+ private MetaContact metaContact;
+
+ /**
+ * Creates a <tt>ContactInfoMenuItem</tt>.
+ */
+ public ContactInfoMenuItem()
+ {
+ super( Resources.getString("contactInfo"),
+ Resources.getImage("infoIcon"));
+
+ this.addActionListener(this);
+ }
+
+ /**
+ * Sets the currently selected <tt>MetaContact</tt>.
+ * @param metaContact the currently selected meta contact
+ */
+ public void setCurrentContact(MetaContact metaContact)
+ {
+ this.metaContact = metaContact;
+ }
+
+ public void setCurrentContactGroup(MetaContactGroup metaGroup)
+ {}
+
+ /**
+ * Initializes and shows the contact details dialog.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ ContactInfoDialog cinfoDialog = new ContactInfoDialog(metaContact);
+
+ cinfoDialog.setLocation(
+ Toolkit.getDefaultToolkit().getScreenSize().width/2
+ - cinfoDialog.getWidth()/2,
+ Toolkit.getDefaultToolkit().getScreenSize().height/2
+ - cinfoDialog.getHeight()/2
+ );
+
+ cinfoDialog.setVisible(true);
+ }
+} \ No newline at end of file
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/Resources.java b/src/net/java/sip/communicator/plugin/contactinfo/Resources.java
new file mode 100644
index 0000000..18910c8
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/Resources.java
@@ -0,0 +1,87 @@
+/*
+ * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+
+package net.java.sip.communicator.plugin.contactinfo;
+
+import java.awt.image.*;
+import java.io.*;
+import java.util.*;
+
+import javax.imageio.*;
+import javax.swing.*;
+
+import net.java.sip.communicator.util.*;
+/**
+ * The Messages class manages the access to the internationalization
+ * properties files.
+ * @author Yana Stamcheva
+ */
+public class Resources {
+
+ private static Logger log = Logger.getLogger(Resources.class);
+
+ private static final String BUNDLE_NAME
+ = "net.java.sip.communicator.plugin.contactinfo.resources";
+
+ private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle
+ .getBundle(BUNDLE_NAME);
+
+ /**
+ * Returns an internationalized string corresponding to the given key.
+ * @param key The key of the string.
+ * @return An internationalized string corresponding to the given key.
+ */
+ public static String getString(String key) {
+ try {
+ return RESOURCE_BUNDLE.getString(key);
+
+ } catch (MissingResourceException e) {
+
+ return '!' + key + '!';
+ }
+ }
+
+ /**
+ * Loads an image from a given image identifier.
+ * @param imageID The identifier of the image.
+ * @return The image for the given identifier.
+ */
+ public static ImageIcon getImage(String imageID) {
+ BufferedImage image = null;
+
+ String path = Resources.getString(imageID);
+ try {
+ image = ImageIO.read(Resources.class.getClassLoader()
+ .getResourceAsStream(path));
+
+ } catch (IOException e) {
+ log.error("Failed to load image:" + path, e);
+ }
+
+ return new ImageIcon(image);
+ }
+
+ /**
+ * Loads an image from a given image identifier.
+ * @param imageID The identifier of the image.
+ * @return The image for the given identifier.
+ */
+ public static byte[] getImageInBytes(String imageID) {
+ byte[] image = new byte[100000];
+
+ String path = Resources.getString(imageID);
+ try {
+ Resources.class.getClassLoader()
+ .getResourceAsStream(path).read(image);
+
+ } catch (IOException e) {
+ log.error("Failed to load image:" + path, e);
+ }
+
+ return image;
+ }
+}
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/contactinfo.manifest.mf b/src/net/java/sip/communicator/plugin/contactinfo/contactinfo.manifest.mf
new file mode 100644
index 0000000..530dcec
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/contactinfo.manifest.mf
@@ -0,0 +1,27 @@
+Bundle-Activator: net.java.sip.communicator.plugin.contactinfo.ContactInfoActivator
+Bundle-Name: Contact Info
+Bundle-Description: A plug-in that can show cross protocol user info.
+Bundle-Vendor: sip-communicator.org
+Bundle-Version: 0.0.1
+Import-Package: org.osgi.framework,
+ net.java.sip.communicator.util,
+ net.java.sip.communicator.service.contactlist,
+ net.java.sip.communicator.service.contactlist.event,
+ net.java.sip.communicator.service.gui,
+ net.java.sip.communicator.service.gui.event,
+ net.java.sip.communicator.service.protocol,
+ net.java.sip.communicator.service.browserlauncher,
+ javax.swing,
+ javax.swing.event,
+ javax.swing.table,
+ javax.swing.text,
+ javax.swing.text.html,
+ javax.accessibility,
+ javax.swing.plaf,
+ javax.swing.plaf.metal,
+ javax.swing.plaf.basic,
+ javax.imageio,
+ javax.swing.filechooser,
+ javax.swing.tree,
+ javax.swing.undo,
+ javax.swing.border \ No newline at end of file
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/resources.properties b/src/net/java/sip/communicator/plugin/contactinfo/resources.properties
new file mode 100644
index 0000000..f010002
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/resources.properties
@@ -0,0 +1,22 @@
+contactInfo=Contact details
+contacts=Contacts
+selectUser=Select a user
+summary=Summary
+summaryDesc=Summary of contact info for
+extended=Extended
+extendedDesc=Extended contact info for
+notSupported=This protocol doesn't support server stored details for now. Try one of the other protocols.
+clickWeb=Click for Web Info
+webInfo=Web Info
+firstNameNS=First Name:
+middleNameNS=Middle Name:
+lastNameNS=Last Name:
+ageNS=Age:
+bdayNS=Birth Date:
+genderNS=Gender:
+emailNS=E-mail:
+phoneNS=Phone:
+userPictures=User Pictures
+notSpecified=[Not specified]
+infoIcon=net/java/sip/communicator/plugin/contactinfo/resources/userInfo16x16.png
+defaultPersonIcon=net/java/sip/communicator/plugin/contactinfo/resources/personPhoto.png \ No newline at end of file
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/resources/personPhoto.png b/src/net/java/sip/communicator/plugin/contactinfo/resources/personPhoto.png
new file mode 100644
index 0000000..47a8837
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/resources/personPhoto.png
Binary files differ
diff --git a/src/net/java/sip/communicator/plugin/contactinfo/resources/userInfo16x16.png b/src/net/java/sip/communicator/plugin/contactinfo/resources/userInfo16x16.png
new file mode 100644
index 0000000..19210b3
--- /dev/null
+++ b/src/net/java/sip/communicator/plugin/contactinfo/resources/userInfo16x16.png
Binary files differ