import java.lang.*;
import java.awt.*;
import java.applet.*;


/*
 *      Purpose: The main program of the applet
 */
public class ControlStructure extends Applet { 
  Image img, img2; ControlPanel ControlWin; 
  TextArea CodeWinEdit, CodeWinDisplay;
  Panel InputWin;
  ImageScrollPanel ScrolledDiagramWin;


  public void init() {

   img = createImage(1500, 1500);

   setLayout(new BorderLayout());

   Panel Contain = new Panel();

   ScrolledDiagramWin = new ImageScrollPanel(img, 1300, 1300);
   ScrolledDiagramWin.reshape(0, 0, 550, 300);


   /*
    *  input code textarea (Editable)
    */
   CodeWinEdit = new TextArea("while (x > 0) {\n" +
                          "  x++;\n" +
                          "  printf(\"x : %d\\n\");\n" +
                          "  do x--; while (x > 0);\n" +
                          "  if (x>0)\n" +
                          "   x=1;\n" +
			  "  else\n" +
			  "   x=0;\n" +
                          "}\n");
   CodeWinEdit.resize(225, 200);
   CodeWinEdit.setBackground(Color.gray);
   CodeWinEdit.setEditable(true);

   Panel panel1 =  new Panel();
   panel1.setLayout(new BorderLayout());
   panel1.add("North", new Label("Input Code (Editable)", Label.CENTER));
   panel1.add("Center", CodeWinEdit);

   /*
    *  simplified code textarea (Non-editable)
    */
   CodeWinDisplay = new TextArea("", 15, 10);
   CodeWinDisplay.resize(225, 200);
   CodeWinDisplay.setBackground(Color.gray);
   CodeWinDisplay.setEditable(false);

   Panel panel2 =  new Panel();
   panel2.setLayout(new BorderLayout());
   panel2.add("North", new Label("Simplified Code (Non-editable)", Label.CENTER));
   panel2.add("Center", CodeWinDisplay);


   Panel CodeWin = new Panel();
   CodeWin.setLayout(new GridLayout(1, 2));
   CodeWin.add(panel1);
   CodeWin.add(panel2);

   ControlWin = new ControlPanel(CodeWinEdit, CodeWinDisplay, 
				 ScrolledDiagramWin);

   ScrolledDiagramWin.setControlPanel(ControlWin);


   add("North", ControlWin);
   add("Center", ScrolledDiagramWin);
   add("South", CodeWin);

  }

}	/* End Class ControlStructure */



/*
 *	Purpose: the control panel
 */
class ControlPanel extends Panel {
  TextArea t, d;
  ImageScrollPanel fd;
  public Button ConvertButton, ClearButton, RunButton;
  public ProgramObj program=null;

  public ControlPanel(TextArea input, TextArea dpy, 
		      ImageScrollPanel FlowDiagram) {
    t = input;
    d = dpy;
    fd = FlowDiagram;
    setLayout(new FlowLayout(FlowLayout.LEFT));
    ConvertButton = new Button("Convert !");
    ClearButton = new Button("Clear");
    RunButton = new Button(" Run ");
    add(ConvertButton);
    add(ClearButton);
    add(RunButton);
    RunButton.disable();
  }

  public boolean action(Event e, Object arg) {
    if (e.target instanceof Button) {

      String str = ((Button)(e.target)).getLabel();
      if (str.equals("Convert !")) {
        StringBuffer s = new StringBuffer();
        
        Parse Parsing = new Parse(t.getText());
        program = Parsing.go();

        if (program == null) {
          System.err.println("Error: convert empty program!");
        } else if (Parsing.ErrStatus) {
          MsgDialog ErrMsg = new MsgDialog("Error", Parsing.ErrStr);
          ErrMsg.show();
        } else {

          fd.clear();
          fd.ImgGc.setColor(Color.black);
          program.draw(70, 50, fd.ImgGc);
          fd.redraw();

          program.print(s, 0);
          String string = s.toString();
          d.setText(string);

          RunButton.enable();
        }

      } else if (str.equals("Clear")) {
        t.setText("");
        d.setText("");
        fd.clear();
        fd.redraw();
        RunButton.disable();
      } else if (str.equals(" Run ")) {
        RunFlowChart Run = new RunFlowChart(fd, d, program, this);       
        Thread t = new Thread(Run);
        t.start();
        ConvertButton.disable();
        ClearButton.disable();
        RunButton.disable();
      } 

    }

    return true;
  }

}	/* End Class ControlPanel */



/*
 *	Purpose: the scrolling drawing area containing the flowchart
 */
class ImageScrollPanel extends ScrollPanel {
  private Image img;
  public Graphics ImgGc;
  public int width, height;
  ControlPanel cp;

  public ImageScrollPanel(Image i, int w, int h) {
    super(i, w, h);

    img = i;
    ImgGc = img.getGraphics();
    width = w;
    height = h;
    clear();
  }

  public void setControlPanel(ControlPanel p) { cp = p; }

