import java.awt.*; import java.applet.*; import java.util.Vector; import java.util.Enumeration; import java.io.*; class MyWindow extends Frame{ Vector myWindows; Vector myModels; Menu fileMenu, editMenu, choiceMenu, controlMenu, levelMenu, colorMenu; SpecialMenuItemGroup levelGroup; CheckboxMenuItemGroup colorGroup, controlGroup, choiceGroup; DrawArea drawArea; Model tempModel; Fractal myparent; public MyWindow(Vector theWindows, Fractal parent, Vector theModels) { super(); myWindows = theWindows; myparent = parent; setTitle("Fractal"); setBackground(Color.white); if (theModels == null) { myModels = new Vector(); addStandardModels(); } else myModels = theModels; setLayout(new BorderLayout()); drawArea = new DrawArea(this); add("Center", drawArea); MenuBar myMenuBar = new MenuBar(); setMenuBar(myMenuBar); fileMenu = new Menu("File"); fileMenu.add(new MenuItem("New")); fileMenu.add(new MenuItem("Open...")); fileMenu.add(new MenuItem("Save as...")); fileMenu.add(new MenuItem("About Fractal...")); fileMenu.addSeparator(); fileMenu.add(new MenuItem("Close")); myMenuBar.add(fileMenu); editMenu = new Menu("Edit"); editMenu.add(new MenuItem("New Generator")); editMenu.add(new MenuItem("Revise Generator")); editMenu.add(new MenuItem("Revise Values")); editMenu.add(new MenuItem("Delete")); myMenuBar.add(editMenu); choiceMenu = new Menu("Choice"); choiceGroup = new CheckboxMenuItemGroup(); Enumeration allModels = myModels.elements(); while (allModels.hasMoreElements()) { try{ tempModel = (Model)allModels.nextElement(); choiceMenu.add(new MyCheckboxMenuItem(tempModel.name, choiceGroup)); } catch (Exception e) ; } myMenuBar.add(choiceMenu); controlMenu = new Menu("Control"); controlGroup = new CheckboxMenuItemGroup(); controlMenu.add(new MyCheckboxMenuItem("Show Generator", controlGroup)); controlMenu.add(new MyCheckboxMenuItem("Hide Generator", controlGroup)); myMenuBar.add(controlMenu); levelMenu = new Menu("Level"); levelGroup = new SpecialMenuItemGroup(); levelMenu.add(new MyCheckboxMenuItem("Lower",levelGroup)); levelMenu.add(new MyCheckboxMenuItem("Higher",levelGroup)); levelMenu.add(new MyCheckboxMenuItem("1",levelGroup)); levelMenu.add(new MyCheckboxMenuItem("2",levelGroup)); levelMenu.add(new MyCheckboxMenuItem("3",levelGroup)); levelMenu.add(new MyCheckboxMenuItem("4",levelGroup)); levelMenu.add(new MyCheckboxMenuItem("5",levelGroup)); levelMenu.add(new MyCheckboxMenuItem("6",levelGroup)); myMenuBar.add(levelMenu); levelGroup.lowerMenu = (MyCheckboxMenuItem)levelMenu.getItem(0); levelGroup.raiseMenu = (MyCheckboxMenuItem)levelMenu.getItem(1); levelGroup.item1 = (MyCheckboxMenuItem)levelMenu.getItem(2); levelGroup.item2 = (MyCheckboxMenuItem)levelMenu.getItem(3); levelGroup.item3 = (MyCheckboxMenuItem)levelMenu.getItem(4); levelGroup.item4 = (MyCheckboxMenuItem)levelMenu.getItem(5); levelGroup.item5 = (MyCheckboxMenuItem)levelMenu.getItem(6); levelGroup.item6 = (MyCheckboxMenuItem)levelMenu.getItem(7); colorMenu = new Menu("Color"); colorGroup = new CheckboxMenuItemGroup(); colorMenu.add(new MyCheckboxMenuItem("No Color", colorGroup)); colorMenu.add(new MyCheckboxMenuItem("Gray", colorGroup)); colorMenu.add(new MyCheckboxMenuItem("Red", colorGroup)); colorMenu.add(new MyCheckboxMenuItem("Green", colorGroup)); colorMenu.add(new MyCheckboxMenuItem("Blue", colorGroup)); colorMenu.add(new MyCheckboxMenuItem("Cyan", colorGroup)); colorMenu.add(new MyCheckboxMenuItem("Magenta", colorGroup)); colorMenu.add(new MyCheckboxMenuItem("Yellow", colorGroup)); myMenuBar.add(colorMenu); } public void doStart() { myWindows.addElement(this); CheckboxMenuItem fix1 = (CheckboxMenuItem)choiceMenu.getItem(0); fix1.setState(true); CheckboxMenuItem fix2 = (CheckboxMenuItem)controlMenu.getItem(1); fix2.setState(true); CheckboxMenuItem fix3 = (CheckboxMenuItem)levelMenu.getItem(4); fix3.setState(true); CheckboxMenuItem fix4 = (CheckboxMenuItem)colorMenu.getItem(2); fix4.setState(true); } public void addStandardModels(){ Model it; it = new Model(); it.makeTwisted(); myModels.addElement(it); it = new Model(); it.makeSieradski(); myModels.addElement(it); it = new Model(); it.makeTree(); myModels.addElement(it); it = new Model(); it.makeInverted(); myModels.addElement(it); it = new Model(); it.makePeano(); myModels.addElement(it); } public void threadStart() { if (drawArea.myThread != null) { if (drawArea.myThread.isAlive()) { drawArea.myThread.resume(); } else drawArea.myThread.start(); } } public void threadSuspend() { if (drawArea.myThread != null) drawArea.myThread.suspend(); } public void threadStop() { if (drawArea.myThread != null) drawArea.myThread.stop(); } public void closeWindow() { if (drawArea.myThread != null) drawArea.myThread.stop(); myWindows.removeElement(this); dispose(); if (myWindows.isEmpty()) { System.exit(0); } } public void increaseLevel(){ levelGroup.increaseLevel(); drawArea.draw(); } public void decreaseLevel(){ levelGroup.decreaseLevel(); drawArea.draw(); } public boolean mouseUp(Event e, int x, int y){ if (e.shiftDown()) decreaseLevel(); else increaseLevel(); return true; } public boolean handleEvent(Event e) { switch (e.id) { case Event.ACTION_EVENT: if (e.target instanceof MenuItem) { Object whichMenu = ((MenuComponent)e.target).getParent(); if ((whichMenu == levelMenu) || (whichMenu == colorMenu) || (whichMenu == controlMenu) || (whichMenu == choiceMenu)) drawArea.draw(); else if (((String)e.arg).equals("Close")) closeWindow(); else if (((String)e.arg).equals("Revise Values")) doRevise(); else if (((String)e.arg).equals("Delete")) doDelete(); else if (((String)e.arg).equals("New Generator")) doNewGenerator(); else if (((String)e.arg).equals("Revise Generator")) doReviseGenerator(); else if (((String)e.arg).equals("Open...")) doOpen(); else if (((String)e.arg).equals("Save as...")) doSave(); else if (((String)e.arg).equals("New")) doNew(); else if (((String)e.arg).equals("About Fractal...")) doAbout(); return true; } return super.handleEvent(e); case Event.WINDOW_DESTROY: closeWindow(); return true; } return super.handleEvent(e); } public Model findSelectedModel(){ Model tempModel, chosenModel = null; String whichChoice = choiceGroup.getCurrent().getLabel(); Enumeration theModels = myModels.elements(); while ((chosenModel == null) && theModels.hasMoreElements()) { try{ tempModel = (Model)theModels.nextElement(); if (whichChoice.equals(tempModel.name)) chosenModel = tempModel; } catch (Exception e) ; } return chosenModel; } public boolean modelStringExists(String s){ boolean found = false; int i = 0; while ((!found) && (i < choiceMenu.countItems())) { if (s.equals(choiceMenu.getItem(i).getLabel())) found = true; i = i + 1; } return found; } public void doDelete(){ if (choiceMenu.countItems() <= 1) return; Model chosenModel = findSelectedModel(); if (chosenModel == null) return; myModels.removeElement(chosenModel); choiceMenu.remove(choiceGroup.getCurrent()); MyCheckboxMenuItem firstItem = (MyCheckboxMenuItem)choiceMenu.getItem(0); choiceGroup.currentChoice = firstItem; firstItem.setStateInternal(true); drawArea.draw(); } public void doNew(){ myparent.makeWin(null); } public void doRevise(){ Model theModel = findSelectedModel(); if (theModel == null) return; Revise myRevise = new Revise(this, true, theModel, drawArea); } public void doNewGenerator(){ int segments = 4; Prelim myPrelim = new Prelim(this, true); } public void doReviseGenerator(){ Model theModel = findSelectedModel(); if (theModel == null) return; ReviseGenerator myReviseGenerator = new ReviseGenerator(this, true, theModel, theModel.segments); } public void doOpen(){ FileInputStream myStream = null; FileDialog myDialog = new FileDialog(this, "Open", FileDialog.LOAD); myDialog.setFile(null); myDialog.move(60, 60); myDialog.show(); String tempdirectory = myDialog.getDirectory(); String tempfile = myDialog.getFile(); if ((tempdirectory != null) && (tempfile != null)) { try { File myFile = new File(tempdirectory + "/" + tempfile); if (myFile.exists() && myFile.canRead()) { myStream = new FileInputStream(myFile); StreamTokenizer myTokens = new StreamTokenizer(myStream); myTokens.eolIsSignificant(false); myTokens.slashSlashComments(true); myTokens.slashStarComments(true); myTokens.parseNumbers(); myTokens.whitespaceChars(0, '!'); myTokens.whitespaceChars('=', '='); myTokens.whitespaceChars(',', ','); myTokens.whitespaceChars(';', ';'); myTokens.whitespaceChars('{', '{'); myTokens.whitespaceChars('}', '}'); myTokens.quoteChar('"'); doRead(myTokens); try { myStream.close(); } catch (Exception ex) ; } } catch (Exception e) { if (myStream != null) try { myStream.close(); } catch (Exception ex) ; } } } public void doRead(StreamTokenizer myTokens) throws IOException { int token; Vector theModels; token = myTokens.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!myTokens.sval.equals("magic"))) return; token = myTokens.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!myTokens.sval.equals("fractal"))) return; theModels = new Vector(); token = myTokens.nextToken(); while ((token == StreamTokenizer.TT_WORD) && myTokens.sval.equals("newf")) { getModel(myTokens, theModels); token = myTokens.nextToken(); } if ((token == StreamTokenizer.TT_WORD) && myTokens.sval.equals("end")) { if (!theModels.isEmpty()) { myparent.makeWin(theModels); } } } public void getModel(StreamTokenizer myTokens, Vector theModels) throws IOException { int token; Model myModel = new Model(); token = myTokens.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!myTokens.sval.equals("size"))) throw new IOException(); token = myTokens.nextToken(); if (token != StreamTokenizer.TT_NUMBER) throw new IOException(); myModel.size = myTokens.nval; token = myTokens.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!myTokens.sval.equals("segments"))) throw new IOException(); token = myTokens.nextToken(); if (token != StreamTokenizer.TT_NUMBER) throw new IOException(); myModel.segments = (int)myTokens.nval; token = myTokens.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!myTokens.sval.equals("numberOfTurns"))) throw new IOException(); token = myTokens.nextToken(); if (token != StreamTokenizer.TT_NUMBER) throw new IOException(); myModel.numberOfTurns = (int)myTokens.nval; token = myTokens.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!myTokens.sval.equals("turns"))) throw new IOException(); int tempturns[] = new int[myModel.numberOfTurns + 1]; for (int i = 0; i <= myModel.numberOfTurns; i++) { token = myTokens.nextToken(); if (token != StreamTokenizer.TT_NUMBER) throw new IOException(); tempturns[i] = (int)myTokens.nval; } myModel.turns = tempturns; token = myTokens.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!myTokens.sval.equals("maxSafe"))) throw new IOException(); token = myTokens.nextToken(); if (token != StreamTokenizer.TT_NUMBER) throw new IOException(); myModel.maxSafe = (int)myTokens.nval; token = myTokens.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!myTokens.sval.equals("name"))) throw new IOException(); token = myTokens.nextToken(); if (token != '"') throw new IOException(); myModel.name = myTokens.sval; token = myTokens.nextToken(); if ((token != StreamTokenizer.TT_WORD) || (!myTokens.sval.equals("endf"))) throw new IOException(); theModels.addElement(myModel); } public void doSave(){ FileOutputStream myStream = null; FileDialog myDialog = new FileDialog(this, "Save", FileDialog.SAVE); myDialog.setFile(null); myDialog.move(60, 60); myDialog.show(); String tempdirectory = myDialog.getDirectory(); String tempfile = myDialog.getFile(); if ((tempdirectory != null) && (tempfile != null)) { try { File myFile = new File(tempdirectory + "/" + tempfile); if (myFile.exists()) { if (myFile.canWrite()) myFile.delete(); else return; } myStream = new FileOutputStream(myFile); PrintStream myPrint = new PrintStream(myStream); doWrite(myPrint); try { myStream.close(); } catch (Exception ex) ; } catch (Exception e) { if (myStream != null) try { myStream.close(); } catch (Exception ex) ; } } } public void doWrite(PrintStream myPrint) { Model tempModel; myPrint.println("magic fractal"); myPrint.println(""); Enumeration allModels = myModels.elements(); while (allModels.hasMoreElements()) { try{ tempModel = (Model)allModels.nextElement(); myPrint.println("newf"); myPrint.print("size = "); myPrint.print((int)tempModel.size); myPrint.println(","); myPrint.print("segments = "); myPrint.print(tempModel.segments); myPrint.println(","); myPrint.print("numberOfTurns = "); myPrint.print(tempModel.numberOfTurns); myPrint.println(","); myPrint.print("turns = {"); for (int i = 0; i <= tempModel.numberOfTurns; i++) { myPrint.print(tempModel.turns[i]); if (i < tempModel.numberOfTurns) myPrint.print(", "); else myPrint.println("};"); } myPrint.print("maxSafe = "); myPrint.print(tempModel.maxSafe); myPrint.println(","); myPrint.print("name = "); myPrint.print("\""); myPrint.print(tempModel.name); myPrint.println("\","); myPrint.println("endf;"); myPrint.println(""); } catch (Exception e) ; } myPrint.println("end"); } public void doAbout(){ AboutDialog aboutDialog = new AboutDialog(this, true); } } /* Code below is Sun's CheckboxGroup, modified to handle similar CheckboxMenuItemGroups. CheckboxGroup.java 1.11 95/11/14 Sami Shaio Copyright (c) 1994-1995 Sun Microsystems, Inc. All Rights Reserved. Permission to use, copy, modify, and distribute this software and its documentation for NON-COMMERCIAL purposes and without fee is hereby granted provided that this copyright notice appears in all copies. Please refer to the file "copyright.html" for further important copyright and licensing information. SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ /* This class is used to create a multiple-exclusion scope for a set of Checkbox buttons. For example, creating a set of Checkbox buttons with the same CheckboxGroup object means that only one of those Checkbox buttons will be allowed to be "on" at a time. version 1.11 11/14/95 author Sami Shaio */ public class CheckboxMenuItemGroup { MyCheckboxMenuItem currentChoice = null; public CheckboxMenuItemGroup() { } public MyCheckboxMenuItem getCurrent() { return currentChoice; } public synchronized void setCurrent(MyCheckboxMenuItem box) { if (box != null && box.group != this) { return; } MyCheckboxMenuItem oldChoice = this.currentChoice; this.currentChoice = box; if ((oldChoice != null) && (oldChoice != box)) { oldChoice.setStateInternal(false); } if (box != null && oldChoice != box && !box.getState()) { box.setStateInternal(true); } } public String toString() { return getClass().getName() + "[current=" + currentChoice + "]"; } } public class SpecialMenuItemGroup extends CheckboxMenuItemGroup { MyCheckboxMenuItem lowerMenu; MyCheckboxMenuItem raiseMenu; MyCheckboxMenuItem item1, item2, item3, item4, item5, item6; int whichItem = 0; public synchronized void setCurrent(MyCheckboxMenuItem box) { if (box != null && box.group != this) { return; } if (box == lowerMenu) whichItem--; else if (box == raiseMenu) whichItem++; else if (box == item1) whichItem = 1; else if (box == item2) whichItem = 2; else if (box == item3) whichItem = 3; else if (box == item4) whichItem = 4; else if (box == item5) whichItem = 5; else if (box == item6) whichItem = 6; fixUp(); } public void fixUp(){ if (whichItem < 1) whichItem = 1; if (whichItem > 6) whichItem = 6; item1.setStateInternal(false); item2.setStateInternal(false); item3.setStateInternal(false); item4.setStateInternal(false); item5.setStateInternal(false); item6.setStateInternal(false); switch(whichItem) { case 1: item1.setStateInternal(true); break; case 2: item2.setStateInternal(true); break; case 3: item3.setStateInternal(true); break; case 4: item4.setStateInternal(true); break; case 5: item5.setStateInternal(true); break; case 6: item6.setStateInternal(true); break; } if (whichItem > 1) lowerMenu.enable(); else lowerMenu.disable(); if (whichItem < 6) raiseMenu.enable(); else raiseMenu.disable(); } public int getLevel(){ if (whichItem > 0) return whichItem; else return 1; } public void increaseLevel(){ whichItem++; fixUp(); } public void decreaseLevel(){ whichItem--; fixUp(); } } /* ------------------------------------ */ public class MyCheckboxMenuItem extends CheckboxMenuItem { CheckboxMenuItemGroup group; public MyCheckboxMenuItem(String label, CheckboxMenuItemGroup group) { super(label); this.group = group; } public void setStateInternal(boolean state) { super.setState(state); } public void setState(boolean state) { CheckboxMenuItemGroup group = this.group; if ((group != null) && state) group.setCurrent(this); } } public class Model { double size = 160; int segments = 4; int numberOfTurns = 8; int turns[] = {0, -90, 90, 90, 0, -90, -90, 90, 0}; int maxSafe = 4; String name = "Twisted Curve"; public Model(){ } public Model(double mysize, int mysegments, int mynumberOfTurns, int myturns[], int mymaxSafe, String myname){ size = mysize; segments = mysegments; numberOfTurns = mynumberOfTurns; turns = myturns; maxSafe = mymaxSafe; name = myname; } public void makeTwisted(){ } public void makeSieradski(){ double mysize = 140; int mysegments = 4; int mynumberOfTurns = 12; int myturns[] = {0, -90, 180, -90, -90, 0, 180, 0, -90, -90, 180, -90, 0}; int mymaxSafe = 4; String myname = "Sieradski's Curve"; size = mysize; segments = mysegments; numberOfTurns = mynumberOfTurns; turns = myturns; maxSafe = mymaxSafe; name = myname; } public void makeTree(){ double mysize = 200; int mysegments = 3; int mynumberOfTurns = 5; int myturns[] = {0, 90, -90, -90, 90, 0}; int mymaxSafe = 5; String myname = "Tree Curve"; size = mysize; segments = mysegments; numberOfTurns = mynumberOfTurns; turns = myturns; maxSafe = mymaxSafe; name = myname; } public void makeInverted(){ double mysize = 140; int mysegments = 3; int mynumberOfTurns = 5; int myturns[] = {0, -90, 90, 90, -90, 0}; int mymaxSafe = 5; String myname = "Inverted Curve"; size = mysize; segments = mysegments; numberOfTurns = mynumberOfTurns; turns = myturns; maxSafe = mymaxSafe; name = myname; } public void makePeano(){ double mysize = 140; int mysegments = 3; int mynumberOfTurns = 9; int myturns[] = {0, -90, 90, 90, 90, -90, -90, -90, 90, 0}; int mymaxSafe = 4; String myname = "Peano's Curve"; size = mysize; segments = mysegments; numberOfTurns = mynumberOfTurns; turns = myturns; maxSafe = mymaxSafe; name = myname; } public int theTurn(int i) { return turns[i]; } }