diff options
author | Damian Minkov <damencho@jitsi.org> | 2013-08-28 16:32:42 +0300 |
---|---|---|
committer | Damian Minkov <damencho@jitsi.org> | 2013-08-28 16:32:42 +0300 |
commit | e9de32d9ce47a826be4c35997502d0360490f9be (patch) | |
tree | a0e4b27e299de2dc1d11662c44d1aa6652a671d0 /src | |
parent | b4c90af94926b9904ba2e75286339faad986c0bb (diff) | |
download | jitsi-e9de32d9ce47a826be4c35997502d0360490f9be.zip jitsi-e9de32d9ce47a826be4c35997502d0360490f9be.tar.gz jitsi-e9de32d9ce47a826be4c35997502d0360490f9be.tar.bz2 |
Adds web page button, if contacts has web page detail, shows a button to open that page.
Diffstat (limited to 'src')
4 files changed, 435 insertions, 0 deletions
diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java index 991281c..25e1f86 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListTreeCellRenderer.java @@ -170,6 +170,11 @@ public class ContactListTreeCellRenderer private final SIPCommButton chatButton = new SIPCommButton(); /** + * The web button. + */ + private final SIPCommButton webButton = new SIPCommButton(); + + /** * The add contact button. */ private final SIPCommButton addContactButton = new SIPCommButton(); @@ -338,6 +343,13 @@ public class ContactListTreeCellRenderer } } }); + webButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + openURL(treeContactList, treeNode, webButton); + } + }); initButtonToolTips(); this.setToolTipText(""); @@ -483,6 +495,7 @@ public class ContactListTreeCellRenderer this.remove(desktopSharingButton); this.remove(chatButton); this.remove(addContactButton); + this.remove(webButton); clearCustomActionButtons(); @@ -748,6 +761,7 @@ public class ContactListTreeCellRenderer this.remove(callVideoButton); this.remove(desktopSharingButton); this.remove(addContactButton); + this.remove(webButton); clearCustomActionButtons(); @@ -848,6 +862,13 @@ public class ContactListTreeCellRenderer x += addButton(addContactButton, ++gridX, x, false); } + //webButton + if (uiContact.getDescriptor() instanceof MetaContact) + { + if(containsWebPageDetail(uiContact)) + x += addButton(webButton, ++gridX, x, false); + } + // The list of the contact actions // we will create a button for every action Collection<SIPCommButton> contactActions @@ -1245,6 +1266,7 @@ public class ContactListTreeCellRenderer callVideoButton.getModel().setRollover(false); desktopSharingButton.getModel().setRollover(false); addContactButton.getModel().setRollover(false); + webButton.getModel().setRollover(false); if (customActionButtons != null) { @@ -1290,6 +1312,9 @@ public class ContactListTreeCellRenderer if (!addContactButton.equals(excludeComponent)) addContactButton.getModel().setRollover(false); + if (!webButton.equals(excludeComponent)) + webButton.getModel().setRollover(false); + if (customActionButtons != null) { Iterator<JButton> buttonsIter = customActionButtons.iterator(); @@ -1376,6 +1401,247 @@ public class ContactListTreeCellRenderer ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL_ROLLOVER)); addContactButton.setPressedIcon( ImageLoader.getImage(ImageLoader.ADD_CONTACT_BUTTON_SMALL_PRESSED)); + + webButton.setIconImage( + ImageLoader.getImage(ImageLoader.WEB_BUTTON)); + webButton.setRolloverIcon( + ImageLoader.getImage(ImageLoader.WEB_BUTTON_ROLLOVER)); + webButton.setPressedIcon( + ImageLoader.getImage(ImageLoader.WEB_BUTTON_PRESSED)); + } + + /** + * Listens for contact details if not cached, we will receive when they + * are retrieved to update current web button state, if meanwhile + * user hasn't changed the current contact. + */ + private class WebDetailsListener + implements OperationSetServerStoredContactInfo.DetailsResponseListener + { + /** + * The source this listener is created for, if current tree node + * changes ignore any event. + */ + private Object source; + + /** + * The button to change. + */ + private JButton webButton; + + /** + * The ui contact to update after changes. + */ + private UIContact uiContact; + + /** + * Create listener. + * @param source the contact this listener is for, if different + * than current ignore. + * @param webButton + * @param uiContact the contact to refresh + */ + WebDetailsListener(Object source, JButton webButton, UIContact uiContact) + { + this.source = source; + this.webButton = webButton; + this.uiContact = uiContact; + } + + /** + * Details have been retrieved. + * @param details the details retrieved if any. + */ + public void detailsRetrieved(Iterator<GenericDetail> details) + { + // if treenode has changed ignore + if(!source.equals(treeNode)) + return; + + while(details.hasNext()) + { + GenericDetail d = details.next(); + + if(d instanceof WebPageDetail) + { + final WebPageDetail webd = (WebPageDetail)d; + if(webd.getDetailValue() != null) + { + SwingUtilities.invokeLater(new Runnable() + { + public void run() + { + webButton.setEnabled(true); + + treeContactList.refreshContact(uiContact); + } + }); + + return; + } + } + } + } + } + + /** + * Checks for existence of at least single web page detail. + * @param uiContact the contact to check + * @return true if at least one detail available, false otherwise. + */ + private boolean containsWebPageDetail(UIContact uiContact) + { + WebDetailsListener webDetailsListener = + new WebDetailsListener(treeNode, webButton, uiContact); + + return getWebPageDetails(uiContact, webDetailsListener, true) != null; + } + + /** + * Retrieves all web page details for the supplied uiContact. + * @param uiContact the contacts + * @param webDetailsListener the listener to wait for details retrieval, + * or null of we do not want to wait + * @param returnFirst should we return after founding the first one, + * used for check whether such detail exist + * @return list of details or null if currently not available + */ + private static List<WebPageDetail> getWebPageDetails( + UIContact uiContact, + WebDetailsListener webDetailsListener, + boolean returnFirst) + { + Iterator<Contact> contacts + = ((MetaContact)uiContact.getDescriptor()) + .getContactsForOperationSet( + OperationSetServerStoredContactInfo.class).iterator(); + + List<WebPageDetail> res = new ArrayList<WebPageDetail>(); + + boolean foundWebLink = false; + while (contacts.hasNext()) + { + Contact contact = contacts.next(); + OperationSetServerStoredContactInfo opset + = contact.getProtocolProvider().getOperationSet( + OperationSetServerStoredContactInfo.class); + + Iterator<GenericDetail> iter = + opset.requestAllDetailsForContact( + contact, webDetailsListener); + + if(iter == null) + continue; + + while(iter.hasNext()) + { + GenericDetail d = iter.next(); + if(d instanceof WebPageDetail) + { + final WebPageDetail webd = (WebPageDetail)d; + if(webd.getDetailValue() != null) + { + res.add(webd); + + if(returnFirst) + { + foundWebLink = true; + break; + } + } + } + } + + if(returnFirst && foundWebLink) + break; + } + + if(returnFirst) + { + if(res.isEmpty()) + return null; + } + + return res; + } + + /** + * Opens url, used from webButton. + * @param treeContactList the contactlist component + * @param treeNode the currently selected node + * @param button the button that was clicked + */ + private static void openURL( + TreeContactList treeContactList, TreeNode treeNode, JButton button) + { + if (treeNode != null && treeNode instanceof ContactNode) + { + UIContact contactDescriptor + = ((ContactNode) treeNode).getContactDescriptor(); + + if (contactDescriptor instanceof MetaUIContact) + { + List<WebPageDetail> details = + getWebPageDetails(contactDescriptor, null, false); + + if(details == null) + return; + + if(details.size() == 1) + { + GuiActivator.getBrowserLauncher().openURL( + details.get(0).getURL().toString()); + } + else + { + Point location = new Point(button.getX(), + button.getY() + button.getHeight()); + + SwingUtilities.convertPointToScreen( + location, treeContactList); + + location.y = location.y + + treeContactList.getPathBounds( + treeContactList.getSelectionPath()).y; + location.x += 8; + location.y -= 8; + + List<JMenuItem> items = new ArrayList<JMenuItem>(); + Iterator<WebPageDetail> detailIterator = details.iterator(); + while(detailIterator.hasNext()) + { + final WebPageDetail wd = detailIterator.next(); + String url = wd.getDetailValue().toString(); + + String displayStr = url; + // do not display too long links + if(displayStr.length() > 60) + { + displayStr = displayStr.substring(0, 60); + displayStr += "..."; + } + final JMenuItem menuItem = new JMenuItem(displayStr); + menuItem.setName(url); + menuItem.setToolTipText(url); + + menuItem.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + GuiActivator.getBrowserLauncher().openURL( + menuItem.getName()); + } + }); + items.add(menuItem); + } + + new ExtendedPopupMenu( + treeContactList, + null, + items).showPopupMenu(location.x, location.y); + } + } + } } /** @@ -1572,6 +1838,8 @@ public class ContactListTreeCellRenderer .getI18NString("service.gui.SEND_MESSAGE")); addContactButton.setToolTipText(GuiActivator.getResources() .getI18NString("service.gui.ADD_CONTACT")); + webButton.setToolTipText(GuiActivator.getResources() + .getI18NString("service.gui.WEBPAGE")); // We need to explicitly remove the buttons from the tooltip manager, // because we're going to manager the tooltip ourselves in the @@ -1583,5 +1851,6 @@ public class ContactListTreeCellRenderer ttManager.unregisterComponent(desktopSharingButton); ttManager.unregisterComponent(chatButton); ttManager.unregisterComponent(addContactButton); + ttManager.unregisterComponent(webButton); } } diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java index cbb4780..5598b87 100644 --- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java +++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java @@ -329,6 +329,24 @@ public class ImageLoader = new ImageID("service.gui.buttons.ADD_CONTACT_BUTTON_SMALL_PRESSED"); /** + * The web button image. + */ + public static final ImageID WEB_BUTTON + = new ImageID("service.gui.buttons.WEB_BUTTON"); + + /** + * The call web pressed image. + */ + public static final ImageID WEB_BUTTON_ROLLOVER + = new ImageID("service.gui.buttons.WEB_BUTTON_ROLLOVER"); + + /** + * The web button pressed image. + */ + public static final ImageID WEB_BUTTON_PRESSED + = new ImageID("service.gui.buttons.WEB_BUTTON_PRESSED"); + + /** * The chat button small image. */ public static final ImageID CHAT_BUTTON_SMALL diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java b/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java index 5f087c5..af1be57 100644 --- a/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java +++ b/src/net/java/sip/communicator/impl/protocol/jabber/InfoRetreiver.java @@ -7,6 +7,7 @@ package net.java.sip.communicator.impl.protocol.jabber; import java.lang.reflect.*; +import java.net.*; import java.util.*; import net.java.sip.communicator.service.protocol.ServerStoredDetails.*; @@ -288,6 +289,14 @@ public class InfoRetreiver byte[] imageBytes = card.getAvatar(); if(imageBytes != null && imageBytes.length > 0) result.add(new ImageDetail("Image", imageBytes)); + + try + { + tmp = card.getField("URL"); + if(tmp != null) + result.add(new WebPageDetail(new URL(tmp))); + } + catch(MalformedURLException e){} } catch (Throwable exc) { diff --git a/src/net/java/sip/communicator/plugin/desktoputil/ExtendedPopupMenu.java b/src/net/java/sip/communicator/plugin/desktoputil/ExtendedPopupMenu.java new file mode 100644 index 0000000..796d306 --- /dev/null +++ b/src/net/java/sip/communicator/plugin/desktoputil/ExtendedPopupMenu.java @@ -0,0 +1,139 @@ +/* + * Jitsi, 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.desktoputil; + +import net.java.sip.communicator.util.skin.*; + +import javax.swing.*; +import java.awt.*; +import java.util.List; + +/** + * The <tt>ExtendedPopupMenu</tt> is the dialog shown to let the user choose + * from several options. + * + * @author Damian Minkov + */ +public class ExtendedPopupMenu + extends SIPCommPopupMenu + implements Skinnable +{ + /** + * Serial version UID. + */ + private static final long serialVersionUID = 0L; + + /** + * The invoker component. + */ + private final JComponent invoker; + + /** + * Creates this dialog by specifying a list of items to choose from. + * + * @param invoker the invoker of this pop up + * @param title + * @param menuItems the list of items to select through + */ + public ExtendedPopupMenu(JComponent invoker, + String title, + List<JMenuItem> menuItems) + { + if (invoker != null) + this.invoker = invoker; + else + this.invoker = new JPanel(); + + this.init(title); + + for (JMenuItem menuItem : menuItems) + { + this.add(menuItem); + } + } + + /** + * Initializes and add some common components. + * + * @param infoString the string we'd like to show on the top of this + * popup menu + */ + private void init(String infoString) + { + setInvoker(invoker); + + if(infoString != null) + { + this.add(createInfoLabel(infoString)); + + this.addSeparator(); + } + + this.setFocusable(true); + } + + /** + * Shows the dialog at the given location. + * + * @param x the x coordinate + * @param y the y coordinate + */ + public void showPopupMenu(int x, int y) + { + setLocation(x, y); + setVisible(true); + } + + /** + * Shows this popup menu regarding to its invoker location. + */ + public void showPopupMenu() + { + Point location = new Point(invoker.getX(), + invoker.getY() + invoker.getHeight()); + + SwingUtilities + .convertPointToScreen(location, invoker.getParent()); + setLocation(location); + setVisible(true); + } + + /** + * Creates the info label. + * + * @param infoString the string we'd like to show on the top of this + * popup menu + * @return the created info label + */ + private Component createInfoLabel(String infoString) + { + JMenuItem infoLabel = new JMenuItem(); + + infoLabel.setEnabled(false); + infoLabel.setFocusable(false); + + infoLabel.setText("<html><b>" + infoString + "</b></html>"); + + return infoLabel; + } + + /** + * Reloads all menu items. + */ + public void loadSkin() + { + Component[] components = getComponents(); + for(Component component : components) + { + if(component instanceof Skinnable) + { + Skinnable skinnableComponent = (Skinnable) component; + skinnableComponent.loadSkin(); + } + } + } +} |