  public boolean mouseDown(Event e, int x, int y) { 
    if (cp.program == null) return true;
    int posx = x+horiz.getValue();
    int posy = y+vert.getValue();
    cp.program.CheckInside(posx, posy);
    return true;
  }

  public void clear() {
    ImgGc.setColor(Color.white);
    ImgGc.fillRect(0, 0, width, height);
  }

  public void redraw() { 
    super.setImage(img, width, height);
  }

}	/* End Class ImageScrollPanel */



/*
 *	Purpose: Dialog showing the content of condition and statements
 */
class ShowContentDialog extends Frame {
  Button bokay;
  TextArea ta;
  String text, head;

  public ShowContentDialog() {
    super();

    setBackground(Color.white);
    setForeground(Color.black);
    setLayout(new BorderLayout());
    bokay = new Button("OK");
    Panel panel = new Panel();
    panel.add(bokay);

    add("Center", ta = new TextArea(""));
    add("South", panel);
    resize(300, 200);

    ta.setEditable(false);
  }

  public void setHeading(String str) { setTitle(str); }

  public void setText(String str) { ta.setText(str); }

/*  public void paint(Graphics g) {
    super.paint(g);
    FontMetrics fm = g.getFontMetrics();
    g.drawString(text,
        (250-fm.stringWidth(text))/2, 80);
  } */

  public boolean action(Event e, Object arg) {
    if (e.target instanceof Button) {
      hide();
    }
    return true;
  }

}       /* End Class ShowContentDialog */





/*
 *	Purpose: Message Dialog
 */
class MsgDialog extends Frame {
  Button bokay;
  String text;

  public MsgDialog(String heading, String msg) {
    super(heading);
    setText(msg);

    setBackground(Color.gray);
    setForeground(Color.white);
    setLayout(new BorderLayout());
    bokay = new Button("OK");
    Panel panel = new Panel();
    panel.add(bokay);

    add("South", panel);
    resize(250, 150);
  }

  public void setText(String str) { text = new String(str); }

  public void paint(Graphics g) {
    super.paint(g);
    FontMetrics fm = g.getFontMetrics();
    g.drawString(text,
	(250-fm.stringWidth(text))/2, 80);
  }

  public boolean action(Event e, Object arg) {
    if (e.target instanceof Button) {
      hide();
    }
    return true;
  }

}	/* End Class MsgDialog */



/*
 *	Purpose: Dialog to ask the user the truth value of a condition
 */
class ConditionDialog extends Frame {
  Button btrue, bfalse;
  RunFlowChart run;
  String text;

  public ConditionDialog(RunFlowChart r) {
    super("Runing the Program");

    run = r;
    setBackground(Color.gray);
    setForeground(Color.white);
    setLayout(new BorderLayout());

    btrue = new Button("True");
    bfalse = new Button("False");
    Panel panel = new Panel();
    panel.add(btrue);
    panel.add(bfalse);

    add("South", panel);
    resize(250, 150);
  }

  public void setText(String str) { text = new String(str); }

  public void paint(Graphics g) {
    super.paint(g);
    FontMetrics fm = g.getFontMetrics();
    g.drawString(text,
	(250-fm.stringWidth(text))/2, 80);
  }

  public boolean action(Event e, Object arg) {
    if (e.target instanceof Button) {
      String str = ((Button)(e.target)).getLabel();
      hide();

      if (str == "True")
        run.ConditionValue = true;
      else
        run.ConditionValue = false;

      run.t.resume();
    }
    return true;
  }

}	/* End Class ConditionDialog */



/*
 *	Purpose: Dialog to ask the user to continue the execution of the flow
 *               chart program
 */
class NextDialog extends Frame {
  Button bnext;
  RunFlowChart run;
  String text;

  public NextDialog(RunFlowChart r) {
    super("Runing the Program");

    run = r;

    setBackground(Color.gray);
    setForeground(Color.white);
    setLayout(new BorderLayout());
    bnext = new Button("Next");
    Panel panel = new Panel();
    panel.add(bnext);

    add("South", panel);
    resize(250, 150);
  }

  public void setText(String str) { text = new String(str); }

  public void paint(Graphics g) {
    super.paint(g);
    FontMetrics fm = g.getFontMetrics();
    g.drawString(text,
	(250-fm.stringWidth(text))/2, 100-fm.getHeight());
    g.drawString("Press next to continue", 
	(250-fm.stringWidth("Press next to continue"))/2, 100);
  }

  public boolean action(Event e, Object arg) {
    if (e.target instanceof Button) {
      hide();
      run.t.resume();
    }
    return true;
  }

}	/* End Class NextDialog */


/*
 *	Purpose: A simple dialog displaying a text string and a okay button
 */
class OkayDialog extends Frame {
  Button bokay;
  RunFlowChart run;
  String text;

