//
/* ----------------------------------------------------------------------------------------------
    gate.java	論理回路										ver. 2.00 (JDK 1.02)
    															ueyama@infonet.co.jp  1998.08.26
    															update: 2007.08.06
---------------------------------------------------------------------------------------------- */

import java.applet.Applet;
import java.awt.*;

public class gate extends Applet implements Runnable
{
	int			Gn=0;													// ゲートNo. 0:AND 1:OR 2:NAND 3:NOR 4:NOT
	int			Ph=0;													// 表示波形位相 80pixel=1周期
	int			Wait=32;												// 表示変更待ち時間 (msec)
	int			Xi=5, Xo=456;											// 入出力波形表示 X座標
	int			Ya=16, Yb=54, Yx=35;									// 入出力波形表示 Y座標
	int			Xt=497, Yt=76;
	boolean		Run=false;
	boolean		Stp=false;
	Image		Img, Buf;
	Thread		th=null;
	
	int			Tt[][][]={{{0,1,2},{0,0,0},{0,1,0},{1,0,0},{1,1,1}},	// 真理値表: AND
						  {{0,1,2},{0,0,0},{0,1,1},{1,0,1},{1,1,1}},	//           OR
						  {{0,1,2},{0,0,1},{0,1,1},{1,0,1},{1,1,0}},	//           NAND
						  {{0,1,2},{0,0,1},{0,1,0},{1,0,0},{1,1,0}},	//           NOR
						  {{0,2,2},{0,1,1},{1,0,0},{0,1,1},{1,0,0}}};	//           NOT
	int			Wf[][]={{1,40,40},{1,20,20},{1,20,60},{1,60,20},{0,20,60},{0,60,20},{0,40,40}};	// 波形データ
				//		 A         B         AND       OR        NAND      NOR       NOT           初期値, 幅, 幅
	
	public void init()
	{
		String	bg=getParameter("bgcolor");								// 背景色の読み込み
		int bgc=Integer.valueOf(bg,16).intValue();
		setBackground(new Color(bgc));
		Buf=createImage(size().width,size().height);
		MediaTracker mt=new MediaTracker(this);
		Img=getImage(getCodeBase(), getParameter("figure"));			// gif ファイルの読み込み
		mt.addImage(Img, 0);
		try
		{
			mt.waitForID(0);
		}
		catch(InterruptedException e){};
	}
	
	public void start()
	{
		if(th==null)
		{
			th=new Thread(this);
			th.start();
		}
	}
	
	public void update(Graphics g)
	{
		paint(g);
	}
	
	public boolean inside(int x, int a, int b)
	{
		return (x<=Math.max(a,b) && x>=Math.min(a,b)) ? true:false;
	}
	
	public void dsp_g(int x, int y, int n, int c, Graphics g)			// ゲートや数字の表示
	{
		int w=0, h=0, ox=0, oy=0;
		switch(c)
		{
			case 0: w=130; h=74; ox=  0; oy= 0;	break;					// ゲート
			case 1: w= 20; h=31; ox=650; oy= 0;	break;					// '0' '1'(大)
			case 2: w= 13; h=15; ox=650; oy=31;	break;					// '0' '1'(小)
			case 3: w= 13; h=14; ox=650; oy=46;	break;					// 'A', 'B', 'X'
			case 4: w= 26; h=23; ox=  0; oy=74;	break;					// ボタン
			case 5: w=301; h=14; ox=390; oy=74;	break;					// ラジオボタン
			case 6: w=  6; h= 6; ox=650; oy=60;	break;					// ラジオボタン用ドット
		}
		Graphics gx=g.create();
		gx.clipRect(x,y,w,h);
		gx.clearRect(x,y,w,h);
		gx.drawImage(Img,x-(ox+n*w),y-oy,this);
		gx.dispose();
	}
	
	public int dsp_wf(int x, int y, int n, Graphics g)					// 波形表示  n: 波形データNo.
	{
		int i,l,m,p,w,x0=x;
		m=Wf[n][1]+Wf[n][2];											// 信号の周期
		w=Ph % m;														// 波形 水平線の長さ
		if(w>Wf[n][2]) w-=Wf[n][2];
		p=(Ph%m>Wf[n][2])?1:2;											// Wf[][p]
		l=(p==1)? Wf[n][0]: ((Wf[n][0]==0)?1:0);						// 信号の値 (0 or 1)
		for(i=0;i<160;i+=w)												// 入力波形を 160pixel で表示
		{
			g.fillRect(x,y-l*20,w,3);									// 波形:水平線の描画
			x+=w;
			g.fillRect(x,y-20,3,23);									// 波形:垂直線の描画
			p=(p==1)?2:1;
			w=Wf[n][p];
			l=(l==0)?1:0;
		}
		g.fillRect(x,y-l*20,160-(x-x0),3);								// 波形:水平線の描画
		return l;
	}
	
