Contact tooltips containing images, protocol contacts and status icons.

cusax-fix
Yana Stamcheva 17 years ago
parent 32ee340f77
commit efea236c1d

@ -146,4 +146,7 @@ toolbarRolloverBackground=414141
contactListContactForeground=000000
# Contactlist group text foreground color.
contactListGroupForeground=000000
contactListGroupForeground=000000
# Tooltip background.
tooltipBackground=e8e9ef

@ -697,6 +697,14 @@ public void run()
*/
private void setDefaultThemePack()
{
// Show tooltips immediately and specify a custom background.
ToolTipManager toolTipManager = ToolTipManager.sharedInstance();
UIManager.put("ToolTip.background",
new Color(GuiActivator.getResources()
.getColor("tooltipBackground")));
toolTipManager.setInitialDelay(0);
toolTipManager.setEnabled(true);
// we need to set the UIDefaults class loader so that it may access
// resources packed inside OSGI bundles
UIManager.put("ClassLoader", getClass().getClassLoader());

@ -125,9 +125,8 @@ private void initCallLabel(JLabel callLabel)
boolean hasMoreParticipants = false;
String text = "";
ImageIcon imageIcon = ImageUtils.scaleIconWithinBounds(
new ImageIcon(ImageLoader
.getImage(ImageLoader.DEFAULT_USER_PHOTO)),
ImageIcon imageIcon = ImageUtils.getScaledRoundedImage(
ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO),
40, 45);
while (participantsIter.hasNext())

@ -199,20 +199,11 @@ else if(contact != null)
}
}
if(contactImage != null)
{
Image image = ImageLoader.getBytesInImage(contactImage);
if(image == null)
return null;
return ImageUtils.scaleIconWithinBounds(
new ImageIcon(image),
AVATAR_ICON_WIDTH,
AVATAR_ICON_HEIGHT
);
}
else
return null;
return ImageUtils.getScaledRoundedImage(
contactImage,
AVATAR_ICON_WIDTH,
AVATAR_ICON_HEIGHT
);
}
/**

@ -60,11 +60,10 @@ public class ChatContactPanel
private JPanel personPhotoPanel = new JPanel(new BorderLayout());
private JLabel personPhotoLabel = new JLabel(ImageUtils
.scaleIconWithinBounds(
new ImageIcon(ImageLoader
.getImage(ImageLoader.DEFAULT_USER_PHOTO)),
ChatContact.AVATAR_ICON_WIDTH,
ChatContact.AVATAR_ICON_HEIGHT));
.getScaledRoundedImage(
ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO),
ChatContact.AVATAR_ICON_WIDTH,
ChatContact.AVATAR_ICON_HEIGHT));
private JLabel personNameLabel = new JLabel();

@ -527,7 +527,6 @@ public void fireContactListEvent(MetaContact sourceContact,
}
}
/**
* Manages a mouse click over the contact list.
*
@ -1552,4 +1551,92 @@ else if (returnCode == MessageDialog.OK_DONT_ASK_CODE)
}
}
}
/**
* Creates a customized tooltip for this contact list.
*
* @return The customized tooltip.
*/
public JToolTip createToolTip()
{
Point currentMouseLocation = MouseInfo.getPointerInfo().getLocation();
SwingUtilities.convertPointFromScreen(currentMouseLocation, this);
int index = this.locationToIndex(currentMouseLocation);
Object element = this.getModel().getElementAt(index);
MetaContactTooltip tip = new MetaContactTooltip();
if (element instanceof MetaContact)
{
MetaContact metaContact = (MetaContact) element;
byte[] avatarImage = metaContact.getAvatar();
if (avatarImage != null && avatarImage.length > 0)
tip.setImage(new ImageIcon(metaContact.getAvatar()));
tip.setTitle(metaContact.getDisplayName());
Iterator<Contact> i = metaContact.getContacts();
while (i.hasNext())
{
Contact protocolContact = (Contact) i.next();
Image protocolStatusIcon
= ImageLoader.getBytesInImage(
protocolContact.getPresenceStatus().getStatusIcon());
String contactAddress = protocolContact.getAddress();
String statusMessage = protocolContact.getStatusMessage();
tip.addProtocolContact(new ImageIcon(protocolStatusIcon),
contactAddress);
}
}
else if (element instanceof MetaContactGroup)
{
MetaContactGroup metaGroup = (MetaContactGroup) element;
tip.setTitle(metaGroup.getGroupName());
}
tip.setComponent(this);
return tip;
}
/**
* Returns the string to be used as the tooltip for <i>event</i>. We don't
* really use this string, but we need to return different string each time
* in order to make the TooltipManager change the tooltip over the different
* cells in the JList.
*
* @return the string to be used as the tooltip for <i>event</i>.
*/
public String getToolTipText(MouseEvent event)
{
Point currentMouseLocation = event.getPoint();
int index = this.locationToIndex(currentMouseLocation);
Object element = this.getModel().getElementAt(index);
if (element instanceof MetaContact)
{
MetaContact metaContact = (MetaContact) element;
return metaContact.getDisplayName();
}
else if (element instanceof MetaContactGroup)
{
MetaContactGroup metaGroup = (MetaContactGroup) element;
return metaGroup.getGroupName();
}
return null;
}
}

