/* SramApplet.java 
 *
 * simple CMOS-style demonstration of the 6T SRAM cell using jfig
 *
 * 24.06.03 - Java version for applet use (instead of Jython script)
 *
 */

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;

import jfig.canvas.*;
import jfig.objects.*;
import jfig.gui.JModularEditor;

public class SramApplet extends  Applet{
        

  public final static int DATA_IN      = 0x8;
  public final static int WORDLINE     = 0x4;
  public final static int WRITE_ENABLE = 0x2;

  public final static Color VCC        = Color.red;
  public final static Color GND        = Color.blue;
  public final static Color Z          = Color.orange;
  public final static Color OFF        = Color.black;

 
  FigAttribs     attribs;
  FigParser      parser;
  FigObjectList  objectList; 
  FigSwingCanvas objectCanvas;

  int             state = 0;

 
  public SramApplet() {
    super();
System.out.println( "-#- <init>" );
  }


  public void init() {
    attribs    = new FigAttribs();
    objectList = new FigObjectList();
    parser     = new FigParser();

    //objectCanvas = new PresentationViewerCanvas();
    objectCanvas = new FigSwingCanvas();
    objectCanvas.showRulers( false );
    objectCanvas.getTrafo().setGridMode( FigTrafo2D.NO_GRID );
    objectCanvas.getTrafo().setSnapRelative( FigTrafo2D.NO_SNAP );
    //objectCanvas.getTrafo().set_zoom( Double.valueOf(zoom).doubleValue() );
    objectCanvas.setObjectEnumerator( new ObjectEnumerator() );
    objectCanvas.getComponent().addMouseListener( new MouseHandler() );

    this.setLayout( new BorderLayout() );
    this.add( "Center", objectCanvas.getComponent() );
    // this.add( "South", new Button( "Hugo" ));

    parser.setObjectPainter( objectCanvas );
    try {
      String filename = "sram.fig";
      URL url = new URL( getCodeBase(), filename );
      InputStream inputStream = url.openStream();

      parser.setFilenameAndType( url.toExternalForm(), "URL" );
      parser.parse_fig_file_not_threaded( inputStream,
               true, false, false, // toplevel, compound, merge
               attribs,
               objectCanvas.getTrafo(),
               objectList );
System.out.println( "-#- parser ok, repainting" );
      objectCanvas.doFullRedraw();
      // objectCanvas.doZoomFit(); // does not work...
    }
    catch( Throwable t ) {
System.out.println( "-F- " + t );
t.printStackTrace();
    }

    //editor.doParseFile( "6T-sram.fig", false ); // don't merge

    state = DATA_IN | WRITE_ENABLE | WORDLINE;
    update();
    state = state ^ DATA_IN;
    update();
  }


  public FigObject findObjectViaComment( String name ) {
    for( Enumeration e=objectList.elements(); e.hasMoreElements(); ) {
      FigObject tmp = (FigObject) e.nextElement();
      if (name.equals(tmp.getComment())) return tmp;
    }
    return null;
  }



  public void setColor( String name, Color color ) {
    FigObject target = findObjectViaComment( name );
    if (target == null) return;

    if (target instanceof FigCompound) {
      FigAttribs attr = target.getAttributes();
      attr.lineColor = color;
      attr.fillColor = color;
      attr.updateLineColorMask = true;
      attr.updateFillColorMask = true;
      target.update( attr );
    }
    else {
      FigAttribs attr = target.getAttributes();
      attr.lineColor = color;
      target.setAttributes( attr );
    }
  }

  public void showTran( String name, Color color ) {
    FigObject target = findObjectViaComment( name );
    if (target == null) return;

    FigAttribs attr = target.getAttributes();
    if (color == VCC) {
      attr.lineColor = VCC;
      attr.fillColor = VCC;
      attr.fillStyle = FigAttribs.SOLID_FILL;
    }
    else if (color == GND) {
      attr.lineColor = GND;
      attr.fillColor = GND;
      attr.fillStyle = FigAttribs.SOLID_FILL;
    }
    else if (color == Z) {
      attr.lineColor = Z;
      attr.fillColor = Z;
      attr.fillStyle = FigAttribs.SOLID_FILL;
    }
    else if (color == OFF) {
      attr.lineColor = OFF;
      attr.fillColor = OFF;
      attr.fillStyle = FigAttribs.NO_FILL;
    }
    target.setAttributes( attr );
  }