  public OkayDialog(RunFlowChart r) {
    super("Runing the Program");

    run = r;

    setBackground(Color.gray);
    setForeground(Color.white);
    setLayout(new BorderLayout());
    bokay = new Button("OK");
    Panel panel = new Panel();
    panel.add(bokay);

    add("South", panel);
    resize(250, 150);
  }

  public void setText(String str) { text = new String(str); }

  public void paint(Graphics g) {
    super.paint(g);
    FontMetrics fm = g.getFontMetrics();
    g.drawString(text,
	(250-fm.stringWidth(text))/2, 80);
  }

  public boolean action(Event e, Object arg) {
    if (e.target instanceof Button) {
      hide();
      run.t.resume();
    }
    return true;
  }

}	/* End Class OkayDialog */


/*
 *	Purpose: running the program in the flow chart
 */
class RunFlowChart implements Runnable {
  ProgramObj program;
  ImageScrollPanel flowchart;
  ControlPanel control;
  ConditionDialog conditionD;
  NextDialog nextD;
  OkayDialog okayD;
  public Thread t;
  public boolean ConditionValue = false;
  TextArea dpy;
  

  public RunFlowChart(ImageScrollPanel fc, TextArea d,  ProgramObj p, ControlPanel cp) {
    program = p;
    flowchart = fc;
    control = cp;
    dpy = d;

    conditionD = new ConditionDialog(this);
    nextD = new NextDialog(this); 
    okayD = new OkayDialog(this);
  }

  public void run() {
    go(program);
  }

  void redraw() {
    flowchart.clear();
    flowchart.ImgGc.setColor(Color.black);
    program.draw(70, 50, flowchart.ImgGc);
    flowchart.redraw();
  }
  
  void go(ControlObj obj) {

    if (obj == null) return;

    if (obj instanceof ProgramObj) {

      obj.active = true;
      ((ProgramObj)obj).begin = true;
      redraw();

      t = Thread.currentThread();
      nextD.setText("The beginning of the program");
      nextD.show();
      t.suspend();

      obj.active = false;
      go(((ProgramObj)obj).content);

      obj.active = true;
      ((ProgramObj)obj).begin = false;
      redraw();
      t = Thread.currentThread();
      dpy.select(0, 0);
      okayD.setText("The end of the program");
      okayD.show();
      t.suspend();
      obj.active = false;

      control.ConvertButton.enable();
      control.ClearButton.enable();
      control.RunButton.enable();

    } else if (obj instanceof StmtList) {

      go(((StmtList)obj).CodeSeg);
      go(((StmtList)obj).next);

    } else if (obj instanceof StatementObj) {

      obj.active = true;
      redraw();

      t = Thread.currentThread();
      dpy.select(obj.SelectStart, obj.SelectEnd);
      nextD.setText("Now Statements "+((StatementObj)obj).StatementNo+" is executing....");
      nextD.show();
      t.suspend();
      obj.active = false;

    } else if (obj instanceof IfObj) {

      obj.active = true;
      redraw();

      t = Thread.currentThread();
      dpy.select(obj.SelectStart, obj.SelectEnd);
      conditionD.setText("The truth value of Condition "+((IfObj)obj).ConditionNo+"?");
      conditionD.show();
      t.suspend();
      obj.active = false;
       if (ConditionValue == true)
         go(((IfObj)obj).yes);
       else
         go(((IfObj)obj).no);


    } else if (obj instanceof WhileObj) {

      while (true) {

       obj.active = true;
       redraw();

       t = Thread.currentThread();
       dpy.select(obj.SelectStart, obj.SelectEnd);
       conditionD.setText("The truth value of Condition "+((WhileObj)obj).ConditionNo+"?");
       conditionD.show();
       t.suspend();
       obj.active = false;
       if (ConditionValue == true)
         go(((WhileObj)obj).content);
       else
         break;
      }

    } else if (obj instanceof RepeatObj) {

      do {
       obj.active = false;
       go(((RepeatObj)obj).content);

       obj.active = true;
       redraw();

       t = Thread.currentThread();
       dpy.select(obj.SelectStart, obj.SelectEnd);
       conditionD.setText("The truth value of Condition "+((RepeatObj)obj).ConditionNo+"?");
       conditionD.show();
       t.suspend();
       obj.active = false;
      } while (ConditionValue == true);
    }

  } /* End Method go */

}	/* End Class RunFlowChart */















/************************************************************************

  The following classes are the internal representation of the user inputed 
  program or flowchart.

 ************************************************************************/



class ControlType {
  static int IF=0;
  static int WHILE=1;
  static int REPEAT=2;
  static int STATEMENT=3;
  static int STMTLIST=4;
  static int PROGRAM=5;
}


class UnitInfo {
  Dimension unitsize;
  int up, bottom;

  public UnitInfo(int w, int h, int u, int b) {
    unitsize = new Dimension(w, h);
    up = u;
    bottom = b;
  }

  public UnitInfo() { this(0,0,0,0); } 
}