@ -8,11 +8,7 @@
package net.java.sip.communicator.impl.gui.main.contactlist;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
@ -20,7 +16,6 @@
import net.java.sip.communicator.impl.gui.main.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.contactlist.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.*;
/**
@ -32,7 +27,7 @@
* @author Yana Stamcheva
*/
public class ContactListCellRenderer
extends JPanel
extends JPanel
implements ListCellRenderer
{
private Logger logger = Logger.getLogger(ContactListCellRenderer.class);
@ -101,6 +96,8 @@ public ContactListCellRenderer(MainFrame mainFrame)
this.add(nameLabel, BorderLayout.CENTER);
this.add(photoLabel, BorderLayout.EAST);
this.setToolTipText("");
}
/**
@ -147,10 +144,13 @@ public Component getListCellRendererComponent(JList list, Object value,
byte[] avatar = contactItem.getAvatar(true);
if (avatar != null && avatar.length > 0)
{
Image roundedAvatar = createRoundImage(avatar);
ImageIcon roundedAvatar
= ImageUtils.getScaledRoundedImage( avatar,
AVATAR_WIDTH,
AVATAR_HEIGHT);
if (roundedAvatar != null)
this.photoLabel.setIcon(new ImageIcon(roundedAvatar));
this.photoLabel.setIcon(roundedAvatar);
}
// We should set the bounds of the cell explicitely in order to
@ -165,8 +165,6 @@ public Component getListCellRendererComponent(JList list, Object value,
list.getWidth() - 28, 0, 25, 30);
this.isLeaf = true;
this.setToolTipText(getContactToolTip(contactItem));
}
else if (value instanceof MetaContactGroup)
{
@ -212,8 +210,6 @@ else if (value instanceof MetaContactGroup)
this.buttonsPanel.add(groupContentIndicator);
this.isLeaf = false;
this.setToolTipText(getGroupToolTip(groupItem));
}
// this.add(buttonsPanel, BorderLayout.EAST);
@ -222,51 +218,6 @@ else if (value instanceof MetaContactGroup)
return this;
}
/**
* Creates a rounded avatar image.
*
* @param avatarBytes The bytes of the initial avatar image.
*
* @return The rounded corner image.
*/
private Image createRoundImage(byte[] avatarBytes)
{
BufferedImage destImage = null;
try
{
InputStream in = new ByteArrayInputStream(avatarBytes);
BufferedImage avatarImage = ImageIO.read(in);
ImageIcon scaledImage = ImageUtils.scaleIconWithinBounds(
new ImageIcon(avatarImage),
AVATAR_WIDTH,
AVATAR_HEIGHT);
destImage
= new BufferedImage(scaledImage.getIconWidth(),
scaledImage.getIconHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = destImage.createGraphics();
AntialiasingManager.activateAntialiasing(g);
g.setColor(Color.WHITE);
g.fillRoundRect(0, 0,
scaledImage.getIconWidth(),
scaledImage.getIconHeight(),
10, 10);
g.setComposite(AlphaComposite.SrcIn);
g.drawImage(scaledImage.getImage(), 0, 0, null);
}
catch (Exception e)
{
logger.error("Could not create image.", e);
}
return destImage;
}
/**
* Paint a background for all groups and a round blue border and background
@ -315,52 +266,4 @@ else if (index%2 > 0)
7, 7);
}
}
/**
*
* @param contactItem
*/
private String getContactToolTip(MetaContact contactItem)
{
String toolTipText = "<html>";
toolTipText += "<b>"+contactItem.getDisplayName()+"</b>";
Iterator<Contact> i = contactItem.getContacts();
while (i.hasNext())
{
Contact protocolContact = (Contact) i.next();
Image protocolStatusIcon
= ImageLoader.getBytesInImage(
protocolContact.getPresenceStatus().getStatusIcon());
String contactDisplayName = protocolContact.getDisplayName();
String contactAddress = protocolContact.getAddress();
String statusMessage = protocolContact.getStatusMessage();
toolTipText
+= "<br>"
+ ((!contactDisplayName
.equals(contactAddress))
? contactDisplayName + " ("+contactAddress + ")"
: contactDisplayName)
+ ((statusMessage != null && statusMessage.length() > 0)
? " - " + statusMessage : "");
}
toolTipText += "</html>";
return toolTipText;
}
private String getGroupToolTip(MetaContactGroup groupItem)
{
String toolTipText = "<html>";
toolTipText += groupItem.getGroupName();
toolTipText += "</html>";
return toolTipText;
}
}
}

