// // LineGraphPaper.java // GraphPaperTest // // Created by djoiner on Wed Dec 12 2001. // Copyright (c) 2001 __MyCompanyName__. All rights reserved. // import java.awt.*; import java.awt.event.*; public class LineGraphPaper extends BufferCanvas implements MouseListener,MouseMotionListener { int nLines=0; int maxLines=30; int traceLines=30; int traceStep=10; boolean traceOn=true; int traceIndex=0; LineGraphData [] theLines; String title; String indLabel; String depLabel; int topBorderWTitle=30; //with title int topBorderWOTitle=10; //without title int topBorder=topBorderWOTitle; int bottomBorderWLabel=50; int bottomBorderWOLabel=30; int bottomBorder=bottomBorderWOLabel; int leftBorderWLabel=75; int leftBorderWOLabel=50; int leftBorder=leftBorderWOLabel; int rightBorder=10; int buttonSize=24; int dragButtonX; int dragButtonY; int zoomButtonX; int zoomButtonY; boolean dragButtonOn = false; boolean zoomButtonOn = false; boolean dragButtonPressed = false; boolean zoomButtonPressed = false; boolean zoomOut = false; int anchorX=-1; int anchorY=-1; boolean editable = true; boolean highlightBoxOn = false; int highlightBoxX; int highlightBoxY; int highlightBoxWidth; int highlightBoxHeight; double indRealMin = -10.0; double indRealMax = 10.0; double depRealMin = -10.0; double depRealMax = 10.0; double pixelsPerLetter=5.0; int sigDigits = 3; int nDefaultColors = 10; Color [] defaultColors = { Color.red, Color.blue, new Color(0,155,0), new Color(20,100,100), new Color(20,20,20), new Color(20,100,20), new Color(75,75,150), new Color(100,50,50), new Color(50,100,50), new Color(50,75,100) }; public LineGraphPaper() { super(); theLines = new LineGraphData[maxLines]; addMouseMotionListener(this); addMouseListener(this); } public void setTitle(String title) { if (title == null) { this.title = null; topBorder = topBorderWOTitle; } else { this.title = new String(title); topBorder = topBorderWTitle; } } public String getTitle() { if (title == null) { return null; } else { return new String(title); } } public void setIndLabel(String indLabel) { if (indLabel == null) { this.indLabel=null; bottomBorder = bottomBorderWOLabel; } else { this.indLabel = new String(indLabel); bottomBorder = bottomBorderWLabel; } } public String getIndLabel() { if (indLabel == null) { return null; } else { return new String(indLabel); } } public void setDepLabel(String depLabel) { if (depLabel == null) { this.depLabel = null; leftBorder = leftBorderWOLabel; } else { this.depLabel = new String(depLabel); leftBorder = leftBorderWLabel; } } public String getDepLabel() { if (depLabel == null) { return null; } else { return new String(depLabel); } } public void setEditable(boolean editable) { this.editable = editable; } public boolean getEditable() { return editable; } public int realToDisplay(double real, double realMin, double realMax, int displayMin, int displayMax) { double value = (real-realMin)/(realMax-realMin); return displayMin+(int)(value*(double)(displayMax-displayMin)); } public double displayToReal(int display, int displayMin, int displayMax, double realMin, double realMax) { double value = (double)(display-displayMin)/ (double)(displayMax-displayMin); return realMin+value*(realMax-realMin); } public int indRealToDisplay(double indReal) { return realToDisplay(indReal,indRealMin,indRealMax, leftBorder,getWidth()-rightBorder); } public double indDisplayToReal(int indDisplay) { return displayToReal(indDisplay, leftBorder, getWidth() - rightBorder, indRealMin, indRealMax); } public int depRealToDisplay(double depReal) { return realToDisplay(depReal,depRealMin,depRealMax, getHeight()-bottomBorder,topBorder); } public double depDisplayToReal(int depDisplay) { return displayToReal(depDisplay, getHeight()-bottomBorder, topBorder, depRealMin, depRealMax); } public Color blendColor(Color c1, Color c2, double w1) { int red,green,blue; double w2=1.0-w1; red = (int)(w2*(double)c1.getRed()+w1*(double)c2.getRed()); green = (int)(w2*(double)c1.getGreen()+w1*(double)c2.getGreen()); blue = (int)(w2*(double)c1.getBlue()+w1*(double)c2.getBlue()); return new Color(red,green,blue); } public void reset() { traceIndex=0; if(traceOn) { // make all lines darker Color bgColor = getBackground(); for (int i=0 ;imaxLines) { maxLines = Math.max(1,maxLines*2); LineGraphData [] tempLines = new LineGraphData[maxLines]; for (int i=0; itraceLines) { nLines-=traceStep; for (int i=0;i maxData) maxData = theLines[i].nData; } for(int c=0;cindRealMaxTest) indRealMaxTest = theLines[i].indVariable[j]; } } if (indRealMinTest!=indRealMaxTest) { indRealMin=indRealMinTest; indRealMax=indRealMaxTest; } else { indRealMin = -10.0; indRealMax = 10.0; } } public void calcDepBounds() { double depRealMinTest=0.0; double depRealMaxTest=0.0; for (int i=0; idepRealMaxTest) depRealMaxTest = theLines[i].depVariable[j]; } } if (depRealMinTest!=depRealMaxTest) { depRealMin=depRealMinTest; depRealMax=depRealMaxTest; } else { depRealMin=-10.0; depRealMax=10.0; } } public void calcBounds() { calcIndBounds(); calcDepBounds(); } public void setIndMin(double indRealMin) { this.indRealMin = indRealMin; } public void setIndMax(double indRealMax) { this.indRealMax = indRealMax; } public void setDepMin(double depRealMin) { this.depRealMin = depRealMin; } public void setDepMax(double depRealMax) { this.depRealMax = depRealMax; } public double getIndMin() { return indRealMin; } public double getIndMax() { return indRealMax; } public double getDepMin() { return depRealMin; } public double getDepMax() { return depRealMax; } public Color getColor(int i) { return defaultColors[i%nDefaultColors]; } public void setValues(int nData, double [] indVariable, double [] depVariable, String label) { setValues(nData, indVariable, depVariable, null, label); } public void setValues(int nData, double [] indVariable, double [] depVariable) { setValues(nData, indVariable, depVariable, null, null); } public void setValues(int nData, double [] indVariable, double [] depVariable, Color color) { setValues(nData,indVariable,depVariable,color,null); } public void setValues(int nData, double [] indVariable, double [] depVariable, Color color, String label) { checkLines(nLines+1); nLines+=1; traceIndex+=1; if (color==null) { color = defaultColors[traceIndex-1%nDefaultColors]; } if (label==null) { label = new String(""); } theLines[nLines-1] = new LineGraphData(nData, indVariable,depVariable,color,label); } public void drawLines(Graphics g) { // draw lines for (int i=0; inLines-traceIndex-1) { thickLine(g, indRealToDisplay(theLines[i].indVariable[j]), depRealToDisplay(theLines[i].depVariable[j]), indRealToDisplay(theLines[i].indVariable[j+1]), depRealToDisplay(theLines[i].depVariable[j+1])); } else { g.drawLine( indRealToDisplay(theLines[i].indVariable[j]), depRealToDisplay(theLines[i].depVariable[j]), indRealToDisplay(theLines[i].indVariable[j+1]), depRealToDisplay(theLines[i].depVariable[j+1])); } g.setColor(oldColor); } } } public void drawBorder(Graphics g) { // draw border Color oldColor = g.getColor(); g.setColor(Color.black); thickLine(g,leftBorder,topBorder, leftBorder,getHeight()-bottomBorder); thickLine(g,leftBorder,getHeight()-bottomBorder, getWidth()-rightBorder,getHeight()-bottomBorder); thickLine(g,getWidth()-rightBorder,getHeight()-bottomBorder, getWidth()-rightBorder,topBorder); thickLine(g,getWidth()-rightBorder,topBorder, leftBorder,topBorder); g.setColor(oldColor); } public void drawTitle(Graphics g) { if (title!=null) { double titleLength = (double)title.length(); int titlePos = getWidth()/2- (int)(titleLength*pixelsPerLetter/2.0); int titleHeight = topBorder/2+(int)pixelsPerLetter; g.drawString(title,titlePos,titleHeight); } } public void drawDepLabel(Graphics g, double label, int offset, int nAvoid, int [] avoid) { int height = getHeight(); int width = getWidth(); String labelString = StrLib.round(label, sigDigits); double length = (double)labelString.length(); int labelStringPos = leftBorder - (int) ((length+1)*pixelsPerLetter); int labelHeight = depRealToDisplay(label) + offset; boolean okToDraw = true; if (labelHeight > height - bottomBorder || labelHeight < topBorder) { okToDraw = false; } for (int i=0; i= depRealMin && ticks[i] <= depRealMax) { drawDepLabel(g,ticks[i],0,nAvoid,avoid); g.drawLine(leftBorder, depRealToDisplay(ticks[i]), leftBorder+tickLength, depRealToDisplay(ticks[i])); } } if (depLabel != null) { double labelLength = (double)depLabel.length(); int labelPos = leftBorder/2- (int)(labelLength*pixelsPerLetter/2.0); g.drawString(depLabel,labelPos,labelHeight); } } public void drawIndLabel(Graphics g, double label, int offset) { int height = getHeight(); int width = getWidth(); String labelString = StrLib.round(label, sigDigits); double length = (double)labelString.length(); int labelStringPos = indRealToDisplay(label) - (int) ((length)*pixelsPerLetter/2.0) + offset; int labelHeight = height - bottomBorder + 3*(int)pixelsPerLetter; boolean okToDraw = true; if (labelStringPos < leftBorder - (int)(2.0*pixelsPerLetter) || labelStringPos > width - rightBorder + (int)(2.0*pixelsPerLetter)) { okToDraw = false; } if (okToDraw) { g.drawString(labelString,labelStringPos,labelHeight); } } public void drawIndLabels(Graphics g) { // draw labels for max, min, and if not blocking something else, zero int height = getHeight(); int width = getWidth(); int nTicks = 6; double [] ticks = MathLib.niceLabels(nTicks, indRealMin, indRealMax); int tickLength = 5; for (int i=0; i< nTicks; i++) { if (ticks[i] >= indRealMin && ticks[i] <= indRealMax) { drawIndLabel(g,ticks[i],0); g.drawLine(indRealToDisplay(ticks[i]), height-bottomBorder, indRealToDisplay(ticks[i]), height-bottomBorder-tickLength); } } if (indLabel != null) { double labelLength = (double)indLabel.length(); int labelPos = (width + leftBorder - rightBorder)/2- (int)(labelLength*pixelsPerLetter/2.0); int labelHeight = height + 3*(int)pixelsPerLetter/2 - bottomBorder/2; g.drawString(indLabel,labelPos,labelHeight); } } public void drawAxes(Graphics g) { if (indRealMin<0.0 && 0.0 dragButtonX && x < dragButtonX + buttonSize && y > dragButtonY && y < dragButtonY + buttonSize) { dragButtonPressed = true; anchorX = -1; anchorY = -1; } else if (x > zoomButtonX && x < zoomButtonX + buttonSize && y > zoomButtonY && y < zoomButtonY + buttonSize) { zoomButtonPressed = true; if (evt.isShiftDown()) zoomOut = true; else zoomOut = false; anchorX = -1; anchorY = -1; } else { anchorX = x; anchorY = y; } repaintBuffer(); } } public void mouseReleased(MouseEvent evt) { if (editable) { if (dragButtonPressed) { dragButtonOn = !dragButtonOn; zoomButtonOn = false; } else if(zoomButtonPressed) { zoomButtonOn = !zoomButtonOn; dragButtonOn = false; } if (zoomButtonOn) { if (highlightBoxOn) { int x1 = Math.min(anchorX,highlightBoxX); int y1 = Math.min(anchorY,highlightBoxY); int x2 = Math.max(anchorX,highlightBoxX); int y2 = Math.max(anchorY,highlightBoxY); if (evt.isShiftDown()) { int centerX = (x1+x2)/2; int centerY = (y1+y2)/2; double centerRealX = indDisplayToReal(centerX); double centerRealY = depDisplayToReal(centerY); double value = (double)(centerX - leftBorder)/ (double)(centerX-x1); double leftDistanceX = value*(centerRealX - indRealMin); value = (double)(getWidth()-rightBorder-centerX)/ (double)(x2-centerX); double rightDistanceX = value*(indRealMax - centerRealX); value = (double)(centerY - topBorder)/ (double)(centerY-y1); double topDistanceY = value*(depRealMax - centerRealY); value = (double)(getHeight()-bottomBorder-centerY)/ (double)(y2-centerY); double bottomDistanceY = value*(centerRealY - depRealMin); setBounds( centerRealX - leftDistanceX, centerRealX + rightDistanceX, centerRealY - bottomDistanceY, centerRealY + topDistanceY ); } else { setBounds( indDisplayToReal(x1), indDisplayToReal(x2), depDisplayToReal(y2), depDisplayToReal(y1) ); } } } dragButtonPressed = false; zoomButtonPressed = false; anchorX=-1; anchorY=-1; highlightBoxOn = false; repaintBuffer(); } } public void mouseEntered(MouseEvent evt) {} public void mouseExited(MouseEvent evt) {} public void mouseDragged(MouseEvent evt) { if (editable) { // first check that the mouse // movement was properly anchored if (anchorX>=0 && anchorY>=0) { int x = evt.getX(); int y = evt.getY(); if(dragButtonOn) { // compute new values of range // In the anchored frame, what is // the current real x and y. // what is the anchor real x and y // what is the change? double newX = indDisplayToReal(x); double newY = depDisplayToReal(y); double oldX = indDisplayToReal(anchorX); double oldY = depDisplayToReal(anchorY); double changeX = oldX - newX; double changeY = oldY - newY; setBounds(indRealMin+changeX,indRealMax+changeX, depRealMin+changeY,depRealMax+changeY); anchorX = x; anchorY = y; } else if (zoomButtonOn) { // a zoom drag should create a zoomed box. if (evt.isShiftDown()) zoomOut = true; highlightBoxOn = true; highlightBoxX = x; highlightBoxY = y; } repaintBuffer(); } } } public void mouseMoved(MouseEvent evt) {} } class LineGraphData { int nData; double [] depVariable; double [] indVariable; Color color; String label; public LineGraphData(int nData, double [] indVariable,double [] depVariable, Color color, String label) { this.nData = nData; //this.depVariable = new double[nData]; //this.indVariable = new double[nData]; // for (int i=0; i