/*
 * This is the base class of all the nodes in the internal representation of 
 * the flowcharts. There are four main methods need to implement when
 * subclassing it:
 *
 * size() - return the size of this particular instance of the class needed 
 *          in the flow diagram
 * draw() - draw this instance of the class on the flow diagram
 * print() - print the simplified code
 * CheckInside() [optoinal] - if this class has a condition box or statement
 *                            box drawn on the flow diagram, this method check
 *                            whether a point is inside the box
 */
abstract class ControlObj {
  int type;
  Dimension boxsize = new Dimension(90, 40);
  static int hseparation = 20;
  static int vseparation = 40;
  boolean active = false;
  int SelectStart=1, SelectEnd=2;

  public abstract UnitInfo size();
  public abstract void draw(int x, int y, Graphics g);
  public abstract void print(StringBuffer sb, int indentation);
  public abstract boolean CheckInside(int x, int y);


  public Polygon recordCondition(int x, int y) {

    int xarray[] = new int[5];
    int yarray[] = new int[5];

    xarray[0] = x;
    xarray[1] = x+boxsize.width/2;
    xarray[2] = x+boxsize.width;
    xarray[3] = x+boxsize.width/2;
    xarray[4] = x;

    yarray[0] = y+boxsize.height/2;
    yarray[1] = y;
    yarray[2] = y+boxsize.height/2;
    yarray[3] = y+boxsize.height;
    yarray[4] = y+boxsize.height/2;

    Polygon p = new Polygon(xarray, yarray, 5);

    return p;

  }	/* End Method recordCondition() */



  public void drawCondition(int x, int y, int no, Graphics g) {
    int xarray[] = new int[5];
    int yarray[] = new int[5];

    xarray[0] = x; 
    xarray[1] = x+boxsize.width/2;
    xarray[2] = x+boxsize.width; 
    xarray[3] = x+boxsize.width/2;
    xarray[4] = x; 

    yarray[0] = y+boxsize.height/2;
    yarray[1] = y;
    yarray[2] = y+boxsize.height/2;
    yarray[3] = y+boxsize.height;
    yarray[4] = y+boxsize.height/2;

    Polygon p = new Polygon(xarray, yarray, 5);

    if (active) {
      g.setColor(Color.yellow);
      g.fillPolygon(p);
      g.setColor(Color.black);
    }

    g.drawPolygon(p);

/*    g.drawLine(x, y+boxsize.height/2, x+boxsize.width/2, y);
    g.drawLine(x+boxsize.width/2, y, x+boxsize.width, y+boxsize.height/2);
    g.drawLine(x+boxsize.width, y+boxsize.height/2,
		x+boxsize.width/2, y+boxsize.height);
    g.drawLine(x+boxsize.width/2, y+boxsize.height, x, y+boxsize.height/2); */

    g.setColor(Color.red);
    g.drawString("Condition "+Integer.toString(no), x+10, y+25);
    g.setColor(Color.black);
  }

  public void drawDownArrowLine(int x1, int y1, int x2, int y2, Graphics g) {
    int maxy = Math.max(y1, y2);
    int miny = Math.min(y1, y2);
    g.drawLine(x1, y1, x2, y2);
    g.drawLine(x1, miny+(maxy-miny)/2, x1-5, miny+(maxy-miny)/2-5);
    g.drawLine(x1, miny+(maxy-miny)/2, x1+5, miny+(maxy-miny)/2-5);
  }

  public void drawUpArrowLine(int x1, int y1, int x2, int y2, Graphics g) {
    int maxy = Math.max(y1, y2);
    int miny = Math.min(y1, y2);
    g.drawLine(x1, y1, x2, y2);
    g.drawLine(x1, miny+(maxy-miny)/2, x1-5, miny+(maxy-miny)/2+5);
    g.drawLine(x1, miny+(maxy-miny)/2, x1+5, miny+(maxy-miny)/2+5);
  }

  public void drawLeftArrowLine(int x1, int y1, int x2, int y2, Graphics g) {
    int maxx = Math.max(x1, x2);
    int minx = Math.min(x1, x2);
    g.drawLine(x1, y1, x2, y2);
    g.drawLine(minx+(maxx-minx)/2, y1, minx+(maxx-minx)/2+5, y1-5);
    g.drawLine(minx+(maxx-minx)/2, y1, minx+(maxx-minx)/2+5, y1+5);
  }

  public void drawRightArrowLine(int x1, int y1, int x2, int y2, Graphics g) {
    int maxx = Math.max(x1, x2);
    int minx = Math.min(x1, x2);
    g.drawLine(x1, y1, x2, y2);
    g.drawLine(minx+(maxx-minx)/2, y1, minx+(maxx-minx)/2-5, y1-5);
    g.drawLine(minx+(maxx-minx)/2, y1, minx+(maxx-minx)/2-5, y1+5);
  }

}	/* End Class ControlObj */




class StmtList extends ControlObj {
  ControlObj CodeSeg;
  StmtList next;

  public StmtList() { type = ControlType.STMTLIST; }