@ -802,4 +802,4 @@ public void pluginComponentRemoved(PluginComponentEvent event)
this.remove((Component) c.getComponent());
}
}
}

@ -0,0 +1,156 @@
/*
* 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.impl.gui.main.contactlist;
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.metal.*;
import net.java.sip.communicator.impl.gui.utils.*;
/**
* The tooltip shown over a contact in the contact list.
*
* @author Yana Stamcheva
*/
public class MetaContactTooltip
extends JToolTip
{
private static final int textRowHeight = 25;
private JPanel mainPanel = new JPanel(new BorderLayout(5, 5));
private JLabel imageLabel = new JLabel();
private JLabel titleLabel = new JLabel();
private JPanel centerPanel = new JPanel(new BorderLayout());
private JPanel protocolContactsPanel = new JPanel();
private int textWidth;
private int textHeight;
/**
* Created a <tt>MetaContactTooltip</tt>.
*/
public MetaContactTooltip()
{
this.setUI(new ImageToolTipUI());
this.setLayout(new BorderLayout());
mainPanel.setOpaque(false);
centerPanel.setOpaque(false);
protocolContactsPanel.setOpaque(false);
mainPanel.add(imageLabel, BorderLayout.WEST);
mainPanel.add(centerPanel, BorderLayout.CENTER);
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD));
centerPanel.add(titleLabel, BorderLayout.NORTH);
centerPanel.add(protocolContactsPanel, BorderLayout.CENTER);
protocolContactsPanel.setLayout(
new BoxLayout(protocolContactsPanel, BoxLayout.Y_AXIS));
this.add(mainPanel);
}
/**
* Sets the given image to this tooltip.
*
* @param imageIcon The image icon to set.
*/
public void setImage(ImageIcon imageIcon)
{
imageLabel.setIcon(imageIcon);
}
/**
* Sets the title of the tooltip. The text would be shown in bold on the top
* of the tooltip panel.
*
* @param titleText The title of the tooltip.
*/
public void setTitle(String titleText)
{
titleLabel.setText(titleText);
int stringWidth = GuiUtils.getStringWidth(titleLabel, titleText);
if (textWidth < stringWidth)
textWidth = stringWidth;
textHeight += textRowHeight;
}
/**
* Adds a protocol contact icon and name to this tooltip.
*
* @param protocolContactIcon The icon for the protocol contact to add.
* @param protocolContactName The name of the protocol contact to add.
*/
public void addProtocolContact( ImageIcon protocolContactIcon,
String protocolContactName)
{
JLabel protocolContactLabel = new JLabel( protocolContactName,
protocolContactIcon,
JLabel.CENTER);
protocolContactsPanel.add(protocolContactLabel);
int stringWidth
= GuiUtils.getStringWidth(protocolContactLabel, protocolContactName)
+ protocolContactIcon.getIconWidth()
+ protocolContactLabel.getIconTextGap();
if (textWidth < stringWidth)
textWidth = stringWidth;
textHeight += textRowHeight;
}
/**
* Customized UI for this MetaContactTooltip.
*/
private class ImageToolTipUI extends MetalToolTipUI
{
/**
* Overwrite the UI paint method to do nothing in order fix double
* painting of the tooltip text.
*/
public void paint(Graphics g, JComponent c)
{}
/**
* Returns the size of the given component.
* @return the size of the given component.
*/
public Dimension getPreferredSize(JComponent c)
{
int width = 0;
if (imageLabel.getIcon() != null)
width += imageLabel.getIcon().getIconWidth();
width += textWidth;
int imageHeight = 0;
if (imageLabel.getIcon() != null)
imageHeight = imageLabel.getIcon().getIconHeight();
int height = imageHeight > textHeight ?
imageHeight : textHeight;
return new Dimension(width + 15, height);
}
}
}

