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(); } }