// (c) MIT 2003.  All rights reserved.

// -*-Mode: Java-*- 
// SimulateSurface.java -- 
// Author: Christine Alvarado <calvarad@ai.mit.edu> 
// Maintainer: Christine Alvarado <calvarad@ai.mit.edu> 
// Version: $id:$
// Created: <Mon Apr  5 19:29:30 1999> 
// Time-stamp: <2002-04-10 19:27:05 moltmans> 
// Keywords: 
package rec.simulate;

import rec.sys.*;
import rec.core.widgets.*;
import rec.meche.WMSpring;
import rec.meche.WMForce;
import rec.geo.*;
import java.util.*;
import rec.simulate.widgets.*;
import rec.multi.MultiModal;

public class SimulateSurface extends Surface
{
  public SimulateSurface()
  {
    super();
    // in the future, this assignment will be done dynamically
    m_WidgetPool = getSimRegistry();
//      m_WidgetPool = new WMSimulatorRegistry("WMDebug.wbs");
  }

  protected SimulatorRegistry getSimRegistry()
  {
    return new WMSimulatorRegistryDDE();
  }

  public WSimRectangle makeSimRect( WRectangle r )
  {
    return m_WidgetPool.makeRectangle( r );
  }

  public WSimQuadrilateral makeSimQuad( WQuadrilateral q )
  {
    return m_WidgetPool.makeQuadrilateral( q );
  }

  public WSimCircle makeSimCircle( WCircle c )
  {
    return m_WidgetPool.makeCircle( c );
  }

  public WSimSpring makeSimSpring( WMSpring spr )
  {
    return m_WidgetPool.makeSpring( spr );
  }

  public WSimTriangle makeSimTriangle( WTriangle t )
  {
    return m_WidgetPool.makeTriangle( t );
  }

  public WSimPolygon makeSimPolygon( PolygonInfo pi )
  {
    return m_WidgetPool.makePolygon( pi );
  }
  
  public WSimPolygon makeSimPolygon( WPolygon poly )
  {
    return m_WidgetPool.makePolygon( poly );
  }

  public WSimForce makeSimForce( WMForce f )
  {
    return m_WidgetPool.makeForce( f );
  }

  public WSimAnchor makeSimAnchor( GPoint center, double size ) 
  {
    return m_WidgetPool.makeAnchor( center, size );
  }

  public WSimMotor makeSimMotor( GPoint center ) 
  {
    return m_WidgetPool.makeMotor( center );
  }  

  public WSimGear makeSimGear( WCircle circle ) 
  {
    return m_WidgetPool.makeGear( circle );
  }  

  public WSimGearTrain makeSimGearTrain(WSimGear[] gears,
					WSimGearTrain[] trains, 
					WSimGear newGear, 
					boolean singleCircles)
  {
    WSimGearTrain train =  m_WidgetPool.makeGearTrain( gears,trains, newGear, 
						       singleCircles );

    train.setSurface(this);
    return train;
  }  
    
  public WSimRotationalSpring makeRotationalSpring (GToolkitSpiral spiral)
  {
    return m_WidgetPool.makeRotationalSpring( spiral );
  }   
 
  public WSimRotationalDamper makeRotationalDamper (GPoint center)
  {
    return m_WidgetPool.makeRotationalDamper( center );
  }
  
  public WSimSpringDamper makeSimSpringDamper(GSegment base, boolean damperup)
  {
    return m_WidgetPool.makeSpringDamper(base, damperup);
  }

  public WSimTorque makeSimTorque(WToolkitArc arc, WLine line1, WLine line2, boolean clockwise)
  {
    return m_WidgetPool.makeTorque(arc, line1, line2, clockwise);
  }

  public WSimPinJoint makeSimPinJoint( WSimCircle c ) 
  {
    return m_WidgetPool.makePinJoint( c );
  }

  public WSimDamper makeSimDamper( GSegment s ) 
  {
    return m_WidgetPool.makeDamper( s );
  }
  
  public WSimRod makeSimRod( WLine l )
  {
    return m_WidgetPool.makeRod( l );
  }

    public WSimRope makeSimRope( WComplex c )
    {
	return m_WidgetPool.makeRope( c );
    }

    public WSimRope makeSimRope( WLine l )
    {
	return m_WidgetPool.makeRope( l );
    }

  public WSimPulley makeSimPulley( List wheels, List ropes )
  {
    return m_WidgetPool.makePulley( wheels, ropes );
  }

  // the user is done drawing, so take all the stuff on the surface which
  // are not simulatable parts, and turn them into simulatable stuff
  // if necesary.  I am not using a "Mutator" class here (even though I
  // thought that i might) since we have a special surface which can simply
  // mutate itself
  // For now, anything which could be more than one simulatable object
  // is put here.  This includes rectangles, squares (because they are 
  // represented as rectangles), circles, and lines (which are not part of 
  // shapes or parts when the run button is clicked).
  public void finish()
  {
    // get all the objects on the surface
    Iterator it = getWidgetsIterator();
    while ( it.hasNext() ) {
      Widget vw = (Widget)it.next();
      
      
      if ( vw instanceof WRectangle ) {
	removeWidget( vw );
	addWidget( makeSimRect( (WRectangle)vw ) );
      }
      if ( vw instanceof WCircle ) {
	removeWidget( vw );
	addWidget( makeSimCircle( (WCircle)vw ) );
      }
      if ( vw instanceof WLine ) {
	removeWidget( vw );
	addWidget( makeSimRod( (WLine)vw ) );
      }
    }
  }

  public void findAttachments() 
  {
    m_WidgetPool.attach( this );
    m_WidgetPool.setGravity( this );
  }

  public boolean isGravityOn() 
  {
    return m_WidgetPool.isGravityOn();
  }


  /**
   * Because of the bug with ViaVoice (it locks up some low level
   * windows something so you can't start WorkingModel while it is
   * running), we shut down ViaVoice and then start it up after
   * WorkingModel is started.
   **/
  public void simulate()
  {
    // shutdown ViaVoice (if it is running)
    if (getSystemProperty("multimodal", "").equalsIgnoreCase("on") ) {
      MultiModal mm = getMultiModal();
      if (mm != null) mm.stopViaVoice();
    }
    
    findAttachments();
    m_WidgetPool.load( this );

    // restart ViaVoice (if it was running)
    if (getSystemProperty("multimodal", "").equalsIgnoreCase("on") ) {
      MultiModal mm = getMultiModal();
      if (mm != null) mm.restartViaVoice();
    }
  }

  public void shutdown() 
  {
    m_WidgetPool.shutdown();
  }

  protected SimulatorRegistry m_WidgetPool;

}