	public void paint(Graphics g)
	{
		int i,j,m, sa=0, sb=0, sx=0;
		g.clearRect(0,0,size().width,size().height);
		dsp_g(248,5,Gn,0,g);
		g.setColor(Color.black);
		sa=dsp_wf(Xi,((Gn<4)?Ya:Yx)+20,0,g);							// 入力信号 A の波形の表示
		dsp_g(198,(Gn<4)?12:30,sa,1,g);									// 入力 A の表示
		if(Gn<4) sb=dsp_wf(Xi,Yb+20,1,g);								// 入力信号 B の波形の表示
		if(Gn<4) dsp_g(198,50,sb,1,g);									// 入力 B の表示
		sx=dsp_wf(Xo,Yx+20,Gn+2,g);										// 出力信号 X の波形の表示
		dsp_g(405, 30,sx,1,g);											// 出力 X の表示
		g.setColor(Color.gray);											// 真理値表 の表示
		for(i=0;i<((Gn==4)?4:6);i++) g.drawLine(Xt,Yt+i*20,Xt+80,Yt+i*20);	// 真理値表横罫
		if(Gn<4)														// for AND, OR, NAND, NOR
		{
			for(i=0;i<5;i++) for(j=0;j<3;j++)
			{
				m=Tt[Gn][i][j]+((sa*2+sb+1==i)?2:0);					// 真理値表該当行赤色表示のため
				dsp_g(Xt+j*27+7,Yt+i*20+3,m,(i==0)?3:2,g);				// 文字、数字の表示
			}
			for(j=0;j<4;j++) g.drawLine(Xt+j*27,Yt,Xt+j*27,Yt+100);		// 真理値表縦罫
		}
		else															// for NOT
		{
			for(i=0;i<3;i++) for(j=0;j<2;j++)
			{
				m=Tt[Gn][i][j]+((sa+1==i)?2:0);							// 真理値表該当行赤色表示のため
				dsp_g(Xt+j*40+13,Yt+i*20+3,m,(i==0)?3:2,g);				// 文字、数字の表示
			}
			for(j=0;j<3;j++) g.drawLine(Xt+j*40,Yt,Xt+j*40,Yt+60);		// 真理値表縦罫
		}
		dsp_g(85,210,0,5,g);											// ラジオボタンの表示
		for(i=0;i<5;i++) dsp_g(89+64*i,214,(i==Gn)?0:1,6,g);			// ラジオボタンドットの表示
		dsp_g(410,205,3,4,g);											// << ボタンの表示
		dsp_g(440,205,(Run)?9:6,4,g);									// || ボタンの表示
		dsp_g(470,205,(Wait==16)?2:0,4,g);								// >> ボタンの表示
		dsp_g(510,205,(Run)?14:12,4,g);									// 凸 ボタンの表示
	}

	public void run()
	{
		while(th!=null)
		{
			if(Run || Stp)
			{
				Graphics offg=Buf.getGraphics();
				paint(offg);
				Graphics ong=getGraphics();
				ong.drawImage(Buf,0,0,this);
				Stp=false;
				if(Run) {Ph++; Ph%=80;}
			}
			try
			{
				th.sleep(Wait);
			}
			catch (InterruptedException e){};
		}
	}
	
	public boolean mouseDown(Event e, int mx, int my)
	{
		Graphics gx=getGraphics();
		if(my>204)
		{
			if(inside(mx,85,386)) Gn=(mx-85)/64;						// ラジオボタンをクリック
			if(inside(mx,410,436))
			{
				dsp_g(410,205,4,4,gx);									// << ボタンの表示
				Wait*=2;
			}
			if(inside(mx,440,466))
			{
				dsp_g(440,205,(Run)?10:7,4,gx);							// || ボタンの表示
				Run=!Run;
			}
			if(inside(mx,470,496) && Wait>16)
			{
				dsp_g(470,205,1,4,gx);									// >> ボタンの表示
				Wait/=2;
			}
			if(inside(mx,510,536) && !Run)
			{
				dsp_g(510,205,13,4,gx);									// 凸 ボタンの表示
				Ph++; Ph%=80;
				Stp=true;
			}
		}
		return true;
	}
	
	public boolean mouseUp(Event e, int mx, int my)
	{
		if(my>204 && inside(mx,85,501)) repaint();
		return true;
	}
	
	public void stop()
	{
		if(th!=null)
		{
			th.stop();
			th=null;
		}
	}
}
//
戻る