package thaw.plugins.peerMonitor;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JList;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.JButton;
import javax.swing.ListCellRenderer;
import javax.swing.BorderFactory;
import javax.swing.JPopupMenu;
import javax.swing.JMenuItem;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.Color;
import java.util.Vector;
import java.util.Iterator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Observable;
import thaw.plugins.PeerMonitor;
import thaw.plugins.ToolbarModifier;
import thaw.core.Config;
import thaw.core.I18n;
import thaw.fcp.FCPQueueManager;
import thaw.gui.IconBox;
import thaw.gui.GUIHelper;
/**
* In fact, here is two panels : A panel with the peer list
* and a panel with various details (ref, etc)
*/
public class PeerMonitorPanel extends Observable implements ActionListener, MouseListener
{
public final static String[] STR_STATUS = {
"CONNECTED",
"BACKED OFF",
"TOO OLD",
"TOO NEW",
"DISCONNECTED",
"NEVER CONNECTED"
};
public final static Color[] COLOR_STATUS = {
new Color(0, 164, 0), /* CONNECTED */
Color.ORANGE, /* BACKED OFF */
Color.RED, /* TOO OLD */
Color.BLUE, /* TOO NEW */
Color.GRAY, /* DISCONNECTED */
Color.PINK /* NEVER CONNECTED */
};
public final static Color JLIST_NODE_STAT_BACKGROUND = Color.WHITE;
public final static Color JLIST_PEER_BACKGROUND = new Color(240,240,240);
public final static int STR_INFO_MAX_LNG = 55;
public final static int STR_NODENAME_MAX_LNG = 15;
private JPanel peerPanel;
private JPanel tabPanel;
private JPanel mainPanel;
private JList peerList;
private JProgressBar thawMemBar;
private JProgressBar nodeMemBar;
private JLabel nodeThreads;
private JLabel thawThreads;
private JLabel detailsLabel;
private JPanel detailsPanel;
private JPopupMenu rightClickMenu;
private Vector buttonActions;
private JButton closeTabButton;
private PeerMonitor peerMonitor;
private ToolbarModifier toolbarModifier;
private JButton foldButton;
private final static String nodeMemoryStr = I18n.getMessage("thaw.plugin.peerMonitor.infos.nodeMemory");
private final static String thawMemoryStr = I18n.getMessage("thaw.plugin.peerMonitor.infos.thawMemory");
private final static String nodeThreadsStr = I18n.getMessage("thaw.plugin.peerMonitor.infos.nodeThreads");
private final static String thawThreadsStr = I18n.getMessage("thaw.plugin.peerMonitor.infos.thawThreads");
private final static String nodeStatsStr = I18n.getMessage("thaw.plugin.peerMonitor.nodeStats");
public PeerMonitorPanel(PeerMonitor peerMonitor,
FCPQueueManager queueManager,
Config config,
thaw.core.MainWindow mainWindow) {
buttonActions = new Vector();
this.peerMonitor = peerMonitor;
toolbarModifier = new ToolbarModifier(mainWindow);
tabPanel = new JPanel(new BorderLayout(10, 10));
peerPanel = new JPanel(new BorderLayout());
peerList = new JList();
peerList.setCellRenderer(new PeerCellRenderer());
//peerList.addListSelectionListener(this);
Vector v = new Vector();
v.add(I18n.getMessage("thaw.plugin.peerMonitor.nodeStats"));
peerList.setListData(v);
JLabel peerListLabel = new JLabel(I18n.getMessage("thaw.plugin.peerMonitor.peerList"));
peerListLabel.setIcon(IconBox.peers);
/* We are not the listener */
/* te listener will be thaw.plugins.PeerMonitor */
foldButton = new JButton(">");
nodeMemBar = new JProgressBar(0, 100);
thawMemBar = new JProgressBar(0, 100);
nodeMemBar.setStringPainted(true);
thawMemBar.setStringPainted(true);
setMemBar(0, 134217728);
nodeThreads = new JLabel("");
thawThreads = new JLabel("");
JPanel southSouth = new JPanel(new BorderLayout(5, 5));
JPanel threadPanel = new JPanel(new GridLayout(2, 1));
threadPanel.add(nodeThreads);
threadPanel.add(thawThreads);
southSouth.add(threadPanel, BorderLayout.CENTER);
JPanel littleButtonPanel = new JPanel(new GridLayout(1, 2));
JButton littleButton;
littleButton = new JButton(IconBox.minAdd);
littleButton.setToolTipText(I18n.getMessage("thaw.plugin.peerMonitor.addPeer"));
buttonActions.add(new PeerHelper.PeerAdder(queueManager, mainWindow, littleButton));
littleButtonPanel.add(littleButton);
littleButton = new JButton(IconBox.minDelete);
littleButton.setToolTipText(I18n.getMessage("thaw.plugin.peerMonitor.removePeer"));
buttonActions.add(new PeerHelper.PeerRemover(queueManager, littleButton));
littleButtonPanel.add(littleButton);
southSouth.add(littleButtonPanel, BorderLayout.WEST);
JPanel titlePanel = new JPanel(new BorderLayout(5, 5));
titlePanel.add(peerListLabel, BorderLayout.CENTER);
titlePanel.add(foldButton, BorderLayout.EAST);
peerPanel.add(titlePanel, BorderLayout.NORTH);
peerPanel.add(new JScrollPane(peerList), BorderLayout.CENTER);
JPanel memPanel = new JPanel(new GridLayout(3, 1));
memPanel.add(southSouth);
memPanel.add(nodeMemBar);
memPanel.add(thawMemBar);
peerPanel.add(memPanel, BorderLayout.SOUTH);
peerPanel.setPreferredSize(new java.awt.Dimension(250, 200));
mainPanel = new JPanel(new GridLayout(1, 1, 10, 10)); /* obsolete */
detailsLabel = new JLabel();
detailsPanel = new JPanel();
JPanel globalDetailsPanel = new JPanel(new BorderLayout(5, 5));
globalDetailsPanel.add(detailsLabel, BorderLayout.NORTH);
globalDetailsPanel.add(new JScrollPane(detailsPanel), BorderLayout.CENTER);
mainPanel.add(globalDetailsPanel);
tabPanel.add(mainPanel, BorderLayout.CENTER);
closeTabButton = new JButton(IconBox.minClose);
closeTabButton.setBorderPainted(false);
closeTabButton.addActionListener(this);
JPanel headPanel = new JPanel(new BorderLayout());
headPanel.add(new JLabel(""), BorderLayout.CENTER);
headPanel.add(closeTabButton, BorderLayout.EAST);
tabPanel.add(headPanel, BorderLayout.NORTH);
rightClickMenu = new JPopupMenu();
JMenuItem item;
item = new JMenuItem(I18n.getMessage("thaw.plugin.peerMonitor.addPeer"),
IconBox.minAdd);
buttonActions.add(new PeerHelper.PeerAdder(queueManager, mainWindow, item));
rightClickMenu.add(item);
item = new JMenuItem(I18n.getMessage("thaw.plugin.peerMonitor.removePeer"),
IconBox.minDelete);
buttonActions.add(new PeerHelper.PeerRemover(queueManager, item));
rightClickMenu.add(item);
peerList.addMouseListener(this);
JButton toolbarButton;
toolbarButton = new JButton(IconBox.add);
toolbarButton.setToolTipText(I18n.getMessage("thaw.plugin.peerMonitor.addPeer"));
buttonActions.add(new PeerHelper.PeerAdder(queueManager, mainWindow, toolbarButton));
toolbarModifier.addButtonToTheToolbar(toolbarButton);
toolbarButton = new JButton(IconBox.delete);
toolbarButton.setToolTipText(I18n.getMessage("thaw.plugin.peerMonitor.removePeer"));
buttonActions.add(new PeerHelper.PeerRemover(queueManager, toolbarButton));
toolbarModifier.addButtonToTheToolbar(toolbarButton);
}
public JButton getFoldButton() {
return foldButton;
}
public void setMemBar(long used, long max) {
int pourcent;
/* node mem bar */
pourcent = (int)((used * 100) / max);
nodeMemBar.setString(nodeMemoryStr+ ": "
+ GUIHelper.getPrintableSize(used)
+ " / "
+ GUIHelper.getPrintableSize(max));
nodeMemBar.setValue(pourcent);
/* thaw mem bar */
max = Runtime.getRuntime().maxMemory();
if (max == Long.MAX_VALUE) {
max = Runtime.getRuntime().totalMemory();
}
used = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
pourcent = (int)((used * 100) / max);
thawMemBar.setString(thawMemoryStr+ ": "
+ GUIHelper.getPrintableSize(used)
+ " / "
+ GUIHelper.getPrintableSize(max));
thawMemBar.setValue(pourcent);
}
public void setNmbThreads(int nmbNodeThreads) {
nodeThreads.setText(nodeThreadsStr
+ " : "+ Integer.toString(nmbNodeThreads));
thawThreads.setText(thawThreadsStr
+ " : "+ Integer.toString(Thread.activeCount()));
}
protected class PeerCellRenderer extends JLabel implements ListCellRenderer {
/**
*
*/
private static final long serialVersionUID = 2631236843498183587L;
public PeerCellRenderer() {
setOpaque(true);
}
public java.awt.Component
getListCellRendererComponent(JList list,
Object value, // value to display
int index, // cell index
boolean iss, // is selected
boolean chf) // cell has focus?
{
if (value instanceof String) {
setText((String)value);
setForeground(Color.BLACK);
setBackground(JLIST_NODE_STAT_BACKGROUND);
}
if (value instanceof Peer) {
String txt = ((Peer)value).toString();
/*
if (txt.length() > 25) {
txt = txt.substring(0, 25) + "(...)";
}
*/
setText(txt);
setForeground(((Peer)value).getTextColor());
setBackground(JLIST_PEER_BACKGROUND);
}
// Set a border if the
//list item is selected
if (iss)
setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
else
setBorder(BorderFactory.createLineBorder(list.getBackground(), 1));
return this;
}
}
private Vector peers;
private Hashtable nodeInfos = null;
/**
* \param peers : Hashtable containing Hashtable containing the parameter list
*/
public synchronized void setPeerList(Hashtable pL)
{
peers = new Vector();
peers.add(nodeStatsStr);
/* TODO : dirty : should use comparator, etc */
for (int i = 0 ; i < STR_STATUS.length ; i++) {
for (Enumeration e = pL.elements();
e.hasMoreElements();) {
Hashtable ht = (Hashtable)e.nextElement();
if (STR_STATUS[i].equals(ht.get("volatile.status"))) {
peers.add(new Peer(ht));
}
}
}
/* can it happen ?! */
if (peerList != null && peers != null)
peerList.setListData(peers);
}
public synchronized void setNodeInfos(Hashtable infos) {
if (nodeInfos == null) { /* first time */
displayInfos(I18n.getMessage("thaw.plugin.peerMonitor.nodeInfos"), infos);
}
nodeInfos = infos;
}
public JPanel getTabPanel() {
return tabPanel;
}
public JPanel getPeerListPanel() {
return peerPanel;
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == closeTabButton) {
peerMonitor.hideTab();
}
}
/**
* @return null if it must not be displayed ; else an array with two elements (key translated + value translated)
*/
public String[] getTranslation(String key, String value) {
String [] result = null;
/* PEERS */
if ("volatile.lastRoutingBackoffReason".equals(key))
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.lastRoutingBackoffReason"),
value
};
else if ("volatile.routingBackoffPercent".equals(key))
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.routingBackoffPercent"),
value + "%"
};
else if ("version".equals(key)) /* used also for the node */
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.version"),
value
};
else if ("volatile.status".equals(key))
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.status"),
value
};
else if ("myName".equals(key))
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.myName"),
value
};
else if ("physical.udp".equals(key)) /* used also for the node */
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.physical.udp"),
value
};
else if ("volatile.averagePingTime".equals(key)) /* used also for the node */
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.averagePingTime"),
Integer.toString(new Float(value).intValue()) + " ms"
};
else if ("volatile.idle".equals(key))
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.idle"),
"~" + GUIHelper.getPrintableTime(Long.parseLong(value) / 1000)
};
else if ("volatile.totalBytesOut".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.totalBytesOut"),
"~" + GUIHelper.getPrintableSize(Long.parseLong(value))
};
}
else if ("volatile.totalBytesIn".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.totalBytesIn"),
"~" + GUIHelper.getPrintableSize(Long.parseLong(value))
};
}
else if ("volatile.overloadProbability".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.peer.overloadProbability"),
value
};
}
/* NODE */
else if ("volatile.overallSize".equals(key))
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.node.overallSize"),
"~" + GUIHelper.getPrintableSize(Long.parseLong(value))
};
else if ("volatile.uptimeSeconds".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.node.uptimeSeconds"),
"~" + GUIHelper.getPrintableTime(Long.parseLong(value))
};
}
else if ("volatile.networkSizeEstimateSession".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.node.networkSizeEstimateSession"),
value
};
}
else if ("volatile.runningThreadCount".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.node.runningThreads"),
value
};
}
else if ("myName".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.node.myName"),
value
};
}
else if ("volatile.totalInputBytes".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.totalInputBytes"),
GUIHelper.getPrintableSize(Long.parseLong(value))
};
}
else if ("volatile.backedOffPercent".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.backedOffPercent"),
value + "%"
};
}
else if ("volatile.totalOutputBytes".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.totalOutputBytes"),
GUIHelper.getPrintableSize(Long.parseLong(value))
};
}
else if ("volatile.swapsPerMinute".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.swapPerMinute"),
value
};
}
else if ("volatile.locationChangePerMinute".equals(key)) {
result = new String[] {
I18n.getMessage("thaw.plugin.peerMonitor.infos.locationChangePerMinute"),
value
};
}
/*
if (advanced) {
if (result == null)
result = new String[] { key, value };
else
result[0] = result[0] + " ("+key+")";
}
*/
return result;
}
private static JLabel makeInfoLabel(String txt) {
if (txt.length() > STR_INFO_MAX_LNG)
txt = txt.substring(0, STR_INFO_MAX_LNG) + "(...)";
JLabel lb = new JLabel(txt);
return lb;
}
public void displayInfos(String title, Hashtable ht) {
if (ht == null)
return;
Vector v = new Vector();
for (Enumeration e = ht.keys();
e.hasMoreElements(); ) {
String key = (String)e.nextElement();
String[] val = getTranslation(key, (String)ht.get(key));
if (val != null)
v.add(val);
}
detailsPanel.removeAll();
detailsPanel.setLayout(new GridLayout(v.size()+1, 2));
detailsLabel.setText(title);
detailsLabel.setIcon(IconBox.computer);
for (Iterator i = v.iterator();
i.hasNext();) {
String[] val = (String[])i.next();
detailsPanel.add(makeInfoLabel(val[0] + ":"));
detailsPanel.add(makeInfoLabel(val[1]));
}
mainPanel.validate();
detailsPanel.validate();
}
private void clicked() {
if (peerList.getSelectedValue() instanceof Peer) {
updateButtonState(((Peer)peerList.getSelectedValue()));
} else
updateButtonState(null);
if (peerList.getSelectedValue() == null
|| !(peerList.getSelectedValue() instanceof Peer)) {
displayInfos(I18n.getMessage("thaw.plugin.peerMonitor.nodeInfos"), nodeInfos);
} else {
Peer peer;
if ((peer = ((Peer)peerList.getSelectedValue())) != null) {
String peerName = peer.toString();
displayInfos(I18n.getMessage("thaw.plugin.peerMonitor.peerInfos") + " '" + peerName + "':",
peer.getParameters());
}
}
setChanged();
notifyObservers();
}
public void updateButtonState(Peer target) {
for (Iterator it = buttonActions.iterator();
it.hasNext();) {
PeerHelper.PeerAction a = ((PeerHelper.PeerAction)it.next());
a.setTarget(target);
}
}
public void mouseClicked(final MouseEvent e) {
clicked();
}
public void mouseEntered(final MouseEvent e) { }
public void mouseExited(final MouseEvent e) { }
public void mousePressed(final MouseEvent e) {
showPopupMenu(e);
}
public void mouseReleased(final MouseEvent e) {
showPopupMenu(e);
}
protected void showPopupMenu(final MouseEvent e) {
if(e.isPopupTrigger()) {
rightClickMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
public void showToolbarButtons() {
toolbarModifier.displayButtonsInTheToolbar();
}
public void hideToolbarButtons() {
toolbarModifier.hideButtonsInTheToolbar();
}
}