📄 queuedrawer.java
字号:
/**
* Copyright (C) 2006, Laboratorio di Valutazione delle Prestazioni - Politecnico di Milano
* This program 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 2 of the License, or
* (at your option) any later version.
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
* Created on 16-mar-2004 by Ernesto
*
*/
package jmt.jmarkov.Graphics;
import jmt.jmarkov.Graphics.constants.DrawConstrains;
import jmt.jmarkov.Graphics.constants.DrawNormal;
import jmt.jmarkov.Queues.Exceptions.NonErgodicException;
import jmt.jmarkov.Queues.MM1Data;
import jmt.jmarkov.Queues.QueueLogic;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.*;
import java.util.Vector;
/**
* MMQueues
* --------------------------------------
* 16-mar-2004 - Graphics/QueueDrawNotifier.java
*
* @author Ernesto
*/
public class QueueDrawer extends JComponent implements Notifier, Runnable {
//NEW
//@author Stefano Omini
// introduced DEBUG var to skip System.out.println() calls in final release
private static final boolean DEBUG = false;
//end NEW
private QueueLogic ql;
private Vector jobsv;
private MM1Data mm1;
private double Ui;
//timings
private long remainingTime,
totTime,
runTime,
FPMS = 100;
//queue data
private int jobs = 0,
donejobs = 0,
totjobs = 0,
queueMax = 0,
queueLen = 0,
queueMedia = 0,
lostJobs = 0,
view = 0,
VIEWS = 2;
//panel settings
private double panelH = 250,
panelW = 400,
minH = 100,
minW = 400;
//draw settings
private DrawConstrains dCst;
private static double
START_GAP,
END_GAP,
ELEM_HEIGHT,
ELEM_WIDTH,
ELEMS_GAP,
PROC_RAD,
STAT_RAD,
MORE_JOBS_MAX = 100,
LOST_JOBS_MAX = 100;
private Rectangle2D[] queue;
private RoundRectangle2D viewB;
private Ellipse2D processor, occupiedEll;
private Rectangle2D occupiedRect, moreStatiRect, lostJobsR, txtBounds, tb;
private Area occupiedArea, jobsRemaining;
private String moreJobsStr, lostJobsStr;
private Stroke stroke;
private Font f;
private String[] legendaS;
private Color[] legendaC;
// color settings
private Color emptyC = Color.WHITE,
queueC = Color.BLUE,
busyC = queueC.brighter().brighter(),
animC = Color.RED;
private boolean procUseGradient = true,
queueUseGradient = true,
gradientF,
viewButtonClicked = false;
/**
* Costruisce il grafico della coda in un pannello di
* altezza = 250, larghezza = 400
*
*/
public QueueDrawer(QueueLogic ql) {
super();
this.ql = ql;
panelW = this.getWidth();
panelH = this.getHeight();
init();
}
public QueueDrawer(Dimension panelSize, QueueLogic ql){
super();
this.ql = ql;
panelW = panelSize.width;
panelH = panelSize.height;
init();
}
void init(){
changeDrawSettings(new DrawNormal());
setColors(Color.white,Color.BLUE,Color.RED, true);
legendaS = new String[3];
legendaC = new Color[3];
legendaS[0] = "current queue";
legendaC[0] = queueC;
legendaS[1] = "lost jobs";
legendaC[1] = Color.BLACK;
legendaS[2] = "avg.utilization";
legendaC[2] = busyC;
this.reset();
jobsv = new Vector();
viewB = new RoundRectangle2D.Double();
this.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
if (viewB.contains(e.getX(), e.getY())){
viewButtonClicked = true;
repaint();
}
}
public void mouseReleased(MouseEvent e) {
if (viewB.contains(e.getX(), e.getY())){
viewButtonClicked = false;
changeView();
repaint();
}
}
});
}
public void changeDrawSettings(DrawConstrains dCst){
this.dCst = dCst;
resize();
//assegno le costanti di disegno
f = dCst.getFont();
stroke = dCst.getDrawStroke();
START_GAP = dCst.getStartingGap();
END_GAP = dCst.getStartingGap();
ELEM_HEIGHT = dCst.getElementHeight();
ELEM_WIDTH = dCst.getElementWidth();
ELEMS_GAP = dCst.getElementsGap();
PROC_RAD = dCst.getProcessorRadius();
//inizializzo la coda
queueLen = queueLenght();
queue = new Rectangle2D.Double[queueLenght()];
processor = new Ellipse2D.Double();
//repaint();
}
/* (non-Javadoc)
* @see Graphics.Notifier#runningIn(double)
*/
public void runningIn(double t) {
runTime = (long)t + System.currentTimeMillis();
remainingTime = totTime = (long)t;
mm1 = (MM1Data) jobsv.elementAt(0);
jobsv.remove(0);
mm1.si = t;
Ui = mm1.getUi();
this.repaint();
}
/**
* Imposta il numero medio di stati occupati
* @param s numero medio di stati occupati
*/
public void setMediaJobs(int s){
queueMedia = s;
this.repaint();
}
public void setMaxJobs(int j){
queueMax = j;
if (queueMax > 0) MORE_JOBS_MAX = j;
else {
reset();
MORE_JOBS_MAX = 100;
}
if (DEBUG) {
System.out.println("max jobs=" + queueMax);
}
this.repaint();
}
/* (non-Javadoc)
* @see Graphics.Notifier#addingToQ()
*/
public void addingToQ(double t) {
//System.out.println("jobs:" + jobs);
jobs++;
if((jobs > queueMax) && (queueMax > 0)) lostJobs++;
this.repaint();
mm1 = new MM1Data();
mm1.lambdai = t;
jobsv.add(mm1);
}
/* (non-Javadoc)
* @see Graphics.Notifier#removingFromQ()
*/
public void removingFromQ() {
//System.out.println("jobs:" + jobs);
donejobs++;
jobs--;
}
/* (non-Javadoc)
* @see Graphics.Notifier#reset()
*/
public void reset() {
jobs = 0;
donejobs = 0;
totjobs =0;
runTime = 0;
totTime = 0;
remainingTime = 0;
donejobs = 0;
lostJobs = 0;
Ui = 0.0;
}
public void paint(Graphics g){
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setStroke(stroke);
panelW = this.getWidth();
panelH = this.getHeight();
changeDrawSettings(dCst);
viewB = drawViewButton(10.0,10.0,g2d,false,false);
viewB = drawViewButton(
panelW - viewB.getWidth() - END_GAP,
panelH - viewB.getHeight() - 1,
g2d,true,
viewButtonClicked);
START_GAP = START_GAP * 2 +
drawLegend(
legendaC,
legendaS,
dCst.getFont(),
START_GAP,
START_GAP,
g2d ,false);
for (int i = 0; i < queueLenght(); i++){
if (i < jobs){
drawQueueStatus(queueLenght() - i - 1, queueC, Color.black, gradientF, g2d);
}
else{
drawQueueStatus(queueLenght() - i - 1, emptyC, Color.black, gradientF, g2d);
}
}
drawProcessorView(view, g2d);
if ((jobs > queueLenght()) && ((queueLenght() < queueMax)||(queueMax == 0)))
drawMoreStatus(queueC, emptyC, Color.black, gradientF, g2d);
drawJobs(g2d);
if(lostJobs > 0) drawLostJobs(Color.BLACK,Color.WHITE,Color.BLACK,true,g2d);
txtBounds = drawCenteredText("jobs in the system:" + jobs, queueC, Color.white, panelW/2.0, panelH - ELEM_HEIGHT, g2d, false, false);
drawCenteredText("jobs in the system:" + jobs, queueC, Color.white, panelW/2.0, panelH - txtBounds.getHeight()/2.0, g2d, false, true);
drawLegend(
legendaC,
legendaS,
dCst.getFont(),
dCst.getStartingGap(),
dCst.getStartingGap(),
g2d ,true);
}
/**
* @param view
*/
private void drawProcessorView(int view, Graphics2D g2d) {
drawProcessor(Color.white, Color.black, gradientF, g2d);
double U = 1.0;
try {
U = ql.utilization();
} catch (NonErgodicException e) {
}
legendaS[0] = "current queue";
legendaC[0] = queueC;
switch (view) {
case 1 :
drawOccupiedPercentage(animC, Color.black, gradientF, g2d);
legendaS[2] = "busy time";
legendaC[2] = animC;
break;
case 2 :
drawUtilization(U, busyC, Color.black, gradientF, g2d);
legendaS[2] = "avg.utilization";
legendaC[2] = busyC.brighter();
break;
default :
drawUtilization(U, busyC, Color.black, gradientF, g2d);
legendaS[2] = "avg.utilization";
legendaC[2] = busyC.brighter();
break;
}
}
/**
* @param i
* @param color
* @param g2d
*/
private void drawQueueStatus(int i, Color startC, Color border, boolean gradientFill, Graphics2D g2d) {
double x = getElementXY(i).x,
y = getElementXY(i).y;
queue[i] = new Rectangle2D.Double(x , y, ELEM_WIDTH, ELEM_HEIGHT);
if (gradientFill){
GradientPaint gp = new GradientPaint((float)x, (float)y, startC.brighter(), (float)x, (float)(y + ELEM_HEIGHT), startC.darker(),false);
g2d.setPaint(gp);
}
else{
g2d.setPaint(startC);
}
g2d.fill(queue[i]);
g2d.setPaint(border);
g2d.draw(queue[i]);
// Controllo se questo stato corrisponde alla media dei jobs
if(i == queueLenght() - queueMedia){
//disegno un triangolo sopra lo stato che rappresenta la media
GeneralPath gp = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
gp.moveTo((float)x, (float)(y - ELEM_HEIGHT/2));
gp.lineTo((float)(x + ELEM_WIDTH), (float)(y - ELEM_HEIGHT/2));
gp.lineTo((float)(x + ELEM_WIDTH/2.0), (float)(y - ELEMS_GAP));
gp.closePath();
drawCenteredText("Q", queueC, null, x + ELEM_WIDTH/2.0, y - ELEM_HEIGHT * 0.7, g2d, false, true);
g2d.setColor(queueC);
g2d.fill(gp);
}
x += ELEM_WIDTH/2.0;
y += ELEM_HEIGHT/2.0;
drawCenteredText("" + (queueLenght() - i), readColor(startC), null, x, y, g2d, false, true);
}
private void drawLostJobs2(Color txtColor, boolean gradientFill, Graphics2D g2d) {
double x = getProcessorXY().x + PROC_RAD,
y = getElementXY(0).y + ELEMS_GAP + ELEM_HEIGHT;
Color tmp = g2d.getColor();
int lj;
if (lostJobs > LOST_JOBS_MAX){
lj = (int) LOST_JOBS_MAX;
lostJobsStr = ">" + (int)LOST_JOBS_MAX;
}
else{
lj = lostJobs;
lostJobsStr = "" + (int)lj;
}
g2d.setColor(txtColor);
g2d.drawString("lost jobs:" + lostJobsStr, (float) (START_GAP), (float) (panelH));
g2d.setColor(tmp);
}
private void drawJobs(Graphics2D g2d) {
double x = getProcessorXY().x + 2 * PROC_RAD,
y = getProcessorXY().y + PROC_RAD * 2 + 4 * ELEMS_GAP;
Color tmp = g2d.getColor();
txtBounds = drawCenteredText("executing job:" + donejobs + ", busy time:" + remainingTime, Color.BLACK, Color.WHITE, x,y,g2d, true, false);
drawCenteredText(
"executing job:" + donejobs + ", busy time:" + remainingTime + "ms",
Color.BLACK,
Color.WHITE,
x - txtBounds.getWidth()/2.0,
y,
g2d, true, true);
//draw box around text
g2d.setColor(tmp);
}
private void drawMoreStatus(Color filledc, Color emptyc, Color border, boolean gradientFill, Graphics2D g2d){
double x = START_GAP + ELEM_WIDTH * 2 + ELEMS_GAP * 2,
y = getElementXY(0).y;
moreStatiRect = new Rectangle2D.Double(x, y, ELEM_WIDTH * 2.0, ELEM_HEIGHT);
Area moreStatiA = new Area(moreStatiRect);
int occ = jobs;
if ((queueMax > 0) && (jobs > queueMax)) occ = queueMax;
int mult = 1;
while(occ > (MORE_JOBS_MAX)){
occ = (int) (occ / 10);
mult = mult * 10;
}
moreStatiA.subtract(
new Area(
new Rectangle2D.Double(
x,
y,
ELEM_WIDTH * 2 - ELEM_WIDTH * occ * 2/ MORE_JOBS_MAX,
ELEM_HEIGHT)));
if (gradientFill){
GradientPaint gp;
gp = new GradientPaint(
(float)x,
(float)y,
emptyc.brighter(),
(float)x,
(float)(y + ELEM_HEIGHT),
emptyc.darker(),
false);
g2d.setPaint(gp);
g2d.fill(moreStatiRect);
gp = new GradientPaint(
(float)x,
(float)y,
filledc.brighter(),
(float)x,
(float)(y + ELEM_HEIGHT),
filledc.darker(),
false);
g2d.setPaint(gp);
g2d.fill(moreStatiA);
}
else{
g2d.setPaint(filledc);
g2d.fill(moreStatiA);
g2d.setPaint(emptyc);
g2d.fill(moreStatiRect);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -