001 /* 002 * DotFrame.java 003 * Part of the Spirograph problem set. 004 * 005 * Developed for "Rethinking CS101", a project of Lynn Andrea Stein's AP Group. 006 * For more information, see <a href="http://www.ai.mit.edu/projects/cs101/">the 007 * CS101 homepage</a> or email <las@ai.mit.edu>. 008 * 009 * Copyright (C) 1998 Massachusetts Institute of Technology. 010 * Please do not redistribute without obtaining permission. 011 */ 012 013 package spirograph; 014 015 import java.awt.*; 016 import java.awt.event.*; 017 import java.util.*; 018 019 import java.lang.reflect.Method; 020 import java.lang.reflect.InvocationTargetException; 021 022 /** This class pops up the window for the Spirograph, creates all of 023 * the buttons and the DotPanel, and adds them. It also creates an 024 * instance of AdvEnv and passes it a listener that will set the 025 * velocity of the dot. It also starts and suspends the three 026 * Threads (one for each of the AccelHandlers and one for the 027 * DotPanel).</p> 028 * 029 * <p>Copyright © 1998 Massachusetts Institute of Technology.<br /> 030 * Copyright © 2002-2003 Franklin W. Olin College of Engineering.</p> 031 * 032 * @author Luis Sarmenta, lfgs@cag.lcs.mit.edu 033 * @author Henry Wong, henryw@mit.edu 034 * @author Patrick G. Heck, gus.heck@olin.edu 035 * @version $Id: DotFrame.java,v 1.7 2004/02/09 20:55:03 gus Exp $ 036 * @see Coord 037 * @see DotPanel 038 * @see AccelHandler 039 * @see AdvEnv 040 * @see SetVListener 041 * @see Spirograph 042 */ 043 public class DotFrame extends Frame { 044 045 // Must be fields for anonymouse classes 046 private Thread xSpirit, ySpirit, painter; 047 private boolean xStarted = false, yStarted = false, pStarted = false; 048 private DotPanel myPanel; 049 private ResetMenu myRM; 050 private Coord x, y; 051 052 // These fields are used to calculate the difference in size 053 // between the Panel and the Frame. They are used in order to resize 054 // the Panel after the Frame has been resized. 055 056 private int xDif; 057 private int yDif; 058 059 private AdvEnv myAdvEnv; 060 061 /** Creates a new Dot Frame with the Default font. 062 * 063 * @param xHandler The {@link AccelHandler} for the x direction 064 * @param yHandler The {@link AccelHandler} for the y direction 065 * @param xCoord The {@link Coord} object that defines our movement vectors on the x axis 066 * @param yCoord The {@link Coord} object that defines our movement vectors on the y axis 067 */ 068 public DotFrame(AccelHandler xHandler, AccelHandler yHandler, Coord xCoord, Coord yCoord) { 069 this(xHandler, yHandler, xCoord, yCoord, 070 Spirograph.DEFAULTFONT); 071 } 072 073 /** Creates a new dot frame with the default font and <code>null</code> handlers. 074 * 075 * @param xCoord The {@link Coord} object that defines our movement vectors on the x axis 076 * @param yCoord The {@link Coord} object that defines our movement vectors on the y axis 077 */ 078 public DotFrame(Coord xCoord, Coord yCoord) { 079 this((AccelHandler)null, (AccelHandler)null, xCoord, yCoord, Spirograph.DEFAULTFONT); 080 } 081 082 /** Same as other constructor, except it sets the font rather than 083 * using a default. 084 * 085 * @param xHandler The {@link AccelHandler} for the x direction 086 * @param yHandler The {@link AccelHandler} for the y direction 087 * @param xCoord The {@link Coord} object that defines our movement vectors on the x axis 088 * @param yCoord The {@link Coord} object that defines our movement vectors on the y axis 089 * @param f The desired font for this component 090 */ 091 public DotFrame(AccelHandler xHandler, AccelHandler yHandler, Coord xCoord, Coord yCoord, Font f) { 092 093 this.setFont(f); 094 myPanel = new DotPanel(xCoord, yCoord); 095 096 x = xCoord; 097 y = yCoord; 098 099 this.setLayout( new BorderLayout(10, 10)); 100 101 // Create the textfields and listeners for AdvEnv and pass them in. 102 TextField xVel = new TextField(3); 103 TextField yVel = new TextField(3); 104 SetPosGravListener panelListener = new SetPosGravListener(x,y,myPanel); 105 myPanel.addMouseListener(panelListener); 106 107 myAdvEnv = new AdvEnv(xVel, yVel, myPanel); 108 109 myRM = new ResetMenu(); 110 myRM.addListeners(new ActionListener() { 111 public void actionPerformed(ActionEvent ae) { 112 myPanel.flushLines(); 113 myPanel.paintBuf(); 114 } 115 }, 116 new ActionListener() { 117 public void actionPerformed(ActionEvent ae) { 118 myPanel.flushGrav(); 119 myPanel.paintBuf(); 120 } 121 }, 122 new ActionListener() { 123 public void actionPerformed(ActionEvent ae) { 124 suspendSpirits(); 125 suspendPainting(); 126 x.setPos(0); 127 x.setVel(0); 128 y.setPos(0); 129 y.setVel(0); 130 myPanel.paintBuf(); 131 } 132 }, 133 new ActionListener() { 134 public void actionPerformed(ActionEvent ae) { 135 suspendSpirits(); 136 suspendPainting(); 137 x.setPos(0); 138 x.setVel(0); 139 y.setPos(0); 140 y.setVel(0); 141 myPanel.flushLines(); 142 myPanel.flushGrav(); 143 myPanel.paintBuf(); 144 } 145 }); 146 147 if (xHandler == null) { 148 this.setTitle("Etch-a-Sketch Drawing"); 149 } 150 151 if (xHandler != null && yHandler != null) { 152 153 this.setTitle("Spirograph"); 154 155 // Create the buttons and add some functionality. 156 Button start=new Button("Start"); 157 start.addActionListener(new ActionListener() { 158 public void actionPerformed(ActionEvent e) { 159 if(xStarted) { 160 xSpirit.resume(); 161 } else { 162 xSpirit.start(); 163 xStarted = true; 164 } 165 if(yStarted) { 166 ySpirit.resume(); 167 } else { 168 ySpirit.start(); 169 yStarted = true; 170 } 171 beginPainting(); 172 } 173 }); 174 175 Button stop = new Button("Stop"); 176 stop.addActionListener(new ActionListener() { 177 public void actionPerformed(ActionEvent ae) { 178 xSpirit.suspend(); 179 ySpirit.suspend(); 180 painter.suspend(); 181 } 182 }); 183 184 // Create the ResetMenu and some listeners for its various 185 // buttons 186 187 Button reset=new Button("Reset"); 188 reset.addActionListener(new ActionListener() { 189 public void actionPerformed(ActionEvent e) { 190 myRM.setVisible(true); 191 } 192 }); 193 194 195 196 197 // Add Listeners 198 SetVListener myVelSetter = new SetVListener(xVel, yVel, x, y); 199 myAdvEnv.addListener(myVelSetter); 200 201 Button advEnv = new Button("Advanced Environment Options"); 202 advEnv.addActionListener(new ActionListener() { 203 204 public void actionPerformed(ActionEvent ae) { 205 myAdvEnv.setVisible(true); 206 } 207 }); 208 209 // Create the Quit Button 210 Button quit=new Button("Quit"); 211 quit.addActionListener (new ActionListener() { 212 public void actionPerformed(ActionEvent e) { 213 xSpirit.stop(); 214 ySpirit.stop(); 215 setVisible(false); 216 dispose(); 217 System.exit(0); 218 } 219 }); 220 221 System.out.println ("Buttons created."); 222 223 // Create the Button panel 224 Panel p = new Panel(); 225 p.setLayout(new FlowLayout(FlowLayout.CENTER)); 226 227 p.add(start); 228 p.add(stop); 229 p.add(reset); 230 p.add(advEnv); 231 p.add(quit); 232 this.add("South",p); 233 234 System.out.println ("Button panel created"); 235 236 xSpirit = new Thread (xHandler); 237 ySpirit = new Thread (yHandler); 238 239 } 240 241 painter = new Thread (myPanel); 242 243 this.add("Center", myPanel); 244 245 // The Spirograph handles Resizing the window by changing the 246 // size of the Panel. The variables xDif and yDif represents 247 // the difference in size between the Frame and the Panel. 248 249 this.addComponentListener(new ComponentListener() { 250 // if the window is resized, notify the appropriate 251 // Objects. 252 253 public void componentResized(ComponentEvent e) { 254 int width = getSize().width-xDif; 255 int height = getSize().height-yDif; 256 257 System.out.println ("Resized to " + width 258 + " wide and " + 259 height + " high."); 260 261 myPanel.setSize(width,height); 262 } 263 264 // I need to implement these methods for the 265 // ComponentListener interface. 266 public void componentHidden(ComponentEvent e){} 267 public void componentShown(ComponentEvent e){} 268 public void componentMoved(ComponentEvent e){} 269 270 }); 271 272 System.out.println ("Stuff added."); 273 274 this.pack(); 275 this.setVisible(true); 276 277 // xDif and yDif have to be set after Frame is made Visible, 278 // otherwise the calls to getSize will return 0 279 280 xDif = this.getSize().width - myPanel.getSize().width; 281 System.out.println ("Frame width: " + xDif); 282 yDif = this.getSize().height - myPanel.getSize().height; 283 System.out.println ("Frame height: " + yDif); 284 285 System.out.println ("Done."); 286 } 287 288 /** Show the advanced environment options. This method will be removed when 289 * my AdvEtchControls is fully implemented. It is only used by the new 290 * interface. 291 * 292 * @deprecated Since 1/14/03 - will be removed when AdvEtchControl is complete. 293 */ 294 public void showAdvEnv() { 295 myAdvEnv.setVisible(true); 296 } 297 298 /** Show the advanced environment options. This method will be removed when 299 * my AdvEtchControls is fully implemented. It is only used by the new 300 * interface. 301 * 302 * @deprecated Since 1/14/03 - will be removed when AdvEtchControl is complete. 303 */ 304 public void showResetMenu() { 305 myRM.setVisible(true); 306 } 307 308 /** 309 * Suspend the the painting thread. This uses the dangerous and deprecated 310 * <a href ="http://java.sun.com/j2se/1.4.1/docs/guide/misc/threadPrimitiveDeprecation.html"> 311 * Thread.resume()</a> method.The thread it can be restarted 312 * with {@link DotFrame#beginPainting} 313 * 314 */ 315 public void suspendPainting() { 316 painter.suspend(); 317 } 318 319 /** 320 * Start or Resume painting actions. This uses the dangerous and deprecated 321 * <a href ="http://java.sun.com/j2se/1.4.1/docs/guide/misc/threadPrimitiveDeprecation.html"> 322 * Thread.resume()</a> method. Painting Action can be 323 * suspended with {@link DotFrame#suspendPainting()} 324 * 325 */ 326 public void beginPainting() { 327 if(pStarted) { 328 painter.resume(); 329 } else { 330 painter.start(); 331 pStarted = true; 332 } 333 } 334 335 /** Suspend the the spirit threads. This uses the dangerous and deprecated 336 * <a href ="http://java.sun.com/j2se/1.4.1/docs/guide/misc/threadPrimitiveDeprecation.html"> 337 * Thread.resume()</a> method. 338 */ 339 public void suspendSpirits() { 340 if (xSpirit != null) { 341 xSpirit.suspend(); 342 } 343 if (ySpirit != null) { 344 ySpirit.suspend(); 345 } 346 } 347 348 /** Stop the painting thread and call super.dispose() 349 */ 350 public void dispose() { 351 painter.stop(); 352 super.dispose(); 353 } 354 } 355 356 /* 357 * $Log: DotFrame.java,v $ 358 * Revision 1.7 2004/02/09 20:55:03 gus 359 * javadoc fixes 360 * 361 * Revision 1.6 2003/01/15 17:36:10 gus 362 * adding log keywords to files that don't have them 363 * 364 */