

import java.awt.event.*;
import javax.swing.*;
import com.genlogic.*;

//////////////////////////////////////////////////////////////////////////
public class GlgRobotArmDemo extends GlgJBean implements ActionListener
{
   //////////////////////////////////////////////////////////////////////////
   // The main demo class
   //////////////////////////////////////////////////////////////////////////
   static final long serialVersionUID = 0;

   static final int NUM_ELBOWS = 7;
   boolean
     IsReady = false,
     AutoUpdate = true,
     WireFrame = false;
   GlgAnimationValue elbow_array[] = new GlgAnimationValue[ NUM_ELBOWS ];

   Timer timer = null;

   //////////////////////////////////////////////////////////////////////////
   public GlgRobotArmDemo()
   {
      super();
      SetDResource( "$config/GlgAntiAliasing", 1. );  // Enable antialiasing
   }

   //////////////////////////////////////////////////////////////////////////
   // Starts the update timer
   //////////////////////////////////////////////////////////////////////////
   public void ReadyCallback()
   {
      if( GetJavaLog() )
        PrintToJavaConsole( "Debug: Ready\n" );

      super.ReadyCallback();

      InitializeArrays();
      
      WireFrame = false;
      SetWireFrame();

      if( timer == null )
      {
         timer = new Timer( 30, this );
         timer.setRepeats( true );
         timer.start();
      }

      IsReady = true;      
   }

   //////////////////////////////////////////////////////////////////////////
   // For use as a stand-alone java demo
   //////////////////////////////////////////////////////////////////////////
   public static void main( final String arg[] )
   {
      SwingUtilities.
        invokeLater( new Runnable(){ public void run() { Main( arg ); } } );
   }

   //////////////////////////////////////////////////////////////////////////
   public static void Main( final String arg[] )
   {
      class DemoQuit extends WindowAdapter
      {
         public void windowClosing( WindowEvent e ) { System.exit( 0 ); }
      } 

      JFrame frame = new JFrame();

      frame.setResizable( true );
      frame.setSize( 600, 450 );
      frame.setLocation( 20, 20 );

      GlgRobotArmDemo robot_arm = new GlgRobotArmDemo();      
      frame.getContentPane().add( robot_arm );

      frame.addWindowListener( new DemoQuit() );
      frame.setVisible( true );

      // Setting the viewport triggers the ReadyCallback which starts
        // updates
      robot_arm.SetViewport( GlgObject.LoadWidget( "robot_arm.glg",
                                                  GlgObject.FILE ) );
   }

   //////////////////////////////////////////////////////////////////////////
   public void UpdateRobotArm()
   { 
      int i;

      if( AutoUpdate )
      {
         // Calculate and set new resource values
         // Different elbows of the arm are named "s0" - "s6" in the drawing.
         // The controlling parameters of elbows' rotation transformations
         // are named "Value". 

         // Update all seven elbows of the robot arm
         for( i=0; i < NUM_ELBOWS; ++i )
           elbow_array[ i ].Iterate();

         Update();   // Show changes
      }
   }

   //////////////////////////////////////////////////////////////////////////
   public void StartUpdate()
   {
      AutoUpdate = true;
   }

   //////////////////////////////////////////////////////////////////////////
   public void StopUpdate()
   {
      AutoUpdate = false;
   }

   //////////////////////////////////////////////////////////////////////////
   public void ToggleWireFrame()
   {
      WireFrame = !WireFrame;
      SetWireFrame();
   }

   //////////////////////////////////////////////////////////////////////////
   void SetWireFrame()
   {
      SetDResource( "robot_area/robot_arm/ZSort", WireFrame ? 0. : 1. );
      SetDResource( "robot_area/fill_type", WireFrame ? 1. : 3. );
      Update();
   }

   //////////////////////////////////////////////////////////////////////////
   void InitializeArrays()
   {
      // Initilize simulation controlling parameters
      elbow_array[ 0 ] =
         new GlgAnimationValue( this, GlgAnimationValue.SIN,
                                0,  70, -0.75, 0.75, "s0/Value" );
      elbow_array[ 1 ] =
         new GlgAnimationValue( this, GlgAnimationValue.SIN,
                                0,  60,  0.75, 0.75, "s1/Value" );
      elbow_array[ 2 ] =
         new GlgAnimationValue( this, GlgAnimationValue.SIN,
                                0, 200,  0.,   1.,   "s2/Value" );
      elbow_array[ 3 ] =
         new GlgAnimationValue( this, GlgAnimationValue.SIN,
                                0, 150,  0.,   1.,   "s3/Value" );
      elbow_array[ 4 ] =
         new GlgAnimationValue( this, GlgAnimationValue.SIN,
                                0,  30,  0.,   1.,   "s4/Value" );
      elbow_array[ 5 ] =
         new GlgAnimationValue( this, GlgAnimationValue.SIN,
                                0, 100,  0.,   1.,   "s5/Value" );
      elbow_array[ 6 ] =
         new GlgAnimationValue( this, GlgAnimationValue.SIN,
                                0,  20,  0.,   1.,   "s6/Value" );
   }

   //////////////////////////////////////////////////////////////////////////
   // Stops updates when used as an applet.
   //////////////////////////////////////////////////////////////////////////
   public void stop()
   {
      if( timer != null )
      {
         timer.stop();
         timer = null;
      }

      super.stop();
   }

   //////////////////////////////////////////////////////////////////////////
   // ActionListener method to use the bean as update timer's ActionListener.
   //////////////////////////////////////////////////////////////////////////
   public void actionPerformed( ActionEvent e )
   {
      if( timer != null )
        UpdateRobotArm();
   }

   //////////////////////////////////////////////////////////////////////////
   // Inner class for a Runnable interface.
   // Provides an interface between JavaScript and Java: invokes applet's 
   // methods in a synchronous way as required by Swing.
   //////////////////////////////////////////////////////////////////////////
   class GlgBeanRunnable implements Runnable
   {
      GlgRobotArmDemo bean;
      String request_name;
      int value;

      public GlgBeanRunnable( GlgRobotArmDemo bean_p, 
                             String request_name_p, int value_p )
      {
         bean = bean_p;
         request_name = request_name_p;
         value = value_p;
      }

      public void run()
      {
         if( request_name.equals( "StartUpdate" ) )
           bean.StartUpdate();
         else if( request_name.equals( "StopUpdate" ) )
           bean.StopUpdate();
         else if( request_name.equals( "ToggleWireFrame" ) )
           bean.ToggleWireFrame();
         else
           PrintToJavaConsole( "Invalid request name: " + 
                              request_name + "\n" );
      }
   }

   //////////////////////////////////////////////////////////////////////////
   // Provides an interface between JavaScript and Java: invokes applet's 
   // methods in a synchronous way as required by Swing.
   //////////////////////////////////////////////////////////////////////////
   public void SendRequest( String request_name, int value )
   {
      GlgBeanRunnable runnable = 
        new GlgBeanRunnable( this, request_name, value );

      SwingUtilities.invokeLater( runnable );
   }
}

