package com.limegroup.gnutella.gui;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.plaf.metal.MetalLabelUI;
import com.limegroup.gnutella.version.UpdateInformation;
final class UpdatePanel extends JLabel implements RefreshListener {
private final String labelString =
GUIMediator.getStringResource("UPDATE_MESSAGE_SMALL");
/**
* Whether a new update is available.
*/
private volatile boolean _updateAvailable;
/**
* The most recent UpdateInformation we know about.
*/
private UpdateInformation _info;
/**
* Cached UpdateDialog. Written to only from the awt thread, read from other threads.
*/
private UpdateDialog _dialog;
UpdatePanel() {
super(GUIMediator.getStringResource("UPDATE_MESSAGE_SMALL"), SwingConstants.CENTER);
//make the font so that it looks like a link
setUI(new LinkLabelUI());
FontMetrics fm = getFontMetrics(getFont());
int width = fm.stringWidth(labelString);
Dimension dim = new Dimension(width, fm.getHeight());
//link color, could grab system attribute as well
setForeground(Color.red);
setPreferredSize(dim);
setMaximumSize(dim);
//add a mouse listener
addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
UpdatePanel.this.handleClick();
}
//change cursor, we are on a link
public void mouseEntered(MouseEvent e) {
if(_updateAvailable)
e.getComponent().setCursor
(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
//change back to normal
public void mouseExited(MouseEvent e) {
if(_updateAvailable)
e.getComponent().setCursor(Cursor.getDefaultCursor());
}
});
//add the link
GUIMediator.addRefreshListener(this);
//keep it invisible
setVisible(false);
_updateAvailable = false;
}
public void makeVisible(boolean popup, UpdateInformation info) {
// update the dialog and dispose the old one
Runnable disposer = null;
synchronized(this) {
_updateAvailable = true;
_info = info;
final UpdateDialog currentDialog = _dialog;
if (_info != null )
_dialog = new UpdateDialog(_info);
if (currentDialog != null) {
disposer = new Runnable() {
public void run() {
currentDialog.setVisible(false);
currentDialog.dispose();
}
};
}
}
if (disposer != null)
GUIMediator.safeInvokeLater(disposer);
super.setVisible(true);
// if we blink, notify the user immediately
if (popup) {
GUIMediator.safeInvokeLater(new Runnable() {
public void run() {
handleClick();
}
});
}
}
/**
* Returns true if this update panel should be shown; namely, if
* an update is available.
*/
public boolean shouldBeShown() {
return _updateAvailable;
}
private void handleClick() {
if(!_updateAvailable) //not visible? no update yet
return;
synchronized(this) {
if(_info != null)
_dialog.setVisible(true);
}
}
public void refresh() {
if (!_updateAvailable)
return;
Color currCol = getForeground();
if (currCol.equals(Color.red))
setForeground(Color.black);
if (currCol.equals(Color.black))
setForeground(Color.red);
}
private class LinkLabelUI extends MetalLabelUI {
/**
* Paint clippedText at textX, textY with the labels foreground color.
*
* @see #paint
* @see #paintDisabledText
*/
protected void paintEnabledText(JLabel l, Graphics g, String s,
int textX, int textY) {
super.paintEnabledText(l, g, s, textX, textY);
if (getText() == null)
return;
FontMetrics fm = g.getFontMetrics();
g.fillRect(textX, fm.getAscent()+2,
fm.stringWidth(getText()) -
getInsets().right, 1); //X,Y,WIDTH,HEIGHT
}
}
}