import java.applet.Applet;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
/*
* Created on Sep 11, 2004
*/
/**
* a reimplementation of Rafi Nachmias'
* Polyline
*
* @author Mitch Skinner
*/
public class PolyLine extends Applet {
protected static final int BEGINNER_MODE = 0;
protected static final int FULL_MODE = 1;
PolyLineControls controls;
PolyLineCanvas canvas;
public void init() {
setLayout(new BorderLayout());
canvas = new PolyLineCanvas();
add("Center", canvas);
int mode;
if ("beginner".equalsIgnoreCase(getParameter("MODE"))) {
mode = BEGINNER_MODE;
} else {
mode = FULL_MODE;
}
add("South", controls = new PolyLineControls(canvas, mode));
}
public void destroy() {
remove(controls);
remove(canvas);
}
public void start() {
controls.setEnabled(true);
}
public void stop() {
controls.setEnabled(false);
}
public void processEvent(AWTEvent e) {
if (e.getID() == Event.WINDOW_DESTROY) {
System.exit(0);
}
}
public static void main(String args[]) {
Frame f = new Frame("PolyLine");
PolyLine pl = new PolyLine();
pl.init();
pl.start();
f.add("Center", pl);
f.setSize(300, 300);
f.show();
}
public String getAppletInfo() {
return "An interactive demonstration of\nthe need to control variables.\n(A reimplementation of Rafi Nachmias' PolyLine)";
}
}
class PolyLineCanvas extends Canvas {
private static final int xOffset = 0;
private static final int yOffset = 20;
private static final Color[] colors = new Color[] {
Color.black, Color.blue, Color.red, Color.green, Color.orange,
Color.cyan, Color.darkGray, Color.magenta, Color.pink,
Color.yellow
};
int firstLineLength;
Color lineColor;
int numLines = 0;
int lengthDelta;
BasicStroke stroke;
double angle;
int[] xPoints;
int[] yPoints;
boolean drawn = true;
public void paint(Graphics g) {
double direction = Math.PI;
int lineLength = firstLineLength;
if (0 == numLines) return;
//pause for this number of milliseconds
//between successive draws.
int pause = 1000 / numLines;
Rectangle bounds = this.getBounds();
Graphics2D g2;
g2 = (Graphics2D) g;
g2.setColor(lineColor);
g2.setStroke(stroke);
//too slow, given how I'm doing segment-by-segment drawing
//g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
xPoints[0] = ((int) bounds.getCenterX()) + xOffset;
yPoints[0] = ((int) bounds.getCenterY()) + yOffset;
for(int i = 1; i <= numLines; i++) {
xPoints[i] = xPoints[i - 1] + (int) (lineLength * Math.cos(direction));
yPoints[i] = yPoints[i - 1] + (int) (lineLength * Math.sin(direction));
lineLength += lengthDelta;
if (lineLength < 0) {
numLines = i;
break;
}
direction += angle;
}
if ((! drawn) && (numLines < 100)) {
try {
for(int i = 1; i <= numLines; i++) {
g2.drawPolyline(xPoints, yPoints, i + 1);
Thread.sleep(pause);
}
}catch (InterruptedException e) {
System.out.println("Interruped");
}
} else {
g2.drawPolyline(xPoints, yPoints, numLines + 1);
}
drawn = true;
}
public void redraw(int firstLineLength,
int colorNum,
int numLines,
int lengthDelta,
int lineThickness,
int angleDeg) {
this.xPoints = new int[numLines + 1];
this.yPoints = new int[numLines + 1];
this.firstLineLength = firstLineLength;
this.lineColor = colors[(colorNum - 1) % colors.length];
this.numLines = numLines;
this.lengthDelta = lengthDelta;
this.stroke = new BasicStroke((float)lineThickness, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER);
this.angle = ((180.0 - angleDeg) / 180.0) * Math.PI;
drawn = false;
repaint();
}
}
class PolyLineControls extends Panel
implements ActionListener {
PolyLineCanvas canvas;
//these are min, max, default
private static final int[][] limits = new int[][] {
{1, 300, 200}, //first line length
{1, 10, 1}, //color
{1, 1000, 10}, //number of lines
{-100, 100, 0}, //length delta
{1, 20, 3}, //line thickness
{-180, 180, 50} //angle
};
private TextField[] fields = new TextField[limits.length];
protected void placeComponent(Component comp,
GridBagLayout gridbag,
GridBagConstraints c) {
gridbag.setConstraints(comp, c);
add( comp);
}
public PolyLineControls(PolyLineCanvas canvas, int mode) {
Button b = null;
GridBagLayout gridbag = new GridBagLayout();
GridBagConstraints c = new GridBagConstraints();
setLayout(gridbag);
this.canvas = canvas;
for(int i = 0; i < limits.length; i++) {
fields[i] = new TextField(String.valueOf(limits[i][2]), 4);
fields[i].addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void keyPressed(KeyEvent e) {
if (KeyEvent.VK_ENTER == e.getKeyCode())
draw();
}
});
}
int[] varsToUse;
if (PolyLine.BEGINNER_MODE == mode)
varsToUse = new int[] {2, 5};
else
varsToUse = new int[] {0, 1, 2, 3, 4, 5};
for(int i = 0; i < varsToUse.length; i++) {
c.gridx = i;
c.gridy = 0;
Label lbl = new Label("Variable " + String.valueOf(i + 1));
placeComponent(lbl, gridbag, c);
c.gridy = 1;
fields[varsToUse[i]].setText("");
placeComponent(fields[varsToUse[i]], gridbag, c);
}
b = new Button("Draw");
b.addActionListener(this);
c.gridheight = 2;
c.gridx = fields.length;
c.gridy = 0;
placeComponent(b, gridbag, c);
}
private void draw() {
int[] vals = new int[fields.length];
for(int i = 0; i < fields.length; i++) {
try {
vals[i] = Integer.parseInt(fields[i].getText().trim());
} catch (NumberFormatException e) {
vals[i] = limits[i][2];
fields[i].setText(String.valueOf(vals[i]));
}
if (vals[i] < limits[i][0]) {
vals[i] = limits[i][0];
fields[i].setText(String.valueOf(vals[i]));
} else if (vals[i] > limits[i][1]) {
vals[i] = limits[i][1];
fields[i].setText(String.valueOf(vals[i]));
}
}
canvas.redraw(vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]);
}
public void actionPerformed(ActionEvent ev) {
draw();
}
}