import java.applet.Applet;

// Used for the GUI:
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

// Used to communicate with the surrounding HTML page:
import netscape.javascript.JSObject;
import netscape.javascript.JSException;

/** The AltCommLayer provides an alternative communication layer demo
  * so that Java and techexplorer can interact via a series of JavaScript
  * function calls.  This applet design in considered alternative to other
  * examples in the <strong>techexplorer</strong> documentation which attempt
  * to pass around a reference to a <strong>techexplorer</strong> ActiveX
  * Control or Netscape Plugin object.  That design requires the applet to
  * be aware of <strong>techexplorer</strong> Java classes whereas this
  * design does not.
  * @author	Greg Faron, Integre Technical Publishing Co., Inc.
  * @version			
  */
public class AltCommLayer extends Applet
                          implements ActionListener
  {
// Direct Local File Dependencies:
//   none
//
// Prototypes (not necessary in Java, but helpful to humans):
//
//  Constructors:
//   AltCommLayer(void);
//
//  Methods Inherited from Applet:
//   String getAppletInfo(void);
//   String[][] getParameterInfo(void);
//   void init(void);
//
//  Methods Inherited from ActionListener:
//   void actionPerformed(ActionEvent);
//
//  Original Methods:
//   String getCurrentString(void);
//   void setCurrentString(String);

//
// Protected Members
//
  protected Button broadcastButton = null;
  protected Button receiveButton = null;
  protected JSObject html = null;
  protected TextArea textarea = null;

//
// Constructors
//
/** Default constructor for class <code>AltCommLayer</code>.
  * Required for applets.
  */
  public AltCommLayer()
    {
    // Explicit call to default constructor of superclass, Applet.
    super();
  	} // ends constructor AltCommLayer(void)

//
// Methods Inherited from Applet
//
/** This method is intended (by the Java specs) to provide textual
  * information about the nature of this applet.<br />
  * It is <b>not</b> required for minimal applet execution.
  * @see Applet
  */
  public String getAppletInfo()
    { return "Demo applet to illustrate how to use JavaScript to communicate to Integre techexplorer."; }

/** This method is intended (by the Java specs) to provide textual
  * information about the nature of the various parameters used by this applet.<br />
  * It is <b>not</b> required for minimal applet execution.
  * @see Applet
  */
  public String[][] getParameterInfo()
    {
    final String info[][] = {
      { "texdata", "String", "The initial TeX code to be supplied to Integre techexplorer." }
    };

    return info;
    } // ends getParameterInfo(void)

/** This method is called by the browser's JVM after initial construction.
  * It is used to instantiate several member objects as well as perform GUI
  * layout tasks to prepare the applet for use.
  * @see Applet
  */
  public void init()
    {
    try
      {
      // This is the only oddity when writing compatible code for use
      //  with both the javac and jvc compilers.  jvc thinks a JSException
      //  could be thrown so we have to try and catch it.  javac knows that
      //  one can never be thrown, but since we have to catch one for jvx,
      //  we have to pretend to throw one for javac.
      this.html = JSObject.getWindow(this);
      
      // Pretend to throw an exception.  This satisfies the compiler, but
      //  will be optimized out of the final code because of the "if (false)".
      if (false)
        throw new JSException("Will never occur.");
      } // ends try

    catch(final JSException jse)
      {}

    // Construct the TextArea object member
    this.textarea = new TextArea(this.getParameter("texdata"), 6, 60, TextArea.SCROLLBARS_BOTH);

    // Construct the Button object members
    this.receiveButton = new Button("Get from techexplorer");
    this.receiveButton.setActionCommand("receive");
    this.receiveButton.addActionListener(this);

    this.broadcastButton = new Button("Send to techexplorer");
    this.broadcastButton.setActionCommand("broadcast");
    this.broadcastButton.addActionListener(this);

    // Assign a layout and add everything to the applet
    this.setLayout(new BorderLayout());
    this.add(this.receiveButton, BorderLayout.NORTH);
    this.add(this.textarea, BorderLayout.CENTER);
    this.add(this.broadcastButton, BorderLayout.SOUTH);
    } // ends init(void)

//
// Methods Inherited from ActionListener
//
/** This method handles the signal that occurs when a button is pressed within
  * the applet.  More accurately, it handles events passed from any object that
  * has been assigned <i>this</i> <code>AltCommLayer</code> instance as a listener.
  * @param ae The incoming event to be handled.
  * @see ActionListener
  */
  public void actionPerformed(final ActionEvent ae)
    {
    final String command = ae.getActionCommand();
    if (command == null || command.equals(""))
      return;
    else if (command.equals("broadcast"))
      {
      // Here I've hardcoded the JavaScript function name for simplicity.
      //  Alternatively, you could pass the name in through an applet parameter.
      this.html.call("setTeXString", new Object[] { this.getCurrentString() });
      } // ends else if

    else if (command.equals("receive"))
      {
      // Here I've hardcoded the JavaScript function name for simplicity.
      //  Alternatively, you could pass the name in through an applet parameter.
      this.setCurrentString((String) this.html.call("getTeXString", null));
      } // ends else if

    } // ends actionPerformed(ActionEvent)

//
// Original Methods
//
/** This method retrieves the current value in the displayed textarea.
  * @return The current contents of the {@link #textarea}
  */
  public String getCurrentString()
    {
    // Grab whatever the user entered into the TextArea
    return this.textarea.getText();
    } // ends getCurrentString(void)

/** This method sets the value in the displayed textarea.
  * @param tex A TeX-formatted <code>String</code> that will be displayed
  *            in this applet as unformatted TeX code.
  */
  public void setCurrentString(final String tex)
    {
    // Use the incoming String to replace the current text in the TextArea
    this.textarea.setText(tex);
    } // ends setCurrentString(String)

  } // ends class AltCommLayer