@ -7,10 +7,7 @@
package net.java.sip.communicator.impl.gui.main.presence;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
@ -38,8 +35,7 @@ public class AccountStatusPanel
private JPanel rightPanel = new JPanel(new GridLayout(0, 1, 0, 0));
private ImageIcon imageIcon = ImageUtils.scaleIconWithinBounds(
new ImageIcon(ImageLoader
.getImage(ImageLoader.DEFAULT_USER_PHOTO)),
ImageLoader.getImage(ImageLoader.DEFAULT_USER_PHOTO),
AVATAR_ICON_WIDTH, AVATAR_ICON_HEIGHT);
private JLabel accountImageLabel = new JLabel(imageIcon);
@ -153,12 +149,15 @@ public void run()
byte[] accountImage
= AccountInfoUtils.getImage(accountInfoOpSet);
if (accountImage != null)
{
Image roundedImage = createRoundImage(accountImage);
ImageIcon roundedImage
= ImageUtils.getScaledRoundedImage(
accountImage,
AVATAR_ICON_WIDTH,
AVATAR_ICON_HEIGHT);
accountImageLabel
.setIcon(new ImageIcon(roundedImage));
if (roundedImage != null)
{
accountImageLabel.setIcon(roundedImage);
}
String firstName
@ -214,49 +213,4 @@ protected void paintComponent(Graphics g)
g.fillRoundRect(5, 5, this.getWidth() - 10, this.getHeight() - 10, 8, 8);
}
/**
* Creates a rounded avatar image.
*
* @param avatarBytes The bytes of the initial avatar image.
*
* @return The rounded corner image.
*/
private Image createRoundImage(byte[] avatarBytes)
{
BufferedImage destImage = null;
try
{
InputStream in = new ByteArrayInputStream(avatarBytes);
BufferedImage avatarImage = ImageIO.read(in);
ImageIcon scaledImage = ImageUtils.scaleIconWithinBounds(
new ImageIcon(avatarImage),
AVATAR_ICON_WIDTH,
AVATAR_ICON_HEIGHT);
destImage
= new BufferedImage(scaledImage.getIconWidth(),
scaledImage.getIconHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = destImage.createGraphics();
AntialiasingManager.activateAntialiasing(g);
g.setColor(Color.WHITE);
g.fillRoundRect(0, 0,
scaledImage.getIconWidth(),
scaledImage.getIconHeight(),
10, 10);
g.setComposite(AlphaComposite.SrcIn);
g.drawImage(scaledImage.getImage(), 0, 0, null);
}
catch (Exception e)
{
logger.error("Could not create image.", e);
}
return destImage;
}
}

@ -174,16 +174,20 @@ private JPanel createSummaryInfoPanel()
byte[] bytes = this.contact.getImage();
ImageIcon avatarImage = null;
ImageIcon scaledImage = null;
// If the user has a contact image, let's use it. If not, add the
// default
if (bytes != null)
avatarImage = new ImageIcon(bytes);
{
scaledImage = ImageUtils.getScaledRoundedImage(
bytes,
AVATAR_AREA_WIDTH,
AVATAR_AREA_HEIGHT
);
}
else
avatarImage = Resources.getImage("contactInfoDefaultPersonIcon");
ImageIcon scaledImage = ImageUtils.scaleIconWithinBounds(
avatarImage,
scaledImage = ImageUtils.getScaledRoundedImage(
Resources.getImage("contactInfoDefaultPersonIcon"),
AVATAR_AREA_WIDTH,
AVATAR_AREA_HEIGHT
);
@ -506,4 +510,4 @@ public void hyperlinkUpdate(HyperlinkEvent e)
return mainExtendedPanel;
}
}
}