  public UnitInfo size() {
    UnitInfo tmp = new UnitInfo(0,0,0,0);
    UnitInfo u1 = CodeSeg.size();
    if (next == null) return u1;
    UnitInfo u2 = next.size();

    int lup1 = u1.up;
    int rup1 = u1.unitsize.width - u1.up;
    int lbottom1 = u1.bottom;
    int rbottom1 = u1.unitsize.width - u1.bottom;

    int lup2 = u2.up;
    int rup2 = u2.unitsize.width - u2.up;
    int lbottom2 = u2.bottom;
    int rbottom2 = u2.unitsize.width - u2.bottom;

    tmp.unitsize.height = u1.unitsize.height + u2.unitsize.height;
    tmp.unitsize.width = u1.unitsize.width + u2.unitsize.width
		- Math.min(lbottom1, lup2) - Math.min(rbottom1, rup2);
    if (lbottom1 > lup2) {
      tmp.up = u1.up;
      tmp.bottom = (lbottom1-lup2) + lbottom2;
    } else {
      tmp.up = (lup2-lbottom1) + lup1;
      tmp.bottom = lbottom2;
    }
    
    return tmp;
  }	/* End of size() */


  public boolean CheckInside(int x, int y) {
    if (CodeSeg.CheckInside(x, y) == false) return false;
    if (next != null) return next.CheckInside(x, y);
    return true;
  }


  public void draw(int x, int y, Graphics g) {
    UnitInfo u1 = CodeSeg.size();

    if (next == null) {
      CodeSeg.draw(x, y, g);
    } else {
      UnitInfo u2 = next.size();

      if (u1.bottom > u2.up) {
        CodeSeg.draw(x, y, g);
        next.draw(x+(u1.bottom-u2.up), y+u1.unitsize.height, g);
      } else {
        CodeSeg.draw(x+(u2.up-u1.bottom), y, g);
        next.draw(x, y+u1.unitsize.height, g);
      }
    }
  }	/* End of draw(int, int, Graphics) */


  public void print(StringBuffer sb, int indentation) {
    CodeSeg.print(sb, indentation);
    if (next != null) next.print(sb, indentation);
  }

}	/* End Class StmtList */




class StatementObj extends ControlObj {
  int StatementNo;
  String StatementContent;
  int posx=-1, posy=-1;
  ShowContentDialog dialog = new ShowContentDialog();

  public StatementObj() { type = ControlType.STATEMENT; }

  public UnitInfo size() {
    UnitInfo tmp = new UnitInfo(boxsize.width, boxsize.height+vseparation,
				boxsize.width/2, boxsize.width/2);
    return tmp;
  }

  public boolean CheckInside(int x, int y) {
    if (x < 0) return true;
    if ( (x >= posx && x <= posx+boxsize.width) &&
         (y >= posy && y <= posy+boxsize.height) ) {
/*      System.out.println(StatementContent); */
      dialog.setTitle("Content of Statements "+StatementNo);
      dialog.setText(StatementContent);
      dialog.show();
      return false;
    } else
      return true;
  }

  public void draw(int x, int y, Graphics g) {

    if (active) {
      g.setColor(Color.yellow);
      g.fillRect(x, y, boxsize.width, boxsize.height);
      g.setColor(Color.black);
    }

    posx = x;  posy = y;
    g.drawRect(x, y, boxsize.width, boxsize.height);
    drawDownArrowLine(x+boxsize.width/2, y+boxsize.height, 
		x+boxsize.width/2, y+boxsize.height+vseparation, g);

/*    FontMetrics fm = g.getFontMetrics();
    g.drawString("Statements", 
		x+(boxsize.width-fm.stringWidth("Statements"))/2,
		y+(boxsize.height+fm.getHeight())/2); */

    g.setColor(Color.red);
    g.drawString("Statements "+Integer.toString(StatementNo), x+10, y+25);
    g.setColor(Color.black);
  }

  public void print(StringBuffer sb, int indentation) {
    SelectStart = sb.length()+indentation;
    SelectEnd = SelectStart+("Statments "+StatementNo).length();

    for (int i=0; i<indentation; i++) sb.append(' ');
    sb.append("Statments "+Integer.toString(StatementNo)+"\n");
  }

}	/* End Class StatementObj */




class IfObj extends ControlObj {
  int ConditionNo;
  String ConditionContent;
  Polygon ConditionBox=null;
  ControlObj yes;
  ControlObj no;
  ShowContentDialog dialog = new ShowContentDialog();

  public IfObj() { type = ControlType.IF; }

  public UnitInfo size() {
    UnitInfo tmp = new UnitInfo(0,0,0,0);
    UnitInfo yessize = yes.size();
    UnitInfo nosize;

    if (no == null)
      nosize = new UnitInfo(boxsize.width,0,0,0);
    else
      nosize = no.size();

    Dimension yesd = yessize.unitsize;
    Dimension nod = nosize.unitsize;

    tmp.unitsize.width = yesd.width + nod.width + 2*hseparation;
    tmp.unitsize.height = boxsize.height + Math.max(yesd.height, nod.height)
		 + boxsize.height/2 + vseparation;
    tmp.up = yesd.width + hseparation;
    tmp.bottom = tmp.up;

    return tmp;
  }


