package mygraphs; import java.awt.*; import java.util.*; class GraphPanel extends Panel { Vector items = new Vector(); // This is same as items in panel - store here too for convenience Vector colors = new Vector(); Vector itsYMaxs = new Vector(); float [] ySlopes = null; boolean negativeY = false, autoScale = false, oneMax = true; Image offScrImage = null; boolean offScrUpToDate = false; int scaleInset = 5; GraphPanel() {} public void addItem(GraphableData obj, Color col) { items.addElement(obj); colors.addElement(col); if(oneMax && itsYMaxs.size() > 0) itsYMaxs.addElement(itsYMaxs.elementAt(0)); else itsYMaxs.addElement(new Float(1.0)); updateSlopes(); } // Override this for graphs that store data points public void getNewTimepoint() { repaint(); } // Override this to paint the graph public void paint(Graphics g) { paintOffscreen(); if(offScrUpToDate) g.drawImage(offScrImage, 0, 0, this); } private void paintOffscreen() { Rectangle area = getBounds(); if(offScrImage == null || offScrImage.getWidth(this) != area.width || offScrImage.getHeight(this) != area.height) { offScrImage = createImage(area.width, area.height); offScrUpToDate = false; } if(offScrUpToDate) return; Graphics og = offScrImage.getGraphics(); og.setColor(Color.white); og.fillRect(0, 0, area.width, area.height); plotGraph(og); og.dispose(); } public void plotGraph(Graphics g) {} // Override for each type of graph public void update(Graphics g) { // Gets rid of erase to white blink paint(g); } public void setSize(Dimension d) { super.setSize(d); updateSlopes(); } public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); updateSlopes(); } public void updateSlopes() { int index; float max; if(ySlopes == null || ySlopes.length != itsYMaxs.size()) ySlopes = new float[itsYMaxs.size()]; Dimension area = getSize(); Enumeration elem = itsYMaxs.elements(); index = 0; while(elem.hasMoreElements()) { max = ((Float)elem.nextElement()).floatValue(); if(negativeY) ySlopes[index] = ((float)(area.height - scaleInset * 2) / (max * 2)); else ySlopes[index] = ((float)(area.height - scaleInset * 2) / max); index++; } offScrUpToDate = false; getParent().repaint(); } public boolean getAutoscale() { return autoScale; } public void setAutoscale(boolean auto_scale) { autoScale = auto_scale; } public void setYScale(float max) { if(max <= 0) return; // Maybe need to throw an exception ? for(int index = 0; index < itsYMaxs.size(); index++) { itsYMaxs.setElementAt(new Float(max), index); } updateSlopes(); } public void setYScale(float max, int index_num) { if(max <= 0) return; // Maybe need to throw an exception ? if(oneMax) { setYScale(max); return; } if(index_num >= itsYMaxs.size()) return; // Also an exception here ? itsYMaxs.setElementAt(new Float(max), index_num); updateSlopes(); } public void setYScale(float max, GraphableData obj) { int index = 0; while(index < itsYMaxs.size() && obj != items.elementAt(index)) index++; if(index < itsYMaxs.size()) setYScale(max, index); } public synchronized Dimension getMinimumSize() { return(new Dimension(50, 50)); } public synchronized Dimension getPreferredSize() { return(new Dimension(1000, 1000)); } }