@ -25,7 +25,7 @@ public class ContactInfoMenuItem
{
private JMenuItem menuItem
= new JMenuItem(Resources.getString("contactInfo"),
Resources.getImage("contactInfoIcon"));
new ImageIcon(Resources.getImage("contactInfoIcon")));
private MetaContact metaContact;

@ -7,12 +7,11 @@
package net.java.sip.communicator.plugin.contactinfo;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.swing.*;
import net.java.sip.communicator.service.resources.*;
import net.java.sip.communicator.util.*;
@ -46,7 +45,7 @@ public static String getString(String key)
* @param imageID The identifier of the image.
* @return The image for the given identifier.
*/
public static ImageIcon getImage(String imageID)
public static Image getImage(String imageID)
{
BufferedImage image = null;
@ -65,7 +64,7 @@ public static ImageIcon getImage(String imageID)
log.error("Failed to load image:" + imageID, e);
}
return new ImageIcon(image);
return image;
}
public static ResourceManagementService getResources()

@ -269,4 +269,4 @@ public static String getEmailAddress(
return address.getEMailAddress();
}
}
}

@ -7,15 +7,22 @@
package net.java.sip.communicator.util;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;
/**
* Utility methods for image manipulation.
*
* @author Sebastien Mazy
* @author Yana Stamcheva
*/
public class ImageUtils
{
private static final Logger logger = Logger.getLogger(ImageUtils.class);
/**
* Returns a scaled image fitting within the given bounds
* while keeping the aspect ratio.
@ -26,24 +33,96 @@ public class ImageUtils
* @return the scaled image
*/
public static ImageIcon
scaleIconWithinBounds(ImageIcon image, int width, int height)
scaleIconWithinBounds(Image image, int width, int height)
{
ImageIcon scaledImage;
int scaleHint = Image.SCALE_SMOOTH;
double originalRatio =
(double) image.getIconWidth() / image.getIconHeight();
(double) image.getWidth(null) / image.getHeight(null);
double areaRatio = (double) width / height;
if(originalRatio > areaRatio)
{
scaledImage = new ImageIcon(image.getImage().
scaledImage = new ImageIcon(image.
getScaledInstance(width, -1,scaleHint));
}
else
{
scaledImage = new ImageIcon(image.getImage().
scaledImage = new ImageIcon(image.
getScaledInstance(-1, height, scaleHint));
}
return scaledImage;
}
}
/**
* Creates a rounded avatar image.
*
* @param avatarBytes The bytes of the initial avatar image.
*
* @return The rounded corner image.
*/
public static ImageIcon getScaledRoundedImage( Image image,
int width,
int height)
{
BufferedImage destImage = null;
ImageIcon scaledImage = ImageUtils.scaleIconWithinBounds( image,
width,
height);
destImage
= new BufferedImage(scaledImage.getIconWidth(),
scaledImage.getIconHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = destImage.createGraphics();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(Color.WHITE);
g.fillRoundRect(0, 0,
scaledImage.getIconWidth(),
scaledImage.getIconHeight(),
10, 10);
g.setComposite(AlphaComposite.SrcIn);
g.drawImage(scaledImage.getImage(), 0, 0, null);
return new ImageIcon(destImage);
}
/**
* Creates a rounded corner scaled image.
*
* @param imageBytes The bytes of the image to be scaled.
* @param width The maximum width of the scaled image.
* @param height The maximum height of the scaled image.
*
* @return The rounded corner scaled image.
*/
public static ImageIcon getScaledRoundedImage( byte[] imageBytes,
int width,
int height)
{
if (imageBytes == null || imageBytes.length < 1)
return null;
ImageIcon imageIcon = null;
try
{
InputStream in = new ByteArrayInputStream(imageBytes);
BufferedImage image = ImageIO.read(in);
imageIcon = getScaledRoundedImage(image, width, height);
}
catch (Exception e)
{
logger.error("Could not create image.", e);
}
return imageIcon;
}
}

@ -18,6 +18,7 @@ Import-Package: org.osgi.framework,
javax.swing.text,
net.java.sip.communicator.util.xml,
net.java.sip.communicator.util,
javax.imageio
Export-Package: net.java.sip.communicator.util.xml,
net.java.sip.communicator.util,

Loading…
Cancel
Save