// Copyright 2002, Steven Lillywhite import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.awt.geom.*; import javax.swing.event.*; // public class Tree extends JPanel implements ActionListener { public class TreeApplet extends JApplet implements ActionListener { JPanel mainPanel; JPanel topPanel; JPanel colorPanel; JPanel backPanel; JPanel midPanel; JButton button1; JButton button2; JButton button3; JComboBox choices; JRadioButton colors; JRadioButton black; JRadioButton blue; JRadioButton red; JRadioButton magenta; JRadioButton pastels; JRadioButton darkhues; JRadioButton backblue; JRadioButton backgray; JLabel angleLabel; JTextField angle; JTextField iterations; JLabel iterationsLabel; JLabel lengthLabel; JTextField length; boolean pictureIsOn=false; paintPane painttree; String coloration="Colors"; String backColoration="gray"; String panelType="AnglesLengths"; public void init(){ try { UIManager.setLookAndFeel( UIManager.getSystemLookAndFeelClassName()); } catch (Exception e) {} makePane(getContentPane()); } void makePane(Container container){ topPanel=new JPanel(); topPanel.setLayout(new GridLayout(0,1)); topPanel.setBorder(BorderFactory.createEtchedBorder()); colorPanel = new JPanel(); colorPanel.setLayout(new GridLayout(0,1)); colorPanel.setBorder(BorderFactory.createEtchedBorder()); backPanel = new JPanel(); backPanel.setLayout(new GridLayout(0,1)); backPanel.setBorder(BorderFactory.createEtchedBorder()); midPanel = new JPanel(); midPanel.setLayout(new GridLayout(0,1)); button1 = new JButton("Start"); button1.setActionCommand("Run"); button2 = new JButton("Update"); button2.setActionCommand("Update"); button2.setMnemonic(KeyEvent.VK_SPACE); button3 = new JButton("Get Information"); button1.addActionListener(this); button2.addActionListener(this); button3.addActionListener(this); String[] boxStrings = {"Angles", "ConstantAngles", "AnglesLengths"}; choices = new JComboBox(boxStrings); choices.setSelectedIndex(2); choices.addActionListener(this); colors = new JRadioButton("Colors"); colors.setActionCommand("Colors"); colors.setSelected(true); black = new JRadioButton("Black"); black.setActionCommand("Black"); blue = new JRadioButton("Blue"); blue.setActionCommand("Blue"); red = new JRadioButton("Red"); red.setActionCommand("Red"); magenta = new JRadioButton("Magenta"); magenta.setActionCommand("Magenta"); pastels = new JRadioButton("Pastels"); pastels.setActionCommand("Pastels"); darkhues = new JRadioButton("Dark Hues"); darkhues.setActionCommand("Dark Hues"); backblue = new JRadioButton("Background Blue"); backblue.setActionCommand("blue"); backgray = new JRadioButton("Background Gray"); backgray.setActionCommand("gray"); backgray.setSelected(true); ButtonGroup group2 = new ButtonGroup(); group2.add(colors); group2.add(black); group2.add(blue); group2.add(red); group2.add(magenta); group2.add(pastels); group2.add(darkhues); ButtonGroup group3 = new ButtonGroup(); group3.add(backblue); group3.add(backgray); colors.addActionListener(this); black.addActionListener(this); blue.addActionListener(this); red.addActionListener(this); magenta.addActionListener(this); pastels.addActionListener(this); darkhues.addActionListener(this); backblue.addActionListener(this); backgray.addActionListener(this); lengthLabel = new JLabel("Length(integer): (+/-)ok"); length = new JTextField("65", 5); length.addActionListener(this); iterationsLabel = new JLabel("Iterations: (<15)"); iterations = new JTextField("10", 5); iterations.addActionListener(this); angleLabel = new JLabel("Angle: (0-360)"); angle = new JTextField("360",5); angle.addActionListener(this); topPanel.add(button2); topPanel.add(button3); topPanel.add(choices); colorPanel.add(colors); colorPanel.add(black); colorPanel.add(red); colorPanel.add(pastels); backPanel.add(backblue); backPanel.add(backgray); midPanel.add(lengthLabel); midPanel.add(length); midPanel.add(iterationsLabel); midPanel.add(iterations); midPanel.add(angleLabel); midPanel.add(angle); mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); mainPanel.setMaximumSize(new Dimension(160,400)); mainPanel.add(topPanel); mainPanel.add(colorPanel); mainPanel.add(backPanel); mainPanel.add(midPanel); // mainPanel.add(Box.createVerticalGlue()); // mainPanel.setSize(140,100); mainPanel.setAlignmentY(Component.TOP_ALIGNMENT); container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS)); container.add(mainPanel); // container.add(Box.createRigidArea(new Dimension(50,0))); painttree= new paintPane(10,65,"Colors","gray", 360,"AnglesLengths"); container.add(painttree); } //actions for button and jtextfield events:///////////////// public void actionPerformed(ActionEvent e){ Object source = e.getSource(); int m=Integer.parseInt(iterations.getText()); int l = Integer.parseInt(length.getText()); double a = Double.parseDouble(angle.getText())*Math.PI/360; if (source==button3){ InfoApplet info = new InfoApplet(); } if(source==choices){ JComboBox cb = (JComboBox)source; panelType = (String)cb.getSelectedItem(); } if (source==red || source==blue || source==colors ||source==pastels || source==darkhues || source==magenta|| source==black){ coloration=e.getActionCommand(); } if (source==backblue || source==backgray){ backColoration=e.getActionCommand(); } if (l==0){ JOptionPane.showMessageDialog(null,"Zero is a bit boring.", "Some advice", JOptionPane.INFORMATION_MESSAGE); } if ((m<1 || m>14) &&(panelType=="Angles" || panelType=="ConstantAngles"||panelType=="AnglesLengths")){ JOptionPane.showMessageDialog(null, "Please enter a number " +"between 1 and 16.", "WARNING!", JOptionPane.WARNING_MESSAGE); }else if (e.getActionCommand() =="Update"){ painttree.repaint(); }else { getContentPane().remove(painttree); painttree=new paintPane(m,l,coloration,backColoration,a, panelType); getContentPane().add(painttree); getContentPane().validate(); } } // public static void main(String[] args){ // try { // UIManager.setLookAndFeel( // UIManager.getSystemLookAndFeelClassName()); // } catch (Exception e) {} // JFrame f = new JFrame("Tree"); // TreeApplet tree = new TreeApplet(); // tree.makePane(f.getContentPane()); // f.addWindowListener(new WindowAdapter() { // public void windowClosing(WindowEvent e) {System.exit(0);} // }); // // f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // // f.pack(); // f.setSize(800,550); // f.setVisible(true); // } } //end class Tree////////////////////////////////////////////////////////// //begin class paintPane: rules for painting the tree, and paints it/// class paintPane extends JPanel { double methodAngle; Graphics2D g2; double randomtheta=0; int m,l; String colorScheme; String paintMethod; treeAppletMethods methods; //begin constructor///////////////////////////////////////////// public paintPane(int m, int l,String colortype, String color, double angle,String paintMethod){ methods = new treeAppletMethods(); this.paintMethod=paintMethod; if(color=="gray"){ setBackground(Color.lightGray); }else if(color=="blue"){ setBackground(Color.blue); } this.m=m; this.l=l; this.setBorder(BorderFactory.createEtchedBorder()); methodAngle=angle; colorScheme=colortype; } //end constructor/////////////////////////////////////////////// public void paintComponent(Graphics g){ g2=(Graphics2D)g; super.paintComponent(g2); GeneralPath[] initialpath = methods.initialPath(340,310,l); g2.draw(initialpath[0]); if(paintMethod=="Angles"){ methods.makeAngles(initialpath, 0, colorScheme, methodAngle,m,g2); }else if(paintMethod=="ConstantAngles"){ methods.makeConstantAngles(initialpath, methodAngle , 0, colorScheme,m,g2); }else { methods.makeAnglesLengths(initialpath,0,colorScheme, methodAngle ,m,g2,l); } } } //end class randomLengthPane////////////////////////////////////////// //begin class treeMethods: tree painting methods///////////////////// class treeAppletMethods{ //initialPath creates an initial vertical path of length l, which can //be negative, meaning the path points down instead of up public GeneralPath[] initialPath(float x0,float y0,int l){ GeneralPath line = new GeneralPath(); GeneralPath[] stub = new GeneralPath[1]; line.moveTo(x0,y0); line.lineTo(x0,y0-l); stub[0]=line; return stub; } //given a path v0, from (x0,y0) to (x1,y1), makePath creates a new //path v, obtained by applying the following affine transformations //to v0. First translate by v0. Then rotate clockwise about (x1,y1) //by theta radians. public GeneralPath makePath(GeneralPath path, double theta){ GeneralPath line; float x0=0; float y0=0; float x1=0; float y1=0; PathIterator it1 = path.getPathIterator(null); float[] theData = new float[6]; int theType; line=new GeneralPath(); while(!it1.isDone()){ theType = it1.currentSegment(theData); switch(theType){ case PathIterator.SEG_MOVETO : x0=theData[0]; y0=theData[1]; break; case PathIterator.SEG_LINETO : x1=theData[0]; y1=theData[1]; break; } it1.next(); } AffineTransform affine = new AffineTransform(Math.cos(theta), Math.sin(theta),-Math.sin(theta),Math.cos(theta), -Math.cos(theta)*x0+Math.sin(theta)*y0+x1, -Math.sin(theta)*x0-Math.cos(theta)*y0+y1); PathIterator it2 = path.getPathIterator(affine); while(!it2.isDone()){ theType = it2.currentSegment(theData); switch(theType){ case PathIterator.SEG_MOVETO : line.moveTo(theData[0], theData[1]); break; case PathIterator.SEG_LINETO : line.lineTo(theData[0], theData[1]); break; } it2.next(); } return line; } //given a path, makeLengthPath creates a new path exactly as makePath, //except its length is equal to lambda public GeneralPath makeLengthPath(GeneralPath path, double theta, double lambda){ GeneralPath line; float x0=0; float y0=0; float x1=0; float y1=0; double w=lambda; double x,y,r,s; PathIterator it1 = path.getPathIterator(null); float[] theData = new float[6]; int theType; line=new GeneralPath(); while(!it1.isDone()){ theType = it1.currentSegment(theData); switch(theType){ case PathIterator.SEG_MOVETO : x0=theData[0]; y0=theData[1]; break; case PathIterator.SEG_LINETO : x1=theData[0]; y1=theData[1]; break; } it1.next(); } AffineTransform affine = new AffineTransform(Math.cos(theta), Math.sin(theta),-Math.sin(theta),Math.cos(theta), -Math.cos(theta)*x0+Math.sin(theta)*y0+x1, -Math.sin(theta)*x0-Math.cos(theta)*y0+y1); PathIterator it2 = path.getPathIterator(affine); while(!it2.isDone()){ theType = it2.currentSegment(theData); switch(theType){ case PathIterator.SEG_MOVETO : line.moveTo(theData[0], theData[1]); break; case PathIterator.SEG_LINETO : x=(double)x1; y=(double)y1; r=(double)theData[0]; s=(double)theData[1]; line.lineTo((float)(x+w*(r-x)/Math.sqrt( Math.pow((r-x),2)+Math.pow((s-y),2))), (float)( y+w*(s-y)/Math.sqrt( Math.pow((r-x),2)+Math.pow((s-y),2)))); break; } it2.next(); } return line; } public Color getColor(String colortype){ double setColor; String colorScheme; Color color; color=Color.black; colorScheme = colortype; if (colorScheme=="Colors"){ setColor = Math.random(); if(0<= setColor && setColor <0.1) color=Color.red; else if(0.1<= setColor && setColor<0.2) color=Color.blue; else if(0.2<= setColor && setColor<0.3) color=Color.yellow; else if(0.3<= setColor && setColor<0.4) color=Color.white; else if(0.4<= setColor && setColor<0.5) color=Color.orange; else if(0.5<= setColor && setColor<0.6) color=Color.green; else if(0.6<= setColor && setColor<0.7) color=Color.magenta; else if(0.7<= setColor && setColor<0.8) color=Color.cyan; else if(0.8<= setColor && setColor<0.9) color=Color.pink; else if(0.9<= setColor && setColor<1.0) color=Color.black; }else if(colorScheme=="Dark Hues"){ setColor=Math.random(); if(0<=setColor && setColor <0.33) color=Color.blue; else if(0.33<= setColor && setColor <0.66) color=Color.magenta; else if(0.66<= setColor && setColor <1.0) color=Color.black; }else if(colorScheme=="Pastels"){ setColor=Math.random(); if(0<=setColor && setColor <0.25) color=Color.yellow; else if(0.25<= setColor && setColor <0.5) color=Color.orange; else if(0.5<= setColor && setColor <0.75) color=Color.cyan; else if(0.75<= setColor && setColor < 1) color=Color.pink; }else if(colorScheme=="Black"){ color=Color.black; }else if(colorScheme=="Blue"){ color=Color.blue; }else if(colorScheme=="Red"){ color=Color.red; }else if(colorScheme=="Magenta"){ color=Color.magenta; } return color; } //begin the primary methods///////////////////////////// public void makeAngles (GeneralPath[] stubs,int s, String colortype, double maxAngle, int m, Graphics2D g2){ String colorScheme; int n; int i; GeneralPath[] moreStubs; double alpha; double methodAngle; double setColor; methodAngle=maxAngle; colorScheme=colortype; Color color; n=stubs.length; if (s