package org.limewire.ui.swing.statusbar;
import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.Timer;
import org.jdesktop.application.Resource;
import org.jdesktop.swingx.JXPanel;
import org.limewire.core.api.connection.ConnectionStrength;
import org.limewire.core.api.connection.GnutellaConnectionManager;
import org.limewire.ui.swing.components.HyperlinkButton;
import org.limewire.ui.swing.util.GuiUtils;
import org.limewire.ui.swing.util.I18n;
import com.google.inject.Inject;
class ConnectionStatusPanel extends JXPanel {
private final String connectingText = I18n.tr("Connecting");
private final GnutellaConnectionManager gnutellaConnectionManager;
private ConnectionStrength currentStrength;
/**
* Link to the currently running connecting "animate" timer
* that appends dots every 500ms to the connecting message
*/
private Timer animateTimer = null;
private JButton tryAgainButton = null;
private final JLabel connectionStrengthLabel;
private final JLabel connectionStatusLabel;
@Resource private Icon noInternet;
@Resource private Icon disconnected;
@Resource private Icon connecting;
@Resource private Icon weak;
@Resource private Icon weakPlus;
@Resource private Icon medium;
@Resource private Icon mediumPlus;
@Resource private Icon full;
@Resource private Icon turbo;
@Resource private Font font;
@Inject
ConnectionStatusPanel(GnutellaConnectionManager gnutellaConnectionManager) {
this.gnutellaConnectionManager = gnutellaConnectionManager;
GuiUtils.assignResources(this);
this.setLayout(new BorderLayout());
this.setOpaque(false);
this.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
connectionStrengthLabel = new JLabel();
connectionStrengthLabel.setBorder(BorderFactory.createEmptyBorder(1,0,0,4));
connectionStatusLabel = new JLabel();
connectionStatusLabel.setBorder(BorderFactory.createEmptyBorder(0,0,0,4));
connectionStatusLabel.setFont(font);
connectionStatusLabel.setForeground(this.getForeground());
this.add(this.connectionStrengthLabel,BorderLayout.WEST);
this.add(this.connectionStatusLabel,BorderLayout.CENTER);
gnutellaConnectionManager.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(evt.getPropertyName().equals("strength")) {
setConnectionStrength((ConnectionStrength)evt.getNewValue());
}
}
});
// Assume that the program is connecting on startup until
// notified otherwise -- avoids blank status or false positive on
// disconnected state
setConnectionStrength(ConnectionStrength.CONNECTING);
}
private void setConnectionStrength(ConnectionStrength strength) {
currentStrength = strength;
String statusMessage = "";
String tooltipText = "";
boolean shouldHideStatusLater = false;
boolean showTryAgain = false;
Icon strengthIcon = null;
switch(strength) {
case NO_INTERNET:
statusMessage = I18n.tr("No internet connection");
tooltipText = I18n.tr("You have no internet connection");
strengthIcon = noInternet;
break;
case DISCONNECTED:
tooltipText = I18n.tr("Couldn't connect");
statusMessage = I18n.tr("You couldn't connect to LimeWire");
strengthIcon = disconnected;
showTryAgain = true;
break;
case CONNECTING:
statusMessage = connectingText;
tooltipText = I18n.tr("Connecting...");
animateConnecting();
strengthIcon = connecting;
break;
case WEAK:
statusMessage = I18n.tr("Weak connection");
tooltipText = I18n.tr("You have a weak connection");
strengthIcon = weak;
break;
case WEAK_PLUS:
statusMessage = I18n.tr("Weak connection");
tooltipText = I18n.tr("You have a weak connection");
strengthIcon = weakPlus;
break;
case MEDIUM:
statusMessage = I18n.tr("Medium connection");
tooltipText = I18n.tr("You have a medium connection");
strengthIcon = medium;
break;
case MEDIUM_PLUS:
statusMessage = I18n.tr("Medium connection");
tooltipText = I18n.tr("You have a medium connection");
strengthIcon = mediumPlus;
break;
case FULL:
shouldHideStatusLater = true;
statusMessage = I18n.tr("Full connection");
tooltipText = I18n.tr("You are fully connected");
strengthIcon = full;
break;
case TURBO:
shouldHideStatusLater = true;
statusMessage = I18n.tr("Turbo-charged connection");
tooltipText = I18n.tr("You have a turbo-charged connection");
strengthIcon = turbo;
break;
}
if (shouldHideStatusLater) {
hideStatusLater();
}
connectionStatusLabel.setVisible(true);
connectionStatusLabel.setText(statusMessage);
connectionStrengthLabel.setIcon(strengthIcon);
if (tryAgainButton == null) {
if (showTryAgain) {
tryAgainButton = new HyperlinkButton(I18n.tr("Try Again"));
tryAgainButton.setFont(font);
tryAgainButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
gnutellaConnectionManager.restart();
}
});
this.add(this.tryAgainButton, BorderLayout.EAST);
}
}
else {
tryAgainButton.setVisible(showTryAgain);
}
setToolTipText(tooltipText);
}
@Override
public void setToolTipText(String totalText) {
super.setToolTipText(totalText);
connectionStatusLabel.setToolTipText(totalText);
connectionStrengthLabel.setToolTipText(totalText);
}
private void hideStatusLater() {
// We need to gaurd against hiding the status label when moving
// from Full or Turbo down to a lower strength by ensuring it
// it is still in the same state it was when the hide was
// scheduled.
// NOTE: Don't need to gaurd against double hides
final ConnectionStrength initialStength = currentStrength;
Timer hideSheduler = new Timer(3000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (initialStength == currentStrength) {
connectionStatusLabel.setVisible(false);
}
}
});
hideSheduler.setRepeats(false);
hideSheduler.start();
}
private void animateConnecting() {
// Gaurd against running multiple timers if the
// connection goes out of connecting and back
// quickly ( < 500ms in this case)
if (animateTimer != null) {
animateTimer.stop();
}
animateTimer = new Timer(500, new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
if (currentStrength != ConnectionStrength.CONNECTING) {
// Dispose and stop this timer
animateTimer.stop();
animateTimer = null;
return;
}
int numDots = (connectionStatusLabel.getText().trim().length()
- connectingText.length() + 1)
% 4;
StringBuffer message = new StringBuffer(connectingText);
// must be a nicer way of doing this. By always appending same # of .'s or ' '
// we ensure the positioning on the status bar doesn't move while
// in connecting mode
for ( int i=0 ; i<4 ; i++ ) {
if(i < numDots)
message.append('.');
else
message.append(' ');
}
connectionStatusLabel.setText(message.toString());
}
});
animateTimer.start();
}
}