///////////////////////////////////////////////////////////////////////
//
// GraphITControl: Implement Slider and update the GraphIT and techexplorer 
//                 displays in response to user input  
// Version of 9/8/00 2:25PM
//
///////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004 Integre Technical Publishing.  All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////

import java.awt.*;
import java.applet.Applet;
import integre.techexplorer.techexplorer;
import integre.techexplorer.control.techexplorerControl;
import integre.techexplorer.axtchexp.AxTchExpRaw;
import integre.techexplorer.awt.AWTEvent;
import integre.techexplorer.awt.event.*; 			// For MouseEvent, MouseListener

public class GraphITControl extends Applet implements MouseListener { 

  private Applet       graphITHandle    = null;  // Handle for GraphIT applet
  private int          curveID          = TrigCurve.SINCURVE; 
  private String       techexplorerDisp = "";
  private Slider       slider           = null;
  private techexplorer texplorer        = null;
  private int teWindowHeight = 0;               // Needed by the mouseReleased event handler

  // The next two methods are called from JavaScript code in the HTML page & not from the Java code

  public void setPlugin(techexplorer obj, int h)// Called by the JavaScript code in the html
  {                                             // page to provide a handle to the Netscape plugin.
     if ( obj instanceof techexplorer )			// The handle is used to register a listener
        texplorer = obj;						// on the techexplorer component that displays
												// the formulae for the curves that are graphed

     // Register the event listener for the techexplorer trig function display
     texplorer.addMouseListener( (MouseListener)this );
     updateTEDisplay();                         // Initialize TE Display
     
     teWindowHeight = h;                        // Get height of te window for event handling
  }

  public void setControl(AxTchExpRaw obj, int h)// When the browser is IE, this is the method
  {												// used to register event listeners for te
     if ( obj instanceof AxTchExpRaw )
       texplorer = new techexplorerControl( obj );

     // Register the event listener for the techexplorer trig function display
     texplorer.addMouseListener( (MouseListener)this );
     updateTEDisplay();                         // Initialize TE Display
  
     teWindowHeight = h;                        // Get height of te window for event handling
  }

  public void init() {
	setLayout(new GridLayout(1,1));
	slider = new Slider( TrigCurve.CURVE_INIT_PARAM );
    add(slider);
  }

  public void start() {
    // get a handle to the GraphIT applet; loop waits for GraphIT applet to load
  	do {
       try {
  	      graphITHandle = getAppletContext().getApplet("GraphIT");
  	   }
       catch (NullPointerException e) { };
	}
	while(graphITHandle == null);
  }

  public void stop() {
    texplorer = null;                   // To avoid reusing a reference to an outdated TE
  }                                     // object if the HTML page is revisited (e.g., by doing
                                        // a back/forward sequence in the browser).  If an outdated
                                        // reference is used the browser may crash.  Seems to
                                        // affect NN the most.

  // Clean up when applet exits to aid garabage collection
  public void destroy() {
	slider           = null;
	graphITHandle    = null;
	techexplorerDisp = null;
  }

  public String getAppletInfo() {
    return "GraphITControl (named " + getParameter("name") + ") by A. Diaz, B. Trager, R. Sutor";
  }
 
  public void updateTEDisplay( ) {
    int n = slider.getSliderLoc();
	String nStr = "";
	if (n != 1) nStr += n;				// To avoid displaying 1x

	techexplorerDisp = "\\pagecolor{white}\\colorbox{white}{Select: "   +
	   "\\makebox[1.8in][r]{\\color{black}";

    if ( curveID == TrigCurve.SINCURVE ) {
      techexplorerDisp +=
	      "\\begin{eqnarray}" +
          "\\color{red}y & \\color{red}= & \\color{red}\\sin(" + nStr + "x)\\\\" +
          "            y &             = & \\cos(x)" +
	      "\\end{eqnarray}}}";
	}
	if ( curveID == TrigCurve.COSCURVE ) {
      techexplorerDisp +=
	      "\\begin{eqnarray}" +
	      "            y &             = & \\sin(x)\\\\" +
	      "\\color{red}y & \\color{red}= & \\color{red}\\cos(" + nStr + " x)\\\\" +
	      "\\end{eqnarray}}}";
	}

    // Wait, if necessary, until the html page has been loaded and texplorer has been initialized.
    while(texplorer == null || !texplorer.isReady()) {
       try {
         Thread.sleep(50);
       } 
       catch (InterruptedException e) { };
    }

    texplorer.reloadFromTeXString( techexplorerDisp );				// Redisplay the panel
  }

