/* * Open Source Physics software is free software as described near the bottom of this code file. * * For additional information and documentation on Open Source Physics please see: * <http://www.opensourcephysics.org/> */ package org.opensourcephysics.controls; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Iterator; import javax.swing.JButton; import javax.swing.SwingUtilities; import org.opensourcephysics.display.GUIUtils; /** * A GUI consisting of an input text area, a message area, and various buttons * to initialize and control an Animation. * * @author Wolfgang Christian * @author Joshua Gould * @version 1.0 */ public class AnimationControl extends OSPControl { String resetToolTipText = ControlsRes.ANIMATION_RESET_TIP; String initToolTipText = ControlsRes.ANIMATION_INIT_TIP; String startToolTipText = ControlsRes.ANIMATION_START_TIP; String stopToolTipText = ControlsRes.ANIMATION_STOP_TIP; String newToolTipText = ControlsRes.ANIMATION_NEW_TIP; String stepToolTipText = ControlsRes.ANIMATION_STEP_TIP; String initText = ControlsRes.ANIMATION_INIT; String startText = ControlsRes.ANIMATION_START; String stopText = ControlsRes.ANIMATION_STOP; String resetText = ControlsRes.ANIMATION_RESET; String newText = ControlsRes.ANIMATION_NEW; boolean stepModeEditing = true; // enables input editing while single stepping JButton startBtn = new JButton(ControlsRes.ANIMATION_INIT); // changes to start, stop JButton stepBtn = new JButton(ControlsRes.ANIMATION_STEP); JButton resetBtn = new JButton(ControlsRes.ANIMATION_RESET); // changes to new /** * AnimationControl constructor. * * @param animation the animation for this AnimationControl */ public AnimationControl(Animation animation) { super(animation); if(model!=null) { String name = model.getClass().getName(); setTitle(name.substring(1+name.lastIndexOf("."))+" Controller"); //$NON-NLS-1$ //$NON-NLS-2$ } startBtn.addActionListener(new StartBtnListener()); startBtn.setToolTipText(initToolTipText); stepBtn.addActionListener(new StepBtnListener()); stepBtn.setToolTipText(stepToolTipText); resetBtn.addActionListener(new ResetBtnListener()); resetBtn.setToolTipText(resetToolTipText); stepBtn.setEnabled(false); buttonPanel.add(startBtn); buttonPanel.add(stepBtn); buttonPanel.add(resetBtn); validate(); pack(); } /** * Refreshes the user interface in response to display changes such as Language. */ protected void refreshGUI() { super.refreshGUI(); resetToolTipText = ControlsRes.ANIMATION_RESET_TIP; initToolTipText = ControlsRes.ANIMATION_INIT_TIP; startToolTipText = ControlsRes.ANIMATION_START_TIP; stopToolTipText = ControlsRes.ANIMATION_STOP_TIP; newToolTipText = ControlsRes.ANIMATION_NEW_TIP; stepToolTipText = ControlsRes.ANIMATION_STEP_TIP; if(stepBtn==null) { return; } stepBtn.setText(ControlsRes.ANIMATION_STEP); stepBtn.setToolTipText(stepToolTipText); if(startBtn.getText().equals(startText)) { startBtn.setText(ControlsRes.ANIMATION_START); startBtn.setToolTipText(startToolTipText); } else if(startBtn.getText().equals(stopText)) { startBtn.setText(ControlsRes.ANIMATION_STOP); startBtn.setToolTipText(stopToolTipText); } else { startBtn.setText(ControlsRes.ANIMATION_INIT); startBtn.setToolTipText(initToolTipText); } if(resetBtn.getText().equals(newText)) { resetBtn.setText(ControlsRes.ANIMATION_NEW); resetBtn.setToolTipText(newToolTipText); } else { resetBtn.setText(ControlsRes.ANIMATION_RESET); resetBtn.setToolTipText(resetToolTipText); } initText = ControlsRes.ANIMATION_INIT; startText = ControlsRes.ANIMATION_START; resetText = ControlsRes.ANIMATION_RESET; stopText = ControlsRes.ANIMATION_STOP; newText = ControlsRes.ANIMATION_NEW; } /** * Disposes all resources. */ public void dispose() { if(model instanceof AbstractAnimation) { // stops the animation ((AbstractAnimation) model).animationThread = null; } super.dispose(); } /** * Signals the control that the animation has completed. * The control should reset itself in preparation for a new * animation. The given message is printed in the message area. * * @param message */ public void calculationDone(final String message) { // always update a Swing component from the event thread if(model instanceof Animation) { ((Animation) model).stopAnimation(); } Runnable doNow = new Runnable() { public void run() { startBtnActionPerformed(new ActionEvent(this, 0, stopText)); resetBtnActionPerformed(new ActionEvent(this, 0, newText)); resetBtn.setEnabled(true); org.opensourcephysics.display.GUIUtils.enableMenubars(true); if(message!=null) { println(message); } } }; try { if(SwingUtilities.isEventDispatchThread()) { doNow.run(); } else { // paint within the event thread SwingUtilities.invokeAndWait(doNow); } } catch(java.lang.reflect.InvocationTargetException ex1) {} catch(InterruptedException ex1) {} } /** * Method startBtnActionPerformed * * @param e */ void startBtnActionPerformed(ActionEvent e) { // table.getDefaultEditor(Object.class).stopCellEditing(); if(e.getActionCommand().equals(initText)) { stepBtn.setEnabled(true); startBtn.setText(startText); startBtn.setToolTipText(startToolTipText); resetBtn.setText(newText); resetBtn.setToolTipText(newToolTipText); resetBtn.setEnabled(true); readItem.setEnabled(stepModeEditing); table.setEnabled(stepModeEditing); messageTextArea.setEditable(false); GUIUtils.clearDrawingFrameData(false); if(model==null) { println("This AnimationControl's model is null."); //$NON-NLS-1$ } else { ((Animation) model).initializeAnimation(); } org.opensourcephysics.display.GUIUtils.showDrawingAndTableFrames(); } else if(e.getActionCommand().equals(startText)) { setCustomButtonsEnabled(false); startBtn.setText(stopText); startBtn.setToolTipText(stopToolTipText); stepBtn.setEnabled(false); resetBtn.setEnabled(false); readItem.setEnabled(false); table.setEnabled(false); org.opensourcephysics.display.GUIUtils.enableMenubars(false); ((Animation) model).startAnimation(); } else { // action command = Stop startBtn.setText(startText); setCustomButtonsEnabled(true); startBtn.setToolTipText(startToolTipText); stepBtn.setEnabled(true); resetBtn.setEnabled(true); org.opensourcephysics.display.GUIUtils.enableMenubars(true); readItem.setEnabled(stepModeEditing); table.setEnabled(stepModeEditing); ((Animation) model).stopAnimation(); } } /** * Method resetBtnActionPerformed * * @param e */ void resetBtnActionPerformed(ActionEvent e) { if(e.getActionCommand().equals(resetText)) { GUIUtils.clearDrawingFrameData(true); if(model==null) { println("This AnimationControl's model is null."); //$NON-NLS-1$ return; } ((Animation) model).resetAnimation(); if(xmlDefault!=null) { xmlDefault.loadObject(getOSPApp(), true, true); } table.refresh(); } else { // action command = New startBtn.setText(initText); startBtn.setToolTipText(initToolTipText); resetBtn.setText(resetText); resetBtn.setToolTipText(resetToolTipText); stepBtn.setEnabled(false); readItem.setEnabled(true); table.setEnabled(true); messageTextArea.setEditable(true); setCustomButtonsEnabled(true); } } /** * Method stepBtnActionPerformed * * @param e */ void stepBtnActionPerformed(ActionEvent e) { ((Animation) model).stepAnimation(); } private void setCustomButtonsEnabled(boolean enabled) { if(customButtons!=null) { for(Iterator<JButton> it = customButtons.iterator(); it.hasNext(); ) { (it.next()).setEnabled(enabled); } } } /** * Class StartBtnListener */ class StartBtnListener implements ActionListener { /** * Method actionPerformed * * @param e */ public void actionPerformed(ActionEvent e) { startBtnActionPerformed(e); } } /** * Class ResetBtnListener */ class ResetBtnListener implements ActionListener { /** * Method actionPerformed * * @param e */ public void actionPerformed(ActionEvent e) { resetBtnActionPerformed(e); } } /** * Class StepBtnListener */ class StepBtnListener implements ActionListener { /** * Method actionPerformed * * @param e */ public void actionPerformed(ActionEvent e) { stepBtnActionPerformed(e); } } /** * Returns an XML.ObjectLoader to save and load data for this object. * * @return the object loader */ public static XML.ObjectLoader getLoader() { return new AnimationControlLoader(); } /** * A class to save and load data for OSPControls. */ static class AnimationControlLoader extends OSPControlLoader { /** * Saves object data to an XMLControl. * * @param control the control to save to * @param obj the object to save */ public void saveObject(XMLControl control, Object obj) { AnimationControl ac = (AnimationControl) obj; if(ac.startBtn.getText().equals(ac.stopText)) { ac.startBtn.doClick(); // stop the animation if it is running } control.setValue("initialize_mode", ac.startBtn.getText().equals(ac.initText)); //$NON-NLS-1$ super.saveObject(control, obj); } /** * Creates an object using data from an XMLControl. * * @param control the control * @return the newly created object */ public Object createObject(XMLControl control) { return new AnimationControl(null); } /** * Loads an object with data from an XMLControl. * * @param control the control * @param obj the object * @return the loaded object */ public Object loadObject(XMLControl control, Object obj) { AnimationControl ac = (AnimationControl) obj; if(ac.startBtn.getText().equals(ac.stopText)) { ac.startBtn.doClick(); // stop the animation if it is running } boolean initMode = control.getBoolean("initialize_mode"); //$NON-NLS-1$ control.setValue("initialize_mode", null); // don't show this internal parameter //$NON-NLS-1$ super.loadObject(control, obj); // load the control's parameters and the model // put the animation into the initialize state if it was in this state when it was stopped if(initMode) { control.setValue("initialize_mode", true); //$NON-NLS-1$ } if(initMode&&ac.startBtn.getText().equals(ac.startText)) { ac.resetBtn.doClick(); } if(!initMode&&ac.startBtn.getText().equals(ac.initText)) { ac.startBtn.doClick(); } ac.clearMessages(); return obj; } } /** * Creates an animation control and establishes communication between the control and the model. * * @param model Animation * @return AnimationControl */ public static AnimationControl createApp(Animation model) { AnimationControl control = new AnimationControl(model); model.setControl(control); return control; } /** * Creates a animation control and establishes communication between the control and the model. * Initial parameters are set using the xml data. * * @param model Animation * @param xml String[] * @return AnimationControl */ public static AnimationControl createApp(Animation model, String[] xml) { AnimationControl control = createApp(model); control.loadXML(xml); return control; } } /* * Open Source Physics software is free software; you can redistribute * it and/or modify it under the terms of the GNU General Public License (GPL) as * published by the Free Software Foundation; either version 2 of the License, * or(at your option) any later version. * Code that uses any portion of the code in the org.opensourcephysics package * or any subpackage (subdirectory) of this package must must also be be released * under the GNU GPL license. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA * or view the license online at http://www.gnu.org/copyleft/gpl.html * * Copyright (c) 2007 The Open Source Physics project * http://www.opensourcephysics.org */