import java.awt.*; import java.applet.*; import java.util.Vector; import java.util.Enumeration; /* Needed to fix a bug in Sun's Applet Viewer; otherwise mouse events do not get to MyWindow! */ class DrawArea extends Panel{ Image im; Graphics offscreen; boolean offscreenbad = true; MyThread myThread; MyWindow myWindow; public DrawArea(MyWindow aWindow){ myWindow = aWindow; } public void draw(){ Model tempModel; if ((myThread != null) && myThread.isAlive()) myThread.stop(); myThread = new MyThread(myWindow, this); myThread.g = getGraphics(); myThread.offscreen = offscreen; myThread.myModel = null; String whichChoice = myWindow.choiceGroup.getCurrent().getLabel(); Enumeration theModels = myWindow.myModels.elements(); while ((myThread.myModel == null) && theModels.hasMoreElements()) { try{ tempModel = (Model)theModels.nextElement(); if (whichChoice.equals(tempModel.name)) myThread.myModel = tempModel; } catch (Exception e) ; } if (myThread.myModel == null) myThread.myModel = new Model(); myThread.start(); } public void paint(Graphics g){ update(g); } public void update(Graphics g) { Graphics other; if (offscreenbad) draw(); else { other = getGraphics(); other.drawImage(im, 0, 0, null); } } public void reshape(int x, int y, int width, int height) { Dimension r = size(); im = myWindow.createImage(width, height); offscreen = im.getGraphics(); offscreenbad = true; super.reshape(x, y, width, height); } } class MyThread extends Thread{ MyWindow myWindow; DrawArea mydrawArea; Model myModel; Graphics g; Graphics offscreen; double dx, dy; double xpos, ypos; Polygon myPolygon; boolean doFill; int x0, y0; public MyThread(MyWindow aWindow, DrawArea drawArea){ super(); myWindow = aWindow; mydrawArea = drawArea; } public void run() { double size, factor; int n; Color theColor = Color.red; boolean generator = false; Graphics tempg; boolean firsttime; int distance; int dir; mydrawArea.offscreenbad = true; String drawGenerator = myWindow.controlGroup.getCurrent().getLabel(); if (drawGenerator.equals("Show Generator")) generator = true; n = myWindow.levelGroup.getLevel(); doFill = true; if (n > myModel.maxSafe) doFill = false; String whichColor = myWindow.colorGroup.getCurrent().getLabel(); if (whichColor.equals("No Color")) { theColor = Color.white; doFill = false; } else if (whichColor.equals("Gray")) theColor = Color.lightGray; else if (whichColor.equals("Red")) theColor = Color.red; else if (whichColor.equals("Green")) theColor = Color.green; else if (whichColor.equals("Blue")) theColor = Color.blue; else if (whichColor.equals("Cyan")) theColor = Color.cyan; else if (whichColor.equals("Magenta")) theColor = Color.magenta; else if (whichColor.equals("Yellow")) theColor = Color.yellow; Dimension r = mydrawArea.size(); size = myModel.size; factor = r.width; if (factor > r.height) factor = r.height; size = size * factor / 300.0; if (generator) size = (3 * size) / 4; for (int i = 1; i <= 2; i++) { if (i == 1) { tempg = g; firsttime = true; } else { tempg = offscreen; firsttime = false; } tempg.setColor(Color.white); tempg.fillRect(0, 0, r.width, r.height); tempg.setColor(Color.black); if (generator) { distance = (int) (factor / ((myModel.segments + 4) * 2)); moveto(2 * distance + 2, r.height / 2); move(0, 1); drawbox(tempg); move(0, -1); dir = 0; for (int j = 0; j < myModel.numberOfTurns; j++) { switch(myModel.theTurn(j)) { case 90: dir = (dir + 1) % 4; break; case -90: dir = (dir + 3) % 4; break; case 180: dir = (dir + 2) % 4; break; } draw(dir, distance, tempg); } move(2, 1); drawbox(tempg); drawstar(tempg); } if (generator) { xpos = (2 * r.width) / 3 - size / 2; ypos = r.height / 2 + size / 2; } else { xpos = r.width / 2 - size/2; ypos = r.height / 2 + size / 2; } if ((!doFill) || firsttime) { initturtle(); recursion(size,n, tempg); turn(90); recursion(size,n, tempg); turn(90); recursion(size,n, tempg); turn(90); recursion(size,n, tempg); turn(90); } if (doFill && (!firsttime)) { tempg.setColor(theColor); tempg.fillPolygon(myPolygon); tempg.setColor(Color.black); tempg.drawPolygon(myPolygon); } } mydrawArea.offscreenbad = false; if (doFill) mydrawArea.update(g); } public void draw(int a, int distance, Graphics tempg) { switch(a) { case 0: thickline(distance, 0, tempg); break; case 1: thickline(0, - distance, tempg); break; case 2: thickline(- distance, 0, tempg); break; case 3: thickline(0, distance, tempg); break; } } public void moveto(int x, int y){ x0 = x; y0 = y; } public void move(int x, int y){ x0 = x0 + x; y0 = y0 + y; } public void line(int x, int y, Graphics g){ g.drawLine(x0, y0, x0 + x, y0 + y); x0 = x0 + x; y0 = y0 + y; } public void thickline(int x, int y, Graphics g){ if (x > 0) { g.drawLine(x0, y0, x0 + x + 3, y0); g.drawLine(x0, y0 + 1, x0 + x + 3, y0 + 1); g.drawLine(x0, y0 + 2, x0 + x + 3, y0 + 2); g.drawLine(x0, y0 + 3, x0 + x + 3, y0 + 3); } else if (x < 0) { g.drawLine(x0 + 3, y0, x0 + x, y0); g.drawLine(x0 + 3, y0 + 1, x0 + x, y0 + 1); g.drawLine(x0 + 3, y0 + 2, x0 + x, y0 + 2); g.drawLine(x0 + 3, y0 + 3, x0 + x, y0 + 3); } else if (y > 0) { g.drawLine(x0, y0, x0, y0 + y + 3); g.drawLine(x0 + 1, y0, x0 + 1, y0 + y + 3); g.drawLine(x0 + 2, y0, x0 + 2, y0 + y + 3); g.drawLine(x0 + 3, y0, x0 + 3, y0 + y + 3); } else { g.drawLine(x0, y0 + 3, x0, y0 + y); g.drawLine(x0 + 1, y0 + 3, x0 + 1, y0 + y); g.drawLine(x0 + 2, y0 + 3, x0 + 2, y0 + y); g.drawLine(x0 + 3, y0 + 3, x0 + 3, y0 + y); } x0 = x0 + x; y0 = y0 + y; } public void drawbox(Graphics tempg){ move(-3, -3); line(6, 0, tempg); line (0, 6, tempg); line(-6, 0, tempg); line(0, -6, tempg); move(3, 3); } public void drawstar(Graphics tempg){ move(-5, -5); line(11, 11, tempg); move(0, -11); line(-11, 11, tempg); move(6, -6); } public void initturtle() { dx = 1; dy = 0; if (doFill) { myPolygon = new Polygon(); myPolygon.addPoint((int)xpos, (int)ypos); } } public void turn(int theta){ double temp; switch(theta) { case 0: break; case 90: temp = dx; dx = dy; dy = -temp; break; case -90: temp = dx; dx = - dy; dy = temp; break; case 180: dx = - dx; dy = - dy; break; } } public void forward(double d, Graphics tempg) { double tempx, tempy; tempx = xpos + d * dx; tempy = ypos + d * dy; tempg.drawLine((int)xpos, (int)ypos, (int)tempx, (int)tempy); xpos = tempx; ypos = tempy; if (doFill) myPolygon.addPoint((int)xpos, (int)ypos); } public void recursion(double k, int m, Graphics tempg) { if (m == 1) forward(k, tempg); else { for (int i = 1; i <= myModel.numberOfTurns; i++) { turn(myModel.theTurn(i - 1)); recursion(k / myModel.segments, m - 1, tempg); } turn(myModel.theTurn(myModel.numberOfTurns)); } } }