  public void updateAll( ) {
    updateTEDisplay();
    ((GraphIT)graphITHandle).setParam( slider.getSliderLoc() );	    // Update curve definition
    ((GraphIT)graphITHandle).setCurve( curveID );
    ((GraphIT)graphITHandle).repaint( );							// Regraph curve
  }

  // implementation of the MouseListener interface
  public void mouseClicked( MouseEvent e ) { }
  public void mouseEntered( MouseEvent e ) { }
  public void mouseExited( MouseEvent e )  { }
  public void mousePressed( MouseEvent e ) { }
  public void mouseReleased( MouseEvent e ) {
    int y = e.getY();					// Get y coordinate of mouse click
    if (y*20 < 11*teWindowHeight){		// Since y coordinate is at bottom of the cursor, a better
      curveID = TrigCurve.SINCURVE;     // feel is obtained by letting y be a little more than
    }									// 1/2.
	if (y*20 >= 11*teWindowHeight){
	  curveID = TrigCurve.COSCURVE;
	}
    updateAll( );
  }
}										// end class GraphITControl

class Slider extends Panel {
  private int     sliderLoc = 0;
  private int     value     = 0;

  public Slider( int sliderLoc ) {
    this.sliderLoc = sliderLoc;
  }

  public int getSliderLoc( ) {
    return sliderLoc;
  }

  public void update(Graphics g) {		// Override update() to eliminate repainting the
    paint(g);							// background to help control flashing of the
  }										// slider
 	
  public void paint(Graphics g) {
    Dimension d = this.size();
    Image          offImage          = null;
    Graphics       offGraphics       = null;

    //Create the offscreen graphics context
    offImage = createImage(d.width, d.height);
    offGraphics = offImage.getGraphics();
    setBackground(Color.lightGray);                    // Set background color for this component

    // Create image off screen to help control flashing
	offGraphics.setColor(Color.lightGray.darker());	   // Create recessed box to hold 
	offGraphics.drawRect(2, 2, d.width-4, d.height-4); // slider bar.  Draw broader border
	offGraphics.drawRect(1, 1, d.width-2, d.height-2); // to enhance 3-dim'l effect
	offGraphics.drawRect(0, 0, d.width-3, d.height-3);
   	offGraphics.setColor(Color.lightGray.darker());    // Set color of slider bar and draw it
   	offGraphics.fill3DRect(sliderLoc, 4, d.height/3-1, d.height-9, true);
   	offGraphics.fill3DRect(sliderLoc-1, 3, d.height/3+1, d.height-7, true);

    //Paint the image onto the screen.
    g.drawImage(offImage, 2, 2, this);
    offGraphics.dispose();                              // Dispose for efficiency
    offImage.flush();
  }

  private void setSliderLoc(int loc) {
    Dimension d = this.size();

    if ( loc >= 0 && loc < d.width - d.height/3-1 ) {
	  sliderLoc = loc;
	}
	else if ( loc < 0 ) {
	  sliderLoc = 0;
	}
	else {
	  sliderLoc = d.width - d.height/3-1;
	}
	repaint();
  }

  // Event handlers for Sliders
  public boolean mouseDown(Event evt, int x, int y) {
    setSliderLoc(x);
	((GraphITControl)getParent()).updateAll();
	return true;
  }

  public boolean mouseDrag(Event evt, int x, int y) {
    setSliderLoc(x);
	((GraphITControl)getParent()).updateAll();
    return true;
  }
}
