import java.applet.*;
import java.awt.*;
import java.awt.event.*;


public class SimplePendulumApplet extends Applet
        implements Runnable,ActionListener,AdjustmentListener,ItemListener

//Appletクラスを継承して、時間的な処理、ボタンのイベント、スクロールバーのイベントを処理するインターフェイスを実装する。



{
    Thread th;                                                                                                //Threadクラスの変数thを設定
    SimplePendulumCanvas spc;                                                                       //SimplePendulumCanvasクラスの変数spcを設定
    SimplePendulumCanvas2 spc2;

//コンポーネント
    Button button;                                                                                                   
    Scrollbar scrbar,scrbar1;                                                                         
    Label angleLabel,periodLabel;
    Checkbox ch;
    
    


//プロパティ、メンバ
    double t=0;
    int dt=100;
    double thetaMax=Math.PI/6;                                                //初期角度
    double T=2.0;                                                                        //初期周期
    
    final int thetaMax_min=5;                                                            //最小角度
    final int thetaMax_max=90;                                                          //最大角度
    final int deltaTheta=5;                                                                    //角度の刻み幅

    final int periodmax_min=1;                                                              //最小周期
    final int periodmax_max=6;                                                             // 最大周期
    final int deltaperiod=1;                         //周期の刻み幅

    double omega = 2*Math.PI/T;                                                

    boolean threadFlg = true;                                                                         //スレッドのループに利用するフラグ変数  
    boolean suspendFlg = false;                                                                       //スレッドの一時停止と再開に利用するフラグ変数

    
    


//---------------------------------------------------------初期設定用メソッド--------------------------------------------
//メソッド1
public void init(){        
    this.spc=new SimplePendulumCanvas(this.thetaMax);        //キャンバスをオブジェクト化 theta=thetaMax
    this.spc2=new SimplePendulumCanvas2(0);

//画面の設定を行っていく
    //画面上部のパネルの作成
    int theta_i=30;
    int period_i=2;
    this.button=new Button("reset");
    this.ch=new Checkbox("stopped");
    this.scrbar=new Scrollbar(Scrollbar.HORIZONTAL,
                theta_i,
                this.deltaTheta,
                this.thetaMax_min,
                this.thetaMax_max+this.deltaTheta);    //
    this.angleLabel=new Label(theta_i+"deg",Label.CENTER);
    this.scrbar1=new Scrollbar(Scrollbar.HORIZONTAL,period_i,this.deltaperiod,this.periodmax_min,this.periodmax_max+this.deltaperiod);
    this.periodLabel=new Label("T="+period_i+"s",Label.CENTER);

    Panel p=new Panel();                                                            //パネルのオブジェクト化
    p.setLayout(new GridLayout(1,4));                                            //パネルのレイアウトのオブジェクト化と設定

    p.add(ch);
    p.add(button);    //追加
    p.add(scrbar);
    p.add(angleLabel);

    //画面下部のラベルの作成
    Panel p2=new Panel();
    p2.setLayout(new GridLayout(1,3));
    p2.add(new Label("Period T",Label.CENTER));
    p2.add(scrbar1);
    p2.add(periodLabel);
    

    //画面真中のパネル
    Panel p3=new Panel();
    p3.setLayout(new GridLayout(1,2));
    p3.add(spc);
    p3.add(spc2);
    
    //アプレットのレイアウトを設定
    this.setLayout(new BorderLayout());

    this.add(p,BorderLayout.NORTH);
    this.add(p3,BorderLayout.CENTER);
    this.add(p2,BorderLayout.SOUTH);

//リスナーに登録
    this.button.addActionListener(this);
    this.scrbar.addAdjustmentListener(this);
    this.ch.addItemListener(this);
    this.scrbar1.addAdjustmentListener(this);

    }

//-------------------------------------実行が始まると呼び出される処理----------------------//

//メソッド2    
public void start(){
        th=new Thread(this);       //変数thをオブジェクト化
        th.start();                 //スレッドをスタートさせる
    }
    

public void run(){
    while(threadFlg){                
        double omega = 2*Math.PI/this.T;                                //w=2π/Tの計算    
        
        double theta=this.thetaMax*Math.cos(omega*t);    //θ=Acos(wt)の計算            
        
        this.spc.setAngle(theta);                   //CanvasのsetAngleメソッドに値を返す。
        this.spc.repaint();                                                             //Canvasの再描写



        double velocity=this.thetaMax*omega*Math.sin(omega*t);                    //速度の計算
        double acc=this.thetaMax*omega*omega*Math.cos(omega*t);                //加速度の計算
    
        this.spc2.setVelocity(velocity);                       //値を返す
        this.spc2.setAcc(acc);
        this.spc2.repaint();                                //再描写



        t=t+dt/1000.0;               //時間を進める
    
        try{
            Thread.sleep(dt);
             synchronized(this){          
                    while(suspendFlg){               //suspendFlg=Trueの場合、スレッドを一時停止
                            wait();
                                }  
                                    }
                                        }
        catch(InterruptedException e){}
    
            }
        }


public void adjustmentValueChanged(AdjustmentEvent ev){
    if(ev.getSource()==this.scrbar){                            //スクロールバーを移動で、値を変える
    this.angleLabel.setText(this.scrbar.getValue()+"deg");
                    }
    if(ev.getSource()==this.scrbar1){
    this.periodLabel.setText("T="+this.scrbar1.getValue()+"s");                
        }
    }


public void actionPerformed(ActionEvent ev){
    if(ev.getSource()==this.button){                          //Resetボタンを押すと、t=0から
    this.t=0;
    this.thetaMax=this.scrbar.getValue()*Math.PI/180.0;          //初期角度の値を変える
    this.T=this.scrbar1.getValue();                       //周期の値を変える
    }            
    }





public synchronized void itemStateChanged(ItemEvent ev){
    Checkbox ch = (Checkbox)ev.getItemSelectable();           //チェックボックスを押したとき
      
    if(ch.getState()){
            this.suspendFlg=true;                       //suspendFlgをTrueにする
        }    
 
    else{
        suspendFlg = false;      
        notify();}}


public void paint (Graphics g){
        }


public void stop(){
    
    }
}