  public boolean CheckInside(int x, int y) {
    if (ConditionBox==null) return true;

    if (ConditionBox.inside(x, y)) {
      dialog.setTitle("Content of Condition "+ConditionNo);
      dialog.setText(ConditionContent);
      dialog.show();
/*      System.out.println(ConditionContent); */
      return false;
    } 

    if (yes.CheckInside(x, y) == false) return false;
    if (no == null) return true;
    return no.CheckInside(x, y);
  }


  public void draw(int x, int y, Graphics g) {
    UnitInfo yessize = yes.size();
    UnitInfo nosize;

    if (no == null)
      nosize = new UnitInfo(boxsize.width,0,0,boxsize.width/2);
    else
      nosize = no.size();

    g.setColor(Color.blue);
    g.drawString("True",
		x+yessize.unitsize.width+hseparation-boxsize.width/2-23,
		y+boxsize.height/2-2);
    g.drawString("False",
		x+yessize.unitsize.width+hseparation+boxsize.width/2+3,
		y+boxsize.height/2-2);
    g.setColor(Color.black);
    if (ConditionBox == null) {
      ConditionBox = 
       recordCondition(x+yessize.unitsize.width+hseparation-boxsize.width/2, y);
    }
    drawCondition(x+yessize.unitsize.width+hseparation-boxsize.width/2, y, 
		ConditionNo, g);


    g.drawLine(x+yessize.up, y+boxsize.height/2,
	x+yessize.unitsize.width+hseparation-boxsize.width/2, y+boxsize.height/2);
    drawDownArrowLine(x+yessize.up, y+boxsize.height/2,
	x+yessize.up, y+boxsize.height/2+vseparation, g);
    yes.draw(x, y+boxsize.height/2+vseparation, g);

    if (no != null) {
      g.drawLine(x+yessize.unitsize.width+hseparation+boxsize.width/2,
		y+boxsize.height/2,
		x+yessize.unitsize.width+2*hseparation+nosize.up,
		y+boxsize.height/2);
      drawDownArrowLine(x+yessize.unitsize.width+2*hseparation+nosize.up,
		y+boxsize.height/2,
		x+yessize.unitsize.width+2*hseparation+nosize.up,
		y+boxsize.height/2+vseparation, g);
      no.draw(x+yessize.unitsize.width+2*hseparation,
		y+boxsize.height/2+vseparation, g);

      if (yessize.unitsize.height > nosize.unitsize.height) {
        g.drawLine(x+yessize.unitsize.width+2*hseparation+nosize.bottom,
		y+boxsize.height/2+vseparation+nosize.unitsize.height,
		x+yessize.unitsize.width+2*hseparation+nosize.bottom,
		y+boxsize.height/2+vseparation+yessize.unitsize.height);
      } else {
        g.drawLine(x+yessize.bottom,
		y+boxsize.height/2+vseparation+yessize.unitsize.height,
		x+yessize.bottom,
		y+boxsize.height/2+vseparation+nosize.unitsize.height);
      }
    } else {
      g.drawLine(x+yessize.unitsize.width+hseparation+boxsize.width/2,
		y+boxsize.height/2,
		x+yessize.unitsize.width+2*hseparation+boxsize.width/2,
		y+boxsize.height/2);
      drawDownArrowLine(x+yessize.unitsize.width+2*hseparation+boxsize.width/2,
		y+boxsize.height/2,
		x+yessize.unitsize.width+2*hseparation+boxsize.width/2,
		y+boxsize.height/2+vseparation+yessize.unitsize.height, g);
    }

    drawDownArrowLine(x+yessize.unitsize.width+hseparation,
	y+boxsize.height/2+vseparation+Math.max(yessize.unitsize.height, nosize.unitsize.height),
	x+yessize.unitsize.width+hseparation,
	y+boxsize.height/2+vseparation+Math.max(yessize.unitsize.height, nosize.
unitsize.height)+vseparation, g);

    g.drawLine(x+yessize.bottom,
	y+boxsize.height/2+vseparation+Math.max(yessize.unitsize.height, nosize.unitsize.height),
	x+yessize.unitsize.width+2*hseparation+nosize.bottom,
	y+boxsize.height/2+vseparation+Math.max(yessize.unitsize.height, nosize.unitsize.height));
     
  }

