|
From: Lukas P. <pe...@us...> - 2002-07-15 11:16:33
|
Update of /cvsroot/javaprofiler/module/net/sourceforge/javaprofiler/module/views
In directory usw-pr-cvs1:/tmp/cvs-serv10532
Added Files:
TimeSeriesGraph.java TimeSeriesModel.java
Log Message:
Graphical component
--- NEW FILE: TimeSeriesGraph.java ---
package net.sourceforge.javaprofiler.module.views;
import javax.swing.*;
import java.awt.*;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
/** Draws values of a time series in a bar graph.
* @author Lukas Petru
*/
public class TimeSeriesGraph extends JComponent implements
ChangeListener
{
/** The model that holds time series data. */
private TimeSeriesModel model;
/** This JLabel shows the maximum value of the graph. */
private JLabel maximum;
/** This is the maximum value of the graph. */
private int maxValue;
/** This JLabel shows the last value of the graph. */
private JLabel current;
/** This is the last value shown in the graph. */
private int curValue;
/** Constructs graph with default model. */
public TimeSeriesGraph() {
setPreferredSize(new Dimension(40,40));
setOpaque(true);
setModel(new TimeSeriesModel());
maximum=new JLabel("00");
add(maximum);
maximum.setBackground(null);
maximum.setOpaque(true);
current=new JLabel("00");
add(current);
current.setBackground(null);
current.setOpaque(true);
}
/** Sets a new model.
*/
public void setModel(TimeSeriesModel seriesModel) {
if (seriesModel==null)
throw new RuntimeException("TimeSeriesModel must not be null");
TimeSeriesModel oldModel = getModel();
if (oldModel != null) {
oldModel.removeChangeListener(this);
}
model=seriesModel;
model.addChangeListener(this);
}
/** Returns current model. */
public TimeSeriesModel getModel() {
return model;
}
/** Used for notification of a model data change. Internal function,
not to be called by end users.
*/
public void stateChanged(ChangeEvent e) {
repaint();
}
/** Revalidates Label position. Called in case of size change,
border change or label text change. */
private void revalidateLabel() {
Insets insets = getInsets();
int mw=getWidth() - insets.left - insets.right;
int mh=getHeight() - insets.top - insets.bottom;
// maximum
Dimension size=maximum.getPreferredSize();
int w=size.width;
int h=size.height;
if (w>mw) w=mw;
if (h>mh) h=mh;
maximum.setBounds(insets.left, insets.top, w, h);
// current
size=current.getPreferredSize();
w=size.width;
h=size.height;
if (w>mw) w=mw;
if (h>mh) h=mh;
current.setBounds(getWidth()-insets.right-w, insets.top, w, h);
}
/* Provides hook for revalidateLabel. */
public void revalidate() {
revalidateLabel();
super.revalidate();
}
/* Provides hook for revalidateLabel. */
public void setBounds(int x, int y, int width, int height) {
Rectangle old=getBounds();
super.setBounds(x, y, width, height);
if (! getBounds().equals(old))
revalidateLabel();
}
/** Paints a bar graph. */
protected void paintComponent(Graphics g) {
// draw background (component is always opaque)
super.paintComponent(g);
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
// compute usable area
Insets insets = getInsets();
int currentWidth = getWidth() - insets.left - insets.right;
int currentHeight = getHeight() - insets.top - insets.bottom;
currentHeight -= current.getHeight();
int top=insets.top;
int left=insets.left;
// draw horizontal line
g.setColor(getForeground());
int y1=insets.top + current.getHeight();
g.drawLine(insets.left, y1, currentWidth, y1);
// retrieve data
int[] data=model.getData();
// find largest value
int max=1;
for (int i=0; i<data.length; i++) {
if (data[i] > max)
max=data[i];
if (data[i] < 0)
throw new RuntimeException("Illegal value in TimeSeriesModel");
}
max=fineScale(max);
if (maxValue != max) {
maxValue=max;
maximum.setText(String.valueOf(max));
revalidateLabel();
}
int last=data[data.length-1];
if (curValue != last) {
curValue=last;
current.setText(String.valueOf(last));
revalidateLabel();
}
final int sCnt=data.length;
if (sCnt==0)
throw new RuntimeException(
"Array has zero length in TimeSeriesModel.");
// draw
final int advance=(currentWidth+1) / sCnt;
int columnW=advance-1;
if (columnW<1) columnW=1;
int columnH;
int x=getWidth() - insets.right - sCnt*advance + 1;
final int y=getHeight() - insets.bottom;
for (int i=0; i<sCnt; i++) {
columnH=data[i]*currentHeight/max;
g.fillRect(x, y-columnH, columnW, columnH);
x+=advance;
}
}
/** Returns round number greater or equal to argument. */
private int fineScale (int x) {
int d=1;
int i=x;
while (i>=10) {
i/=10;
d*=10;
}
return (x+d-1)/d*d;
}
}
--- NEW FILE: TimeSeriesModel.java ---
package net.sourceforge.javaprofiler.module.views;
import javax.swing.event.EventListenerList;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;
/** Holds data of a time series. Data are stored in an <code>int</code> array.
* @author Lukas Petru
*/
public class TimeSeriesModel {
/** Holds time series values. */
private int[] data;
private transient ChangeEvent changeEvent = null;
private EventListenerList listenerList = new EventListenerList();
public TimeSeriesModel() {
// test data
data=new int[20];
for (int i=0; i<10; i++)
data[i]=i;
for (int i=10; i<20; i++)
data[i]=20-i;
}
/** Sets new time series values. */
public void setData(int[] series) {
if (series==null)
throw new IllegalArgumentException("null");
data=series;
fireStateChanged();
}
/** Returns current time series values. You must not modify the
returned value. Returned value is not null.
*/
public int[] getData() {
return data;
}
/** Returns a copy of time series values. You can freely
modify returned value.
*/
public int[] copyData() {
int[] r=new int[data.length];
System.arraycopy(data, 0, r, 0, data.length);
return r;
}
// event firing
/**
* Adds a <code>ChangeListener</code> to the TimeSeriesModel.
*
* @param l the listener to add
*/
public void addChangeListener(ChangeListener l) {
listenerList.add(ChangeListener.class, l);
}
/**
* Removes a <code>ChangeListener</code> from the TimeSeriesModel.
*
* @param l the listener to remove
*/
public void removeChangeListener(ChangeListener l) {
listenerList.remove(ChangeListener.class, l);
}
/**
* Returns an array of all the change listeners
* registered on this <code>TimeSeriesModel</code>.
*
* @return all of this model's <code>ChangeListener</code>s
* or an empty
* array if no change listeners are currently registered
*/
public ChangeListener[] getChangeListeners() {
return (ChangeListener[])listenerList.getListeners(
ChangeListener.class);
}
/**
* Notifies all listeners that have registered interest for
* notification on this event type. The event instance
* is created lazily.
*
* @see EventListenerList
*/
protected void fireStateChanged() {
// Guaranteed to return a non-null array
Object[] listeners = listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this event
for (int i = listeners.length-2; i>=0; i-=2) {
if (listeners[i]==ChangeListener.class) {
// Lazily create the event:
if (changeEvent == null)
changeEvent = new ChangeEvent(this);
((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
}
}
}
}
|