/**
  * 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.");
     } 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();
   }
 }