  public void update() {
    boolean data_in = ((state & DATA_IN) != 0);
    boolean write   = ((state & WRITE_ENABLE) != 0);
    boolean enable  = ((state & WORDLINE) != 0);

    if (data_in) {
      setColor( "datain",  VCC  );
      setColor( "ndatain", GND  );
    }
    else {
      setColor( "ndatain", VCC  );
      setColor( "datain",  GND  );
    }

    if (enable) { setColor( "wordline", VCC ); }
    else        { setColor( "wordline", GND ); }

    if (write) {
      setColor( "WE",  VCC ); 
      setColor( "nWE", GND );

      if (data_in) {
        setColor( "bit",    VCC ); showTran( "tranD",  VCC );
        setColor( "nbit",   GND ); showTran( "tranND", GND );

        if (enable) { // write data
          state = state | 1;
          setColor( "out12",  VCC ); setColor( "solder12", VCC );
          setColor( "out34",  GND ); setColor( "solder34", GND );

          showTran( "tran1",  VCC );
          showTran( "tran2",  OFF );
          showTran( "tran3",  OFF );
          showTran( "tran4",  GND );

          showTran( "tran5",  VCC );
          showTran( "tran6",  GND );
        }
        else {
          showTran( "tran5",  OFF );
          showTran( "tran6",  OFF );
        }
        
      }
      else {
        setColor( "bit",    GND ); showTran( "tranD",  GND );
        setColor( "nbit",   VCC ); showTran( "tranND", VCC );

        if (enable) { // write data, remember data_in value
          state = state & 0xE;

          setColor( "out12",  GND ); setColor( "solder12", GND );
          setColor( "out34",  VCC ); setColor( "solder34", VCC );

          showTran( "tran1",  OFF );
          showTran( "tran2",  GND );
          showTran( "tran3",  VCC );
          showTran( "tran4",  OFF );

          showTran( "tran5",  GND );
          showTran( "tran6",  VCC );
        }
        else {
          showTran( "tran5",  OFF );
          showTran( "tran6",  OFF );
        }
      }
    }
    else { // not write
      setColor( "WE",  GND ); 
      setColor( "nWE", VCC );
      showTran( "tranD",  OFF );
      showTran( "tranND", OFF );

      if (enable) { // read data
        if ((state & 0x1) != 0) { // 1 stored
          showTran( "tran5", VCC);
          showTran( "tran6", GND );
          setColor( "bit",   VCC ); 
          setColor( "nbit",  GND );
        }
        else { // 0 stored
          showTran( "tran5", GND );
          showTran( "tran6", VCC );
          setColor( "bit",   GND ); 
          setColor( "nbit",  VCC );
        }
      }
      else { // tristate bitlines
          showTran( "tran5", OFF );
          showTran( "tran6", OFF );
          setColor( "bit",   Z   ); 
          setColor( "nbit",  Z   );
      }
    }

// System.out.println( "-read: state= " + state );
    objectCanvas.doFullRedraw();
  }


  public void toggleDataIn() {
    state = state ^ DATA_IN;
    update();
  } 


  public void toggleWordlineEnable() {
    state = state ^ WORDLINE;
    update();
  }


  public void toggleWriteEnable() {
    state = state ^ WRITE_ENABLE;
    update();
  }
  

  public class MouseHandler extends MouseAdapter {

    public void mousePressed( MouseEvent event ) {
      FigTrafo2D trafo = objectCanvas.getTrafo();
      Point         wp = trafo.getWorldCoords( event.getX(), event.getY() );
      // System.out.println( wp );

      if      ((wp.x <     0) || (wp.x >= 2500)) return; // out of bounds
      else if ((wp.y >=    0) && (wp.y <= 2800)) toggleDataIn();
      else if ((wp.y >= 2800) && (wp.y <= 5000)) toggleWordlineEnable();
      else if ((wp.y >= 5000) && (wp.y <= 6600)) toggleWriteEnable();
      else                                       return;
    } 
  }  // end inner class MouseHandler





  public class ObjectEnumerator implements FigDrawableEnumerator {

    public Enumeration getDrawableObjects() {
      return objectList.elements();
    }

    public FigDrawable getTmpObject() {
      return null;
    }
  } // end inner class ObjectEnumerator






  public static void main( String argv[] ) {
    

  }




}
