package org.reldb.dbrowser.ui.monitors;
import java.util.Deque;
import java.util.LinkedList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
public class PercentDisplay extends org.eclipse.swt.widgets.Canvas {
private Deque<Integer> percentageHistory;
private int middleLimit = 50;
private int lowerLimit = 20;
private Color goodColor;
private Color okColor;
private Color badColor;
private Color black;
private Color lightGray;
private int delay = 500;
private boolean running = true;
private int displayWidth;
private String emitText = "";
private final Runnable refresh = new Runnable() {
public void run() {
if (!isDisposed())
redraw();
}
};
private void refresh() {
if (isDisposed())
return;
getDisplay().asyncExec(refresh);
}
public void setMiddleLimit(int middleLimit) {
if (this.middleLimit < 0 || this.middleLimit > 100)
throw new IllegalArgumentException("MiddleLimit must be between 0 and 100, inclusive.");
this.middleLimit = middleLimit;
refresh();
}
public int getMiddleLimit() {
return middleLimit;
}
public void setLowerLimit(int lowerLimit) {
if (this.lowerLimit < 0 || this.lowerLimit > 100)
throw new IllegalArgumentException("LowerLimit must be between 0 and 100, inclusive.");
this.lowerLimit = lowerLimit;
refresh();
}
public int getLowerLimit() {
return lowerLimit;
}
public void setDelay(int milliseconds) {
delay = milliseconds;
}
public int getDelay() {
return delay;
}
public void dispose() {
running = false;
goodColor.dispose();
badColor.dispose();
okColor.dispose();
black.dispose();
lightGray.dispose();
super.dispose();
}
// Force color value between 0 and 255.
private static int cr(int x) {
return Math.max(Math.min(x, 255), 0);
}
// Make a Color redder
private static Color redder(Color c) {
return new Color(c.getDevice(), cr(c.getRed() + 30), cr(c.getGreen() - 30), cr(c.getBlue() - 30));
}
// Make a color yellower
private static Color yellower(Color c) {
return new Color(c.getDevice(), cr(c.getRed() + 30), cr(c.getGreen() + 30), cr(c.getBlue() - 30));
}
// Make a Color greener
private static Color greener(Color c) {
return new Color(c.getDevice(), cr(c.getRed() - 30), cr(c.getGreen() + 30), cr(c.getBlue() - 30));
}
private synchronized Integer[] getPercentages() {
return percentageHistory.toArray(new Integer[0]);
}
private synchronized void addPercentage(int percentValue) {
percentageHistory.add(percentValue);
while (percentageHistory.size() > displayWidth)
percentageHistory.removeFirst();
}
public Point preferredSize() {
GC gc = new GC(this);
String sampleText = "100% CPU";
Point textExtent = gc.textExtent(sampleText);
return new Point(Math.max(75, textExtent.x + 10), textExtent.y + 10);
}
public Point computeSize(int h, int w) {
return preferredSize();
}
public Point computeSize(int h, int w, boolean changed) {
return preferredSize();
}
public PercentDisplay(Composite parent, int style, String displaytext, PercentSource percent) {
super(parent, style);
percentageHistory = new LinkedList<Integer>();
goodColor = greener(getBackground());
badColor = redder(getBackground());
okColor = yellower(getBackground());
black = new Color(parent.getDisplay(), 0, 0, 0);
lightGray = new Color(parent.getDisplay(), 200, 200, 200);
addListener (SWT.Paint, new Listener () {
@Override
public void handleEvent (Event e) {
GC gc = e.gc;
Rectangle rect = getClientArea();
displayWidth = rect.width;
Integer[] percentages = getPercentages();
int lastX = rect.x;
int lastY = rect.y;
Point txtExtent = gc.textExtent(emitText);
int textX = rect.width - txtExtent.x - 5;
int textY = (rect.height - txtExtent.y) / 2;
Rectangle txtRect = new Rectangle(textX, textY, txtExtent.x, txtExtent.y);
for (int index=0; index<percentages.length; index++) {
int barY = (100 - percentages[index]) * rect.height / 100 + 2;
int barX = rect.x + index;
gc.setForeground(getBackground());
gc.drawLine(barX, rect.y, barX, barY);
if (percentages[index] < lowerLimit)
gc.setForeground(badColor);
else if (percentages[index] < middleLimit)
gc.setForeground(okColor);
else
gc.setForeground(goodColor);
gc.drawLine(barX, rect.height, barX, barY);
if (index > 0) {
if (txtRect.contains(barX, barY) || txtRect.contains(lastX, lastY))
gc.setForeground(lightGray);
else
gc.setForeground(black);
gc.drawLine(lastX, lastY, barX, barY);
}
lastX = barX;
lastY = barY;
}
gc.setForeground(black);
gc.drawText(emitText, textX, textY, true);
}
});
Thread painter = new Thread() {
public void run() {
while (running) {
try {sleep(delay);} catch (InterruptedException ie) {}
int percentValue = percent.getPercent();
addPercentage(percentValue);
emitText = String.format("%3d%% ", percentValue) + displaytext;
refresh();
}
}
};
painter.start();
}
}