/** Alternative Relativity: Doppler Effect Demonstrator by Robert John Morton (Belo Horizonte-MG 27 September 2006, 02 May 2012) Produced (concept to full release) in 5 afternoons. + 2 more afternoons to convert it to Swing. */ import javax.swing.*; // library of swing widgets import java.awt.*; // for graphics operations (GUI) import java.lang.System; // to deal with foreign language options import java.awt.event.*; // for the new-fangled 1.1 event handling import java.awt.image.BufferedImage; public class doppler extends JPanel implements Runnable { private int // Integer values which are private to this class XE, // Horizontal extent of window and JFrame. 500 + 4 YE, // Vertical extent of window and JFrame. 230 + 25 ds = 0; // default mode selection private long p = 15, // applet's prescribed cycle period (milliseconds) t = 0, // System Time at end of last cycle dt = 0; // change in System Time between last cycle and this cycle private BufferedImage H; // off-screen image private Graphics2D h; // graphics reference for off-screen image private volatile Thread T; // declare a thread reference variable private wpanel wp; // instance for the wave display panel doppler(int XE, int YE, int ls) { this.XE = XE; this.YE = YE; String SA[][] = { // localized annotations for app's mode selector buttons {"Mode Selector:","Selecione Modo:"}, {"Classical Relativity","Rel. Clássica"}, {"Alternative Relativity","Rel. Alternativa"} }; String S[] = new String[3]; // array for localized annotations /* Get language selection from applet's HTML parameter to display the annotations in the appropriate language. */ for(int i = 0; i < 3; i++) S[i] = SA[i][ls]; ds = 0; // get applet's default mode from HTML parameter boolean DS[] = {false,false}; // boolean array to represent button states DS[ds] = true; // default mode received from HTML call parameter setLayout(null); // to allow the control panels to be laid out manually JLabel L = new JLabel(S[0],Label.LEFT); // mode selector label add(L); L.setBounds(0,0,130,39); // add title label to JPanel // checkbox group to contain the two mode buttons ButtonGroup G = new ButtonGroup(); // create the first and second mode buttons JRadioButton A = new JRadioButton(S[1], DS[0]); JRadioButton B = new JRadioButton(S[2], DS[1]); // add them to the button group and JPanel, set their positions and sizes G.add(A); add(A); A.setBounds(130,0,170,39); G.add(B); add(B); B.setBounds(300,0,180,39); // creat and add a listener to know when either is pressed A.addItemListener(new modebut(0,this)); B.addItemListener(new modebut(1,this)); // Create image in which to animate off screen H = new BufferedImage(1200,191,BufferedImage.TYPE_INT_RGB); h = H.createGraphics(); // capture its graphics context wp = new wpanel(H,h,ds); // create an instance of wave display panel add(wp); // add image to JPanel wp.setBounds(0,40,500,190); // set its position and size T = new Thread(this); // creating the thread object T.start(); // and starting it running // System time at which first cycle period will finish t = System.currentTimeMillis() + p; } public void run() { while (T != null) { // while the run() thread remains alive... // The time remaining in the current cycle period dt = t - System.currentTimeMillis(); if(dt < 10) dt = 10; // in case machine is too slow try { Thread.sleep(dt); // sleep for remainder of cycle period } catch(InterruptedException e){ // catch interrupt from GUI wp.setCF(true); // re-start traverse of light-source } // Set the System Time at which the following cycle will end t = System.currentTimeMillis() + p; wp.atualizar(); // update the waves repaint(); // repaint the entire applet (necessary for Swing) } } void selectMode(int ds) { wave.setMode(ds); // re-initialize the static mode variable in wave.class wp.setCF(true); // set the change flag to re-start the waves wp.setDS(ds); // set new mode: 'classical' or 'alternative' wp.atualizar(); // re-initialize the display - sets up call to update() } // (CALLED BY EVENT LISTENER CLASS BELOW) } // LISTENS FOR EVENTS FROM THE MODE SELECTOR BUTTONS class modebut implements ItemListener { int id; // one of the above events doppler ap; // application that called: always the above applet! public modebut(int id, doppler ap){ // constructor for a new checkbox event this.id = id; // set id number of this instance of 'modebut' this.ap = ap; // set the reference to this instance of the applet } // from which it came. (only one instance anyway). // a checkbox event has occurred from checkbox 'id' public void itemStateChanged(ItemEvent e){ switch(id) { // communicate the selection to the above applet. // "classical relativity" mode has been selected case 0: ap.selectMode(0); break; // "alternative relativity" mode has been selected case 1: ap.selectMode(1); break; } } }