  public void print(StringBuffer sb, int indentation) {
    int indent;

    SelectStart = sb.length()+indentation+4;
    SelectEnd = SelectStart+("Condition "+ConditionNo).length();

    if (indentation < 0) {
      indent = -1*indentation;
    } else {
      indent = indentation;
      for (int i=0; i<indent; i++) sb.append(' ');
    }
    sb.append("if (Condition "+Integer.toString(ConditionNo)+") {\n");

    yes.print(sb, indent+2);

    if (no != null) {
      for (int i=0; i<indent; i++) sb.append(' ');
      sb.append("} else ");

      if (((StmtList)no).CodeSeg instanceof IfObj &&((StmtList)no).next == null)
        no.print(sb, indent*-1);
      else {
        sb.append("{\n");
        no.print(sb, indent+2);
        for (int i=0; i<indent; i++) sb.append(' ');
        sb.append("}\n");
      }
    } else {
      for (int i=0; i<indent; i++) sb.append(' ');
      sb.append("}\n");
    }

  }

}	/* End Class IfObj */
 



class WhileObj extends ControlObj {
  int ConditionNo;
  String ConditionContent;
  Polygon ConditionBox=null;
  ControlObj content;
  ShowContentDialog dialog = new ShowContentDialog();

  public WhileObj() { type = ControlType.WHILE; }

  public UnitInfo size() {
    UnitInfo tmp = new UnitInfo(0,0,0,0);
    UnitInfo u = content.size();

    tmp.unitsize.width = hseparation + u.unitsize.width + hseparation + hseparation/2;
    tmp.unitsize.height = boxsize.height + vseparation + u.unitsize.height + vseparation/2;
    tmp.up = hseparation + u.up;
    tmp.bottom = tmp.unitsize.width - hseparation/2;

    return tmp;
  }


  public boolean CheckInside(int x, int y) {
    if (ConditionBox==null) return true;

    if (ConditionBox.inside(x, y)) {
      dialog.setTitle("Content of Condition "+ConditionNo);
      dialog.setText(ConditionContent);
      dialog.show();
/*      System.out.println(ConditionContent); */
      return false;
    } else
      return content.CheckInside(x, y);
  }


  public void draw(int x, int y, Graphics g) {
    UnitInfo ContentSize = content.size();

    g.setColor(Color.blue);
    g.drawString("True",
		x+hseparation+ContentSize.up-25,
		y+boxsize.height+10);
    g.drawString("False",
		x+hseparation+ContentSize.up+boxsize.width/2,
		y+boxsize.height/2-5);
    g.setColor(Color.black);
    if (ConditionBox == null) {
      ConditionBox = 
      recordCondition(x+hseparation+ContentSize.up-boxsize.width/2, y); 
    }
    drawCondition(x+hseparation+ContentSize.up-boxsize.width/2, y, 
		ConditionNo, g);


    drawDownArrowLine(x+hseparation+ContentSize.up, y+boxsize.height,
		x+hseparation+ContentSize.up, y+boxsize.height+vseparation,g); 
    content.draw(x+hseparation, y+boxsize.height+vseparation,g);
    drawLeftArrowLine(x+hseparation+ContentSize.bottom,
		y+boxsize.height+vseparation+ContentSize.unitsize.height,
		x,
		y+boxsize.height+vseparation+ContentSize.unitsize.height, g);
    drawUpArrowLine(x, y+boxsize.height+vseparation+ContentSize.unitsize.height,
		x, y-10, g);
    drawRightArrowLine(x, y-10,
		x+hseparation+ContentSize.up, y-10, g);
    drawRightArrowLine(x+hseparation+ContentSize.up+boxsize.width/2,
		y+boxsize.height/2,
		x+hseparation+ContentSize.unitsize.width+hseparation,
		y+boxsize.height/2, g);
    drawDownArrowLine( x+hseparation+ContentSize.unitsize.width+hseparation,
		y+boxsize.height/2,
		x+hseparation+ContentSize.unitsize.width+hseparation,
		y+boxsize.height+vseparation+ContentSize.unitsize.height+vseparation/2, g);

  }


  public void print(StringBuffer sb, int indentation) {
    SelectStart = sb.length()+indentation+7;
    SelectEnd = SelectStart+("Condition "+ConditionNo).length();

    for (int i=0; i<indentation; i++) sb.append(' ');
    sb.append("while (Condition "+Integer.toString(ConditionNo)+") {\n");
    content.print(sb, indentation+2);
    for (int i=0; i<indentation; i++) sb.append(' ');
    sb.append("}\n");
  }


} /* End class WhileObj */




class RepeatObj extends ControlObj {
  int ConditionNo;
  String ConditionContent;
  Polygon ConditionBox=null;
  ControlObj content;
  ShowContentDialog dialog = new ShowContentDialog();

  public RepeatObj() { type = ControlType.REPEAT; }

  public UnitInfo size() {
    UnitInfo tmp = new UnitInfo(0,0,0,0);
    UnitInfo u = content.size();

    tmp.unitsize.width = u.unitsize.width + hseparation;
    tmp.unitsize.height = vseparation/2+u.unitsize.height+(boxsize.height+vseparation);
    tmp.up = hseparation + u.up;
    tmp.bottom = hseparation + u.bottom;

    return tmp;
  }

