/*Siddhartha Kasivajhula * Georgia Institute of Technology * c/o Predrag Cvitanovic * Advisor: Rytis Paskauskas * Fall 2005 */ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.awt.image.*; /* Revisions: Button starts applet, and applet is contained in new frame (01/19) Background color changable (for inclusion in paper) (12/28) Zoom feature is spectacular (11/25) AFM real motion is cleaned up (11/24) Ability to "get" real motion of AFM at any observed time on modular map(11/23) Control Panel functionality improved(11/22) Toolbar added(11/22) Surface motion cleaned up (11/16) Control Panel utility improved (11/15) Work to be done: Add two options: (1) Poincare on bounce, (2) Stroboscopic Add more mutable parameters: y0, V, e?. #Iterations (DONE. But e and #iters not added) Add surface option (1) Choose betw sine, triangular. (2) manually enter surface params: A, phase, etc. Add/fix zoom, center, *select*, info (DONE. info currently redundant) Add SCALE to plot (added mouse info). TO DO (11/24) : (1) **Iterate for t=10** (DONE) (2) Add SCALE (DONE, sort of) (3) Maybe fix zoom (DONE) Remember: Add phase shift to surface. Remember: (1)Set control panel params, (2)reset all with new params, (3)and keep current zoom. (GOOD IDEA. NOT DONE YET 12/02) Dec 02, 2005: Add scale to plots, add mouse info to other plots Flush applet when done? (fix applet reload problem) (fixed, but applet still sits in memory. late Jan,'06) Fix PROBE function Ability to CLEAR screens is important. Might as well add individual RESETs, too Ability to out parameter values to the clipboard will be extremely handy Possibly: Add force function. For a particular 'a': (1) Plot force over time (2) Obtain average force (3) Send data to AFM chaps so that they can determine what the real 'a' is Gives an idea of energy losses in the system F = dp/dt. So F_x = dp_x/dt, and F_y = dp_y/dt Magnitude of Force is what me measure, I should think. So F = V(F_x2 + F_y2), and we have it TO FIND PERIODIC ORBIT: Use 0.63 as restitution: calculate x,y,px,py limit as n->oo. -Orbit tends towards periodicity- */ /* ***NOTES*** (02/06/06) Eventually you will have to make all scales the same, at least in Animation, Trajectory. y_scale, Surf_scale or whatever. (21/01/06) This new frame seems to slow down the applet. Makes no sense. (No it doesn't. Suse browsers run the applet jerkily) Background colors should be tied to a single master color, and give the user the option to change color, later (for printing) Split this file up into 5 files? (DONE Jan 06) Rename classes to "Animation", "Trajectory", "Map", and "Accumulated". (DONE Jan 06) Need to add abstract class to calculate specific quantities (force...) "Measure" : Add a new button in toolbar / control panel / menu: Measure --> Force, Energy, momentum,... New class "Measure"; pass user request to class. Obtain values. Plot these measured quantities, perhaps. Force, certainly. *********** */ //! @brief Main applet that draws everything /// This applet really draws everything. (Guarantee is void if brought into contact with Predrag) public class AFMApplet extends JApplet implements ActionListener, KeyListener { //! Main Applet Window and Frame JFrame mainFrame; JButton startSimulator; //!< This button causes the applet to be displayed /***/ //* Controls *// ControlPanel control; //!< Control panel JFrame calculator; //!< 'Calculator' frame JPanel calculatorPanel; //!< calculator panel JRadioButton force; JRadioButton friction; JRadioButton energy; JRadioButton etc; JButton compute; ButtonGroup calcGroup; JSpinner zoomAdjust; /*Toolbar Panel*/ JToolBar toolbar; //!< Toolbar Panel JToolBar controlBar; static JToggleButton zoomTool; static JToggleButton centerTool; static JToggleButton selectTool; static JToggleButton probeTool; static JToggleButton recordTool; static int x_init, y_init; ButtonGroup tools; /**/ JPanel southPanel; //!< The panel that contains all GUI elements at the bottom of the screen. JMenuBar menuBar; JMenu simulation; JMenu options; JMenu help; JMenuItem restart; JMenuItem strobe; JMenuItem poincare; JMenuItem _help; JPanel mainButtonPanel; JButton startButton; JButton stopButton; JButton resetButton; JPanel animationArea; JPanel aPanel1; JPanel ap1; JPanel subP1; JButton start1; JButton stop1; JButton clear1; JPanel aPanel2; JPanel ap2; JPanel subP2; JButton start2; JButton stop2; JToggleButton accumulate2; JButton clear2; JButton get2; // JPanel aPanel3; JPanel ap3; JPanel subP3; JButton start3; JButton stop3; JButton switch3; JButton mapType3; JButton clear3; JPanel aPanel4; JPanel ap4; JPanel subP4; JButton start4; JButton stop4; JButton numerics4; JButton clear4; JButton show; JButton showCalculator; JLabel myName; /**/ /*CONTROL PANEL*/ private JPanel mainControlPanel; /*Parameters panel*/ private JPanel paramPanel; private JLabel aVal; private JLabel xVal; private JLabel yVal; private JLabel pxVal; private JLabel pyVal; private JLabel y0Val; private JLabel VVal; private JLabel eVal; private static JTextField at; private static JTextField xt; private static JTextField yt; private static JTextField pxt; private static JTextField pyt; private static JTextField y0t; private static JTextField Vt; private static JTextField et; private JButton set; private JButton clear; private JButton defaultVals; private JButton periodic; private JButton hide; public static double params[]; /**/ // The four simulation sections on the screen // Animation pa1; Trajectory pa2; Map pa3; Measure pa4; static int SURFACE_HEIGHT; static int y_scale = 300; static boolean _accumulate2 = false; // Applet must stop all threads when page changed. // public void stop() { stopButton_Clicked(); } //! Frees up memory used by all windows public void destroy() { pa1.cleanup(); pa2.cleanup(); pa3.cleanup(); pa4.cleanup(); } //! stop thread 4 (when stop button is pressed) void stop4_Clicked() { start4.setText("Start"); pa4.stop(); } //! start thread 4 (when start button is pressed) void start4_Clicked() { start4.setText("Faster"); pa4.resume(); } void stop3_Clicked() { start3.setText("Start"); double[] lastDataPoint = pa3.getLastDataPoint(); xt.setText(Double.toString(lastDataPoint[0])); pxt.setText(Double.toString(lastDataPoint[1])); yt.setText(Double.toString(lastDataPoint[2])); pyt.setText(Double.toString(lastDataPoint[3])); pa3.stop(); } //! This method is called when the start button on window number three is pressed. void start3_Clicked() { start3.setText("Faster"); pa3.resume(); } void stop2_Clicked() { start2.setText("Start"); pa2.stop(); } void start2_Clicked() { start2.setText("Faster"); pa2.resume(); } void stop1_Clicked() { start1.setText("Start"); pa1.stop(); } void start1_Clicked() { start1.setText("Faster"); pa1.resume(); } //! reset all windows void resetButton_Clicked() { stopButton_Clicked(); pa1.reset(); pa2.reset(); pa3.reset(); pa4.reset(); pa1.repaint(); pa2.repaint(); pa3.repaint(); pa4.repaint(); } //! stop all windows (threads) void stopButton_Clicked() { startButton.setText("ALL START"); start1.setText("Start"); start2.setText("Start"); start3.setText("Start"); start4.setText("Start"); pa1.stop(); pa2.stop(); pa3.stop(); pa4.stop(); } //! start all threads void startButton_Clicked() { start1.setText("Faster"); start2.setText("Faster"); start3.setText("Faster"); start4.setText("Faster"); startButton.setText("All Faster"); pa1.resume(); pa2.resume(); pa3.resume(); pa4.resume(); } static void set_Clicked() { double a, x, y, px, py, y0, V, eps; try { a = (at.getText().length() >= 1) ? Double.parseDouble(at.getText()) : AFMConstants.default_a; // -42 means default x = (xt.getText().length() >= 1) ? Double.parseDouble(xt.getText()) : AFMConstants.default_x; y = (yt.getText().length() >= 1) ? Double.parseDouble(yt.getText()) : AFMConstants.default_y; px = (pxt.getText().length() >= 1) ? Double.parseDouble(pxt.getText()) : AFMConstants.default_px; py = (pyt.getText().length() >= 1) ? Double.parseDouble(pyt.getText()) : AFMConstants.default_py; y0 = (y0t.getText().length() >= 1) ? Double.parseDouble(y0t.getText()) : AFMConstants.default_y0; V = (Vt.getText().length() >= 1) ? Double.parseDouble(Vt.getText()) : AFMConstants.default_V; eps = (et.getText().length() >= 1) ? Double.parseDouble(et.getText()) : AFMConstants.default_e; } catch (NumberFormatException e) { System.out.println("NumberFormatException in AFMApplet.class" + e + "\n Using default values for all..."); a = AFMConstants.default_a; x = AFMConstants.default_x; y = AFMConstants.default_y; px = AFMConstants.default_px; py = AFMConstants.default_py; y0 = AFMConstants.default_y0; V = AFMConstants.default_V; eps = AFMConstants.default_e; } params[1] = a; params[2] = x; params[3] = y; params[4] = px; params[5] = py; params[6] = y0; params[7] = V; params[8] = eps; }// end set_Clicked() //! This method is called when the applet is first loaded public void init() { super.init(); params = new double[10]; // input parameters from the user params[0] = AFMConstants.default_t; params[1] = AFMConstants.default_a; params[2] = AFMConstants.default_x; params[3] = AFMConstants.default_y; params[4] = AFMConstants.default_px; params[5] = AFMConstants.default_py; params[6] = AFMConstants.default_y0; params[7] = AFMConstants.default_V; params[8] = AFMConstants.default_e; pa1 = new Animation(30); pa2 = new Trajectory(100); pa3 = new Map(20); pa4 = new Measure(100); /* Set up control panel, display */ getContentPane().setLayout(new BorderLayout(0, 0)); addNotify(); // allows you to make changes to the panel without affecting it's current state setSize(400, 300); // size of the applet /* Main Applet Window and frame*/ startSimulator = new JButton("Start Simulator"); startSimulator.addActionListener(this); getContentPane().add(startSimulator); mainFrame = new JFrame("Simulator"); mainFrame.getContentPane().setLayout(new BorderLayout(0, 0)); mainFrame.addNotify(); // allows you to make changes to the panel without affecting it's current state mainFrame.setSize(new Dimension(1040, 820)); /* Set up calculator frame */ calculator = new JFrame("Calculator"); calculator.setSize(300,500); calculatorPanel = new JPanel(); calcGroup = new ButtonGroup(); force = new JRadioButton("Force"); friction = new JRadioButton("Friction"); energy = new JRadioButton("Energy"); etc = new JRadioButton("etc"); compute = new JButton("Compute"); compute.addActionListener(this); calcGroup.add(force); calcGroup.add(friction); calcGroup.add(energy); calcGroup.add(etc); /*Control Panel*/ control = new ControlPanel("Control Panel"); mainControlPanel = new JPanel(); paramPanel = new JPanel(); aVal = new JLabel(" Co-efficient of Restitution: a"); xVal = new JLabel(" Initial position: x"); yVal = new JLabel(" Initial position: y"); pxVal = new JLabel(" Initial x-momentum: px"); pyVal = new JLabel(" Initial y-momentum: py"); y0Val = new JLabel(" Equilibrium point: y0"); VVal = new JLabel(" Shear velocity: V"); eVal = new JLabel(" Spring ratio: e"); at = new JTextField(Double.toString(AFMConstants.default_a), 15); xt = new JTextField(Double.toString(AFMConstants.default_x), 15); yt = new JTextField(Double.toString(AFMConstants.default_y), 15); pxt = new JTextField(Double.toString(AFMConstants.default_px), 15); pyt = new JTextField(Double.toString(AFMConstants.default_py), 15); y0t = new JTextField(Double.toString(AFMConstants.default_y0), 15); Vt = new JTextField(Double.toString(AFMConstants.default_V), 15); et = new JTextField(Double.toString(AFMConstants.default_e), 15); /**/ /*Toolbar*/ toolbar = new JToolBar(); controlBar = new JToolBar(); zoomTool = new JToggleButton("Zoom"); centerTool = new JToggleButton("Center"); selectTool = new JToggleButton("Select"); probeTool = new JToggleButton("Probe"); recordTool = new JToggleButton("Record"); zoomTool.setToolTipText("Left-click zooms in, right-click zooms out"); centerTool.setToolTipText("Centers on a point on the plot"); selectTool.setToolTipText("Allows you to select starting point"); probeTool.setToolTipText("Probes for initial parameters in selected region (draw on plot first)"); recordTool.setToolTipText("Records data in a file 'afm.dat' on the local system"); tools = new ButtonGroup(); tools.add(zoomTool); tools.add(centerTool); tools.add(selectTool); //tools.add(recordTool); /**/ hide = new JButton("Hide"); set = new JButton("Set"); clear = new JButton("Clear"); defaultVals = new JButton("Default"); periodic = new JButton("Periodic"); zoomTool.addActionListener(this); // we don't need this anymore centerTool.addActionListener(this); // scheduled selectTool.addActionListener(this); // for probeTool.addActionListener(this); recordTool.addActionListener(this); // removal hide.addActionListener(this); //ActionListeners react when certain events happen set.addActionListener(this); //in this case, the push of a button clear.addActionListener(this); defaultVals.addActionListener(this); periodic.addActionListener(this); pa3.addKeyListener(this); startSimulator.addKeyListener(this); paramPanel.setLayout(new GridLayout(0, 2));//,150,0)); //layout of the panels (grid) paramPanel.add(aVal); paramPanel.add(at); paramPanel.add(xVal); paramPanel.add(xt); paramPanel.add(yVal); paramPanel.add(yt); paramPanel.add(pxVal); paramPanel.add(pxt); paramPanel.add(pyVal); paramPanel.add(pyt); paramPanel.add(y0Val); paramPanel.add(y0t); paramPanel.add(VVal); paramPanel.add(Vt); paramPanel.add(eVal); paramPanel.add(et); paramPanel.add(set); paramPanel.add(clear); paramPanel.add(defaultVals); paramPanel.add(periodic); toolbar.add(new JLabel(" TOOLS ")); toolbar.add(zoomTool); toolbar.add(centerTool); toolbar.add(selectTool); toolbar.add(probeTool); toolbar.add(recordTool); controlBar.add(new JLabel(" CONTROLS ")); mainControlPanel.setLayout(new GridLayout(0, 1, 30, 0)); mainControlPanel.add(paramPanel); mainControlPanel.add(hide); control.getContentPane().add(mainControlPanel); calculatorPanel.setLayout(new GridLayout(0, 1, 30, 0)); calculatorPanel.add(force); calculatorPanel.add(friction); calculatorPanel.add(energy); calculatorPanel.add(etc); calculatorPanel.add(compute); calculator.getContentPane().add(calculatorPanel); restart = new JMenuItem("Restart"); restart.addActionListener(this); strobe = new JMenuItem("Stroboscopic"); strobe.addActionListener(this); poincare = new JMenuItem("Poincare"); poincare.addActionListener(this); _help = new JMenuItem("Help!"); _help.addActionListener(this); simulation = new JMenu("Simulation"); options = new JMenu("Options"); help = new JMenu("Help"); menuBar = new JMenuBar(); simulation.add(restart); options.add(strobe); options.add(poincare); help.add(_help); menuBar.add(simulation); menuBar.add(options); menuBar.add(help); mainFrame.getContentPane().add("North", menuBar); mainButtonPanel = new JPanel(); mainButtonPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 20, 10)); mainButtonPanel.setBounds(0, 937, 1024, 31); southPanel = new JPanel(); southPanel.setLayout(new BorderLayout()); southPanel.add(toolbar, BorderLayout.WEST); southPanel.add(controlBar, BorderLayout.CENTER); // add "CNS@gatech" or some such affiliation here to southPanel? // JLabel "CNS@gatech" southPanel.add(cns) mainFrame.getContentPane().add("South", southPanel); startButton = new JButton("ALL START"); startButton.setToolTipText("Starts the simulation"); startButton.addActionListener(this); startButton.setBounds(410, 5, 59, 21); controlBar.add(startButton); stopButton = new JButton("All Stop"); stopButton.setToolTipText("Stops the simulation"); stopButton.addActionListener(this); stopButton.setBounds(574, 5, 58, 21); controlBar.add(stopButton); resetButton = new JButton("Reset"); resetButton.setToolTipText("Resets the simulation"); resetButton.addActionListener(this); resetButton.setBounds(637, 5, 51, 21); controlBar.add(resetButton); show = new JButton("Show Panel"); show.setToolTipText("Shows the control panel"); show.addActionListener(this); show.setBounds(800, 5, 101, 21); controlBar.addSeparator(); controlBar.add(show); showCalculator = new JButton("Calculator"); showCalculator.setToolTipText("Brings up the calculator window"); showCalculator.addActionListener(this); showCalculator.setBounds(902, 5, 60, 21); controlBar.addSeparator(); controlBar.add(showCalculator); /* The whole animation area */ animationArea = new JPanel(); animationArea.setLayout(new GridLayout(2, 2, 0, 0)); animationArea.setBounds(0, 0, 1024, 737); //262 / 293 (31 pixels) mainFrame.getContentPane().add("Center", animationArea); /* The entire top-left animation area */ aPanel1 = new JPanel(); aPanel1.setLayout(new BorderLayout(0, 0)); aPanel1.setBounds(0, 0, 512, 368); animationArea.add(aPanel1); /* This holds the canvas */ ap1 = new JPanel(); ap1.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 25)); ap1.setBounds(0, 0, 512, 337); aPanel1.add("Center", ap1); /* This has the buttons */ subP1 = new JPanel(); subP1.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); subP1.setBounds(0, 337, 512, 31); aPanel1.add("South", subP1); start1 = new JButton("Start"); start1.addActionListener(this); start1.setBounds(200, 5, 41, 21); subP1.add(start1); stop1 = new JButton("Stop"); stop1.addActionListener(this); stop1.setBounds(246, 5, 40, 21); subP1.add(stop1); clear1 = new JButton("Clear"); clear1.addActionListener(this); clear1.setBounds(246, 5, 40, 21); subP1.add(clear1); /* The entire top-right animation area */ aPanel2 = new JPanel(); aPanel2.setLayout(new BorderLayout(0, 0)); aPanel2.setBounds(512, 0, 512, 368); animationArea.add(aPanel2); /* Top-right canvas */ ap2 = new JPanel(); ap2.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 25)); ap2.setBounds(0, 0, 512, 337); aPanel2.add("Center", ap2); /* Top-right buttons */ subP2 = new JPanel(); subP2.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); subP2.setBounds(0, 337, 512, 31); aPanel2.add("South", subP2); start2 = new JButton("Start"); start2.addActionListener(this); start2.setBounds(200, 5, 41, 21); subP2.add(start2); stop2 = new JButton("Stop"); stop2.addActionListener(this); stop2.setBounds(246, 5, 40, 21); subP2.add(stop2); accumulate2 = new JToggleButton("Accumulate"); accumulate2.addActionListener(this); accumulate2.setBounds(292, 5, 40, 21); subP2.add(accumulate2); get2 = new JButton("Get"); get2.setToolTipText("Ties the state of the AFM here to the animation window"); get2.addActionListener(this); get2.setBounds(338, 5, 40, 21); subP2.add(get2); clear2 = new JButton("Clear"); clear2.addActionListener(this); clear2.setBounds(384, 5, 40, 21); subP2.add(clear2); /* Bottom-left animation area */ aPanel3 = new JPanel(); aPanel3.setLayout(new BorderLayout(0, 0)); aPanel3.setBounds(0, 368, 512, 368); animationArea.add(aPanel3); /* Bottom-left canvas */ ap3 = new JPanel(); ap3.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 25)); ap3.setBounds(0, 0, 512, 337); aPanel3.add("Center", ap3); /* Bottom-left buttons */ subP3 = new JPanel(); subP3.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); subP3.setBounds(0, 337, 512, 31); aPanel3.add("South", subP3); start3 = new JButton("Start"); start3.addActionListener(this); start3.setBounds(200, 5, 41, 21); subP3.add(start3); stop3 = new JButton("Stop"); stop3.addActionListener(this); stop3.setBounds(246, 5, 40, 21); subP3.add(stop3); switch3 = new JButton("( y, py )"); switch3.setToolTipText("Toggles between ( x, px ) and ( y, py )"); switch3.addActionListener(this); switch3.setBounds(292, 5, 40, 21); subP3.add(switch3); mapType3 = new JButton("Poincare'"); mapType3.setToolTipText("Toggle between Stroboscopic map and Poincare' section"); mapType3.addActionListener(this); mapType3.setBounds(338, 5, 40, 21); subP3.add(mapType3); clear3 = new JButton("Clear"); clear3.setToolTipText("Temporarily clears screen"); clear3.addActionListener(this); clear3.setBounds(384, 5, 40, 21); subP3.add(clear3); /* Bottom-right animation area */ aPanel4 = new JPanel(); aPanel4.setLayout(new BorderLayout(0, 0)); aPanel4.setBounds(512, 368, 512, 368); animationArea.add(aPanel4); /* Bottom-right canvas */ ap4 = new JPanel(); ap4.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 25)); ap4.setBounds(0, 0, 512, 337); aPanel4.add("Center", ap4); /* Bottom-right buttons */ subP4 = new JPanel(); subP4.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5)); subP4.setBounds(0, 337, 512, 31); aPanel4.add("South", subP4); start4 = new JButton("Start"); start4.addActionListener(this); start4.setBounds(200, 5, 41, 21); subP4.add(start4); stop4 = new JButton("Stop"); stop4.addActionListener(this); stop4.setBounds(246, 5, 40, 21); subP4.add(stop4); numerics4 = new JButton("Numerics"); numerics4.addActionListener(this); numerics4.setBounds(292, 5, 40, 21); subP4.add(numerics4); clear4 = new JButton("Clear"); clear4.addActionListener(this); clear4.setBounds(338, 5, 40, 21); subP4.add(clear4); /* Add the canvases to the canvas panels */ ap1.add(pa1); ap2.add(pa2); ap3.add(pa3); ap4.add(pa4); }//end init /*Server methods. Interaction with simulation windows.*/ public double[] getParams() // return parameter values, for possible use in future { return params; } public static void drawSurface(BufferedImage image, AFMSimulator afmSim, int surface_periods, Color surface_color) { int W = image.getWidth(), H = image.getHeight(); double INTERVAL = (double) W / AFMConstants.SAMPLES; SURFACE_HEIGHT = H/2 + 100; Graphics back = image.getGraphics(); back.setColor(surface_color); for(int j = 0; j= W) xCoord -= W; int yCoord = SURFACE_HEIGHT - (int) Math.round(afmSim.getSurface().getY(i) * 500 / surface_periods); back.drawOval(xCoord, yCoord, 0, 0); } } } public static void drawAxes(BufferedImage image, int x_axis, int y_axis, String xLabel, String yLabel, double x_max, double y_max, int scale, Color axes_color) { /* try to use the 'scale' idea. It is more elegant and simplifies a lot of things */ int W = image.getWidth(), H = image.getHeight(); Graphics back = image.getGraphics(); back.setColor(axes_color); /* draw axes */ back.drawLine(0, x_axis, W, x_axis); // dear x-axis back.drawLine(y_axis, 0, y_axis, H); // y-axis /* draw axis lables */ back.drawString(xLabel, W - 20, x_axis + 10); back.drawString(yLabel, y_axis + 5, 15); /* draw axis markings */ back.drawLine(W/2, x_axis + 5, W/2, x_axis - 5); // middle back.drawLine(y_axis - 5, H/2, y_axis + 5, H/2); // middle back.drawLine(W/4, x_axis + 5, W/4, x_axis - 5); // left x-axis back.drawLine(W*3/4, x_axis + 5, 3*W/4, x_axis - 5); // right x-axis back.drawLine(y_axis - 5, H/4, y_axis + 5, H/4); // upper y-axis back.drawLine(y_axis - 5, 3*H/4, y_axis + 5, 3*H/4); // lower y-axis /* Values at markers */ back.drawString(Double.toString(x_max / 2), 3*W/4, x_axis + 15); back.drawString(Double.toString(- x_max / 2), W/4, x_axis + 15); back.drawString(Double.toString(y_max / 2), y_axis + 5, H/4); back.drawString(Double.toString(- y_max / 2), y_axis + 5, 3*H/4); } public static void setControlText(String aText, String xText, String yText, String pxText, String pyText, String y0Text, String VText, String eText) { at.setText(aText); xt.setText(xText); yt.setText(yText); pxt.setText(pxText); pyt.setText(pyText); y0t.setText(y0Text); Vt.setText(VText); et.setText(eText); } //! This method is called automatically when a specific "action" takes place. //! This includes all interaction with the user through buttons, menus, mouse movements public void actionPerformed(ActionEvent event) { // finds the source of the event and responds accordingly // /*Main Applet Window events*/ mainFrame.setVisible(true); if(event.getSource() == startSimulator) { mainFrame.setVisible(true); control.setVisible(true); } /*Menubar events*/ if (event.getSource() == restart) { resetButton_Clicked(); startButton_Clicked(); } if (event.getSource() == strobe) { System.out.println("Your wish"); pa3.poincare(false); } if (event.getSource() == poincare) { System.out.println("Stranger things have happened"); pa3.poincare(true); } if(event.getSource() == _help) { JOptionPane.showMessageDialog(mainFrame, "Move over any button to see what it does"); } /**/ /*Common control button events*/ if (event.getSource() == startButton) startButton_Clicked(); if (event.getSource() == stopButton) stopButton_Clicked(); if (event.getSource() == resetButton) resetButton_Clicked(); /**/ /*Top-left events*/ if (event.getSource() == start1) start1_Clicked(); if (event.getSource() == stop1) stop1_Clicked(); if (event.getSource() == clear1) pa1.clear(); /**/ /*Top-right events*/ if (event.getSource() == start2) start2_Clicked(); if (event.getSource() == stop2) stop2_Clicked(); if (event.getSource() == accumulate2) { if(accumulate2.isSelected()) _accumulate2 = true; else _accumulate2 = false; } if (event.getSource() == get2) { stop2_Clicked(); pa1.setState(pa2.getState()); // } if (event.getSource() == clear2) pa2.clear(); /**/ /*Bottom-left events*/ if (event.getSource() == start3) start3_Clicked(); if (event.getSource() == switch3) { if (switch3.getText().equals("( y, py )")) switch3.setText("( x, px )"); else switch3.setText("( y, py )"); pa3.changePanel(); } if (event.getSource() == stop3) stop3_Clicked(); if (event.getSource() == mapType3) { if(mapType3.getText().equals("Poincare'")) { mapType3.setText("Stroboscopic"); System.out.println("Stranger things have happened"); } else { mapType3.setText("Poincare'"); System.out.println("Your wish"); } pa3.toggleMap(); }// if event source = mapType3 if (event.getSource() == clear3) pa3.clear(); /**/ /*Bottom-right events*/ if (event.getSource() == start4) start4_Clicked(); if (event.getSource() == stop4) stop4_Clicked(); if(event.getSource() == numerics4) { if (numerics4.getText().equals("Numerics")) numerics4.setText("Plot"); else numerics4.setText("Numerics"); pa4.switchDisplay(); } if (event.getSource() == clear4) pa4.clear(); /**/ /*Toolbar events*/ if (event.getSource() == probeTool) { if (probeTool.getText().equals("Probe")) probeTool.setText("End"); else probeTool.setText("Probe"); pa3.toggleProbing(); } if(event.getSource() == recordTool) { pa3.toggleRecord(); } /**/ /*Control Panel events*/ if (event.getSource() == hide) control.setVisible(false); // hides control panel if (event.getSource() == set) // sets initial parameters and resets simulation { set_Clicked(); resetButton_Clicked(); } if (event.getSource() == clear) { at.setText(""); xt.setText(""); yt.setText(""); pxt.setText(""); pyt.setText(""); y0t.setText(""); Vt.setText(""); et.setText(""); } if (event.getSource() == defaultVals) { at.setText(Double.toString(AFMConstants.default_a)); xt.setText(Double.toString(AFMConstants.default_x)); yt.setText(Double.toString(AFMConstants.default_y)); pxt.setText(Double.toString(AFMConstants.default_px)); pyt.setText(Double.toString(AFMConstants.default_py)); y0t.setText(Double.toString(AFMConstants.default_y0)); Vt.setText(Double.toString(AFMConstants.default_V)); et.setText(Double.toString(AFMConstants.default_e)); set.doClick(); } if (event.getSource() == periodic) { at.setText(Double.toString(AFMConstants.periodic_a)); xt.setText(Double.toString(AFMConstants.periodic_x)); yt.setText(Double.toString(AFMConstants.periodic_y)); pxt.setText(Double.toString(AFMConstants.periodic_px)); pyt.setText(Double.toString(AFMConstants.periodic_py)); y0t.setText(Double.toString(AFMConstants.periodic_y0)); Vt.setText(Double.toString(AFMConstants.periodic_V)); et.setText(Double.toString(AFMConstants.periodic_e)); set.doClick(); } if (event.getSource() == show) control.setVisible(true); // show control panel /**/ if (event.getSource() == showCalculator) calculator.setVisible(true); }// end actionPerformed public void keyPressed(KeyEvent e) { if (e.getKeyChar() == 'x') stopButton_Clicked(); if (e.getSource()==startSimulator && e.getKeyChar() == 13) { mainFrame.setVisible(true); control.setVisible(true); } } public void keyReleased(KeyEvent e) { //To change body of implemented methods use File | Settings | File Templates. } public void keyTyped(KeyEvent e) { //To change body of implemented methods use File | Settings | File Templates. } }//end AFMApplet //! The control panel, where the user may enter initial parameter values. class ControlPanel extends JFrame implements KeyListener{ public ControlPanel(String title) { super(title); setSize(320, 500); } public void keyPressed(KeyEvent e) { } public void keyReleased(KeyEvent e) { } public void keyTyped(KeyEvent e) { /*if(e.getKeyText().equals("Enter")) { // add here some code to "press" the set button AFMApplet.set_Clicked(); }*/ } }// end ControlPanel