/*
* Copyright 2010-2015 Institut Pasteur.
*
* This file is part of Icy.
*
* Icy is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Icy is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Icy. If not, see <http://www.gnu.org/licenses/>.
*/
package icy.gui.system;
import icy.image.ImageUtil;
import icy.math.UnitUtil;
import icy.network.NetworkUtil;
import icy.resource.ResourceUtil;
import icy.system.SystemUtil;
import icy.system.thread.ThreadUtil;
import icy.util.ColorUtil;
import icy.util.GraphicsUtil;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
import vtk.vtkObjectBase;
/**
* Memory monitor.
*
* @author Fab & Stephane
*/
public class MemoryMonitorPanel extends JPanel implements MouseListener
{
private static final long serialVersionUID = 5629509450385435829L;
private static int NBVAL = 94;
/**
* 0 est la valeur la plus ancienne.
*/
private final double[][] valeur;
private final String[] infos;
private final Timer updateTimer;
private final Color cpuColor = ColorUtil.mix(Color.blue, Color.white);
private final Color cpuTextColor = ColorUtil.mix(cpuColor, Color.white);
private final Color memColor = Color.green;
private final Color memTextColor = ColorUtil.mix(memColor, Color.white);
private final Color connectionColor = ColorUtil.mix(Color.red, Color.white);
private final BasicStroke cpuStroke = new BasicStroke(2);
private final BasicStroke memStroke = new BasicStroke(3);
private final Font textFont = new Font("Arial", Font.BOLD, 9);
private BufferedImage background = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
private final Image networkImage = ImageUtil.getColorImageFromAlphaImage(ResourceUtil.ICON_NETWORK, Color.gray);
private final Image deleteImage = ImageUtil.getColorImageFromAlphaImage(ResourceUtil.ICON_DELETE, Color.red);
boolean displayHelpMessage = false;
public MemoryMonitorPanel()
{
super();
updateTimer = new Timer("Memory / CPU monitor");
// init tables
valeur = new double[NBVAL][2];
for (int i = 0; i < NBVAL; i++)
{
valeur[i][0] = 0;
valeur[i][1] = 0;
}
infos = new String[2];
for (int i = 0; i < 2; i++)
infos[i] = "";
setMinimumSize(new Dimension(120, 50));
setPreferredSize(new Dimension(140, 55));
addMouseListener(this);
updateTimer.scheduleAtFixedRate(new TimerTask()
{
@Override
public void run()
{
updateMemoryMessageBar();
}
}, 100, 100);
}
@Override
protected void paintComponent(Graphics g)
{
final int w = getWidth();
final int h = getHeight();
if ((background.getWidth() != w) || (background.getHeight() != h))
{
background = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
Graphics2D background_g2 = background.createGraphics();
GraphicsUtil.paintIcyBackGround(w, h, background_g2);
}
g.drawImage(background, 0, 0, null);
final Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// display graph
if (valeur != null)
{
float x;
double max;
double ymul;
final float step = w / 100f;
// draw used memory
g2.setStroke(memStroke);
g2.setColor(memColor);
max = SystemUtil.getJavaMaxMemory();
ymul = (h - 8) / max;
x = 6;
for (int i = 0; i < NBVAL - 1; i++)
{
final double v1 = Math.min(valeur[i][0], max);
final double v2 = Math.min(valeur[i + 1][0], max);
final int y1 = h - (int) (v1 * ymul);
final int y2 = h - (int) (v2 * ymul);
g2.drawLine((int) x, y1 - 4, (int) (x + step), y2 - 4);
x += step;
}
// draw CPU load
g2.setStroke(cpuStroke);
g2.setColor(cpuColor);
max = 100d;
ymul = (h - 8) / max;
x = 6;
for (int i = 0; i < NBVAL - 1; i++)
{
final double v1 = Math.min(valeur[i][1], max);
final double v2 = Math.min(valeur[i + 1][1], max);
final int y1 = h - (int) (v1 * ymul);
final int y2 = h - (int) (v2 * ymul);
g2.drawLine((int) x, y1 - 4, (int) (x + step), y2 - 4);
x += step;
}
}
// display text
g2.setFont(textFont);
// display Used & Max Memory
g2.setColor(Color.black);
GraphicsUtil.drawHCenteredString(g2, infos[0], (w / 2) + 1, 6 + 1, false);
g2.setColor(memTextColor);
GraphicsUtil.drawHCenteredString(g2, infos[0], w / 2, 6, false);
// display CPU Load
g2.setColor(Color.black);
GraphicsUtil.drawHCenteredString(g2, infos[1], (w / 2) + 1, 18 + 1, false);
g2.setColor(cpuTextColor);
GraphicsUtil.drawHCenteredString(g2, infos[1], w / 2, 18, false);
String text;
// display internet connection
if (!NetworkUtil.hasInternetAccess())
{
g2.drawImage(networkImage, 10, 30, 16, 16, null);
g2.drawImage(deleteImage, 13, 35, 10, 10, null);
if (displayHelpMessage)
{
text = "Not connected to internet";
g2.setColor(Color.black);
GraphicsUtil.drawHCenteredString(g2, text, (w / 2) + 1, 30 + 1, false);
g2.setColor(connectionColor);
GraphicsUtil.drawHCenteredString(g2, text, w / 2, 30, false);
}
}
if (displayHelpMessage)
{
text = "click to force a garbage collector event";
g2.setColor(Color.black);
GraphicsUtil.drawHCenteredString(g2, text, (w / 2) + 1, 44 + 1, false);
g2.setColor(Color.white);
GraphicsUtil.drawHCenteredString(g2, text, w / 2, 44, false);
}
g2.dispose();
}
void updateMemoryMessageBar()
{
final double usedMemory = SystemUtil.getJavaUsedMemory();
final int cpuLoad = SystemUtil.getCpuLoad();
// save used memory
newValue(0, usedMemory);
// save CPU load
newValue(1, cpuLoad);
setInfo(0,
"Memory: " + UnitUtil.getBytesString(usedMemory) + " (Max: "
+ UnitUtil.getBytesString(SystemUtil.getJavaMaxMemory()) + ")");
setInfo(1, "CPU: " + cpuLoad + "%");
repaint();
}
/**
* Scroll les valeurs et en ajoute ( un seeker serait plus joli...)
*/
public void newValue(int curve, double val)
{
for (int i = 0; i < NBVAL - 1; i++)
valeur[i][curve] = valeur[i + 1][curve];
valeur[NBVAL - 1][curve] = val;
}
public void setInfo(int infonb, String info)
{
infos[infonb] = info;
}
@Override
public void mouseClicked(MouseEvent event)
{
final MouseEvent e = event;
ThreadUtil.bgRun(new Runnable()
{
@Override
public void run()
{
final double freeBefore = SystemUtil.getJavaFreeMemory();
// force garbage collector
System.gc();
final double freeAfter = SystemUtil.getJavaFreeMemory();
final double released = freeAfter - freeBefore;
final double usedMemory = SystemUtil.getJavaUsedMemory();
System.out.println("Max / Used memory: " + UnitUtil.getBytesString(SystemUtil.getJavaMaxMemory())
+ " / " + UnitUtil.getBytesString((usedMemory > 0) ? usedMemory : 0) + " (released by GC: "
+ UnitUtil.getBytesString((released > 0) ? released : 0) + ")");
}
});
// double click --> force VTK garbage collection (need to be done in EDT or it crashes on OSX)
if (e.getClickCount() > 1)
{
vtkObjectBase.JAVA_OBJECT_MANAGER.gc(true);
System.out.println("VTK GC forced");
}
}
@Override
public void mouseEntered(MouseEvent arg0)
{
displayHelpMessage = true;
}
@Override
public void mouseExited(MouseEvent arg0)
{
displayHelpMessage = false;
}
@Override
public void mousePressed(MouseEvent arg0)
{
}
@Override
public void mouseReleased(MouseEvent arg0)
{
}
}