  public boolean CheckInside(int x, int y) {
    if (ConditionBox==null) return true;

    if (ConditionBox.inside(x, y)) {
      dialog.setTitle("Content of Condition "+ConditionNo);
      dialog.setText(ConditionContent);
      dialog.show();
/*      System.out.println(ConditionContent); */
      return false;
    } else
      return content.CheckInside(x, y);
  }

  public void draw(int x, int y, Graphics g) {
    UnitInfo ContentSize = content.size();

    g.drawLine(x+hseparation+ContentSize.up, y,
		x+hseparation+ContentSize.up, y+vseparation/2);
    content.draw(x+hseparation, y+vseparation/2, g);

    g.setColor(Color.blue);
    g.drawString("True",
		x+hseparation+ContentSize.bottom-boxsize.width/2-20,
		y+vseparation/2+ContentSize.unitsize.height+boxsize.height/2-5); 
    g.drawString("False",
		x+hseparation+ContentSize.bottom-35,
		y+vseparation/2+ContentSize.unitsize.height+boxsize.height+10);
    g.setColor(Color.black);
    if (ConditionBox == null) {
      ConditionBox = 
      recordCondition(x+hseparation+ContentSize.bottom-boxsize.width/2,
		y+vseparation/2+ContentSize.unitsize.height);
    }
    drawCondition(x+hseparation+ContentSize.bottom-boxsize.width/2,
		y+vseparation/2+ContentSize.unitsize.height, 
		ConditionNo, g);

    drawLeftArrowLine(x+hseparation+ContentSize.bottom-boxsize.width/2,
		y+vseparation/2+ContentSize.unitsize.height+boxsize.height/2,
		x, 
		y+vseparation/2+ContentSize.unitsize.height+boxsize.height/2,g);
    drawUpArrowLine(x, 
		y+vseparation/2+ContentSize.unitsize.height+boxsize.height/2,
		x, y, g);
    drawRightArrowLine(x, y, x+hseparation+ContentSize.up, y, g);

    drawDownArrowLine(x+hseparation+ContentSize.bottom,
		y+vseparation/2+ContentSize.unitsize.height+boxsize.height,
		x+hseparation+ContentSize.bottom,
		y+vseparation/2+ContentSize.unitsize.height+boxsize.height+vseparation, g);
  }

  public void print(StringBuffer sb, int indentation) {
    for (int i=0; i<indentation; i++) sb.append(' ');
    sb.append("do {\n");
    content.print(sb, indentation+2);

    SelectStart = sb.length()+indentation+9;
    SelectEnd = SelectStart+("Condition "+ConditionNo).length();

    for (int i=0; i<indentation; i++) sb.append(' ');
    sb.append("} while (Condition "+Integer.toString(ConditionNo)+");\n");
  }

}	/* End Class RepeatObj */



class ProgramObj extends ControlObj {
  public ControlObj content;
  public boolean begin = true;

  public ProgramObj() { type = ControlType.PROGRAM; }

  public UnitInfo size() {
    UnitInfo cs = content.size();
    UnitInfo tmp = new UnitInfo(0,0,0,0);
    
    tmp.unitsize.width = cs.unitsize.width;
    tmp.unitsize.height = cs.unitsize.height+2*boxsize.height+vseparation;
    return tmp;
  }


  public boolean CheckInside(int x, int y) {
    return content.CheckInside(x, y);
  }

  public void draw(int x, int y, Graphics g) {
    UnitInfo cs = content.size();

    g.setColor(Color.black);
    if (active && begin) {
      g.setColor(Color.yellow);
      g.fillOval(x+cs.up-boxsize.width/2, y, boxsize.width, boxsize.height);
      g.setColor(Color.black);
    }
    g.drawOval(x+cs.up-boxsize.width/2, y, boxsize.width, boxsize.height);
    g.setColor(Color.red);
    g.drawString("START", x+cs.up-boxsize.width/2+30, y+25);
    g.setColor(Color.black);
    drawDownArrowLine(x+cs.up, y+boxsize.height,
		x+cs.up, y+boxsize.height+vseparation, g);
    content.draw(x, y+boxsize.height+vseparation, g);
    if (active && begin==false) {
      g.setColor(Color.yellow);
      g.fillOval(x+cs.bottom-boxsize.width/2, 
		y+boxsize.height+vseparation+cs.unitsize.height,
		boxsize.width, boxsize.height);
      g.setColor(Color.black);
    }
    g.drawOval(x+cs.bottom-boxsize.width/2, 
		y+boxsize.height+vseparation+cs.unitsize.height,
		boxsize.width, boxsize.height);
    g.setColor(Color.red);
    g.drawString("END", x+cs.bottom-boxsize.width/2+35, 
		y+boxsize.height+vseparation+cs.unitsize.height+25);
    g.setColor(Color.black);
  }

  public void print(StringBuffer sb, int indentation) {
    content.print(sb, indentation);
  }

}	/* End Class ProgramObj */
