From da09f9d5bc05a3546a0cff79646368464f43a821 Mon Sep 17 00:00:00 2001 From: Yana Stamcheva Date: Wed, 23 Jan 2008 13:10:42 +0000 Subject: Contact details plugin --- .../main/contactlist/ContactRightButtonMenu.java | 50 +-- .../plugin/contactinfo/ContactInfoActivator.java | 71 +++ .../contactinfo/ContactInfoContactPanel.java | 185 ++++++++ .../contactinfo/ContactInfoDetailsPanel.java | 490 +++++++++++++++++++++ .../plugin/contactinfo/ContactInfoDialog.java | 83 ++++ .../plugin/contactinfo/ContactInfoMenuItem.java | 67 +++ .../communicator/plugin/contactinfo/Resources.java | 87 ++++ .../plugin/contactinfo/contactinfo.manifest.mf | 27 ++ .../plugin/contactinfo/resources.properties | 22 + .../plugin/contactinfo/resources/personPhoto.png | Bin 0 -> 4045 bytes .../plugin/contactinfo/resources/userInfo16x16.png | Bin 0 -> 465 bytes 11 files changed, 1036 insertions(+), 46 deletions(-) create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/ContactInfoActivator.java create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/ContactInfoContactPanel.java create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDetailsPanel.java create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/ContactInfoDialog.java create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/ContactInfoMenuItem.java create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/Resources.java create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/contactinfo.manifest.mf create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/resources.properties create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/resources/personPhoto.png create mode 100644 src/net/java/sip/communicator/plugin/contactinfo/resources/userInfo16x16.png (limited to 'src') 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 BrowserLauncherService obtained from the bundle + * context. + * @return the BrowserLauncherService 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 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 Contact 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: - + *

+ * 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( "" + + contact.getDisplayName() + + " web info"); + + 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 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 Contact, 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 ContactInfoMenuItem. + */ + public ContactInfoMenuItem() + { + super( Resources.getString("contactInfo"), + Resources.getImage("infoIcon")); + + this.addActionListener(this); + } + + /** + * Sets the currently selected MetaContact. + * @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 Binary files /dev/null and b/src/net/java/sip/communicator/plugin/contactinfo/resources/personPhoto.png 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 Binary files /dev/null and b/src/net/java/sip/communicator/plugin/contactinfo/resources/userInfo16x16.png differ -- cgit v1.1