// Langage JAVA
// Projet 2
//
// Communication entre applets
//
// Christophe Boyanique
// Emmanuel Pinard
// Avril 1999
//
//
// Applet d'affichage de la courbe

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

public class courbe extends Applet
{
  // Variables publiques:
  public int     S;
  public int     n;
  public int     tf;
  public int     dt;
  public int     t;
  public double  U0[];
  public double  U1[];
  public double  U2[];

  protected dessin c = new dessin(this);
  public evt_delegue delegue;

  // Variables privees:
  private Panel p_but;
  private Button b_next;
  private Button b_zero;
  private Button b_dall;

  // Methode invoquee depuis l'autre applet afin d'envoyer les
  // parametres de la courbe
  public void receive_params(int r_S, int r_n, int r_tf, int r_dt)
  {

    // Mets a jour les parametres
    S  = r_S;
    n  = r_n;
    tf = r_tf;
    dt = r_dt;
    t  = 0;

    // Reinitialisation des tableaux de calcul:
    U0 = new double[n+2];
    U1 = new double[n+2];
    U2 = new double[n+2];

    // Initialise la courbe
    init_courbe();
    c.paint(c.getGraphics());
  }

  // Cette methode initialise la procedure de calcul des courbes.
  // Elle calcule les valeurs de U0, et U1.
  public void init_courbe()
  {
    int    i;
    double D = (2750 * 1e-3 / 25) * (2750 * 1e-3 / 25);

    // Initialisation de U-2:
    for (i=0; i<=n+1; i++)
      U1[i] = 0;

    // Initialisation de U-1:
    for (i=0; i<=n+1; i++)
      U0[i] = 0;

    // Initialisation de U-1(1):
    U0[2] = S;

    t = -1;

    // Dessin de la premiere courbe:
    next_courbe();
  }

  // Cette methode calcule l'etape suivante de la courbe
  public void next_courbe()
  {
    int    i;
    double D = (2750 * 1e-3 / 25) * (2750 * 1e-3 / 25);

    for (i=0; i<n+1; i++)
    {
      // On recopie U1 dans U2: U(j-1) dans U(j-2)
      U2[i] = U1[i];
      // On recopie U0 dans U1: U(j) dans U(j-1)
      U1[i] = U0[i];
    }

    // Calcul de U0: U(j)
    for (i=1; i<=n; i++)
      U0[i] = 2 * U1[i] - U2[i] + D * ( -2 * U1[i] + U1[i+1] + U1[i-1] );

    U0[0]   = -U0[2];
    U0[n+1] = U0[n];

    // Incremente le compteur de temps
    t += 1;
  }

  public courbe()
  {
  }

  public void init()
  {
    // Construction de l'interface:
    setLayout(new BorderLayout());

    // Le panel de l'image:
    add("Center", c);

    // Le panel des boutons:
    p_but = new Panel();
    p_but.setLayout(new GridLayout(1, 2));
    // Les boutons du panel:
    b_next = new Button("Etape suivante");
    b_next.addActionListener(new evt_adaptateur(evt_adaptateur.NEXT, new evt_delegue(), this));
    b_zero = new Button("Remise a zero");
    b_zero.addActionListener(new evt_adaptateur(evt_adaptateur.RESET, new evt_delegue(), this));
    b_dall = new Button("de 0 a tf");
    b_dall.addActionListener(new evt_adaptateur(evt_adaptateur.ALL, new evt_delegue(), this));
    p_but.add(b_next);
    p_but.add(b_zero);
    p_but.add(b_dall);

    add("South", p_but);

    // Initialise les parametres par defaut
    receive_params(10, 400, 2000, 50);

  }

  public void start()
  {
  }

  public void stop()
  {
  }

  // Fonction appellee par le delegue
  public void reset()
  {
    // Reinitialise la courbe
    init_courbe();
    c.paint(c.getGraphics());
  }

  // Fonction appellee par le delegue
  public void next()
  { 
    int i;
    
    // Calcul des dt etapes suivantes
    for (i=0; i<dt; i++)
      if ( t < tf )
      {
        next_courbe();
        c.paint(c.getGraphics());
      }
  }

  // Fonction appellee par le delegue
  public void all()
  {
    int i;

    // Reinitialise la courbe
    init_courbe(); 
    // Calcul de la totalite des etapes
    for (i=0; i<tf; i++)
    {
      next_courbe();
      if ( t % dt == 0 )
        c.paint(c.getGraphics());
    }
  }

}

class dessin extends Canvas
{
  // Reference de l'applet principale
  private courbe refcourbe;

  // Constructeur recevant la reference de l'applet principale
  public dessin(courbe ref)
  {
    refcourbe = ref;
  }

  public void paint(Graphics g)
  {
    int    i, cx, cy, cw, ch;
    int    x1, x2, y1, y2;

    // Dessine le cadre de la zone graphique
    Rectangle r = getBounds();
    g.setColor(Color.black);
    g.drawRect(0, 0, r.width, r.height );
    g.setColor(Color.white);
    g.fillRect(1, 1, r.width-2, r.height-2 );

    // Affiche les parametres de la courbe
    g.setColor(Color.black);
    g.drawString( "S=" + Integer.toString(refcourbe.S)
                + " n=" + Integer.toString(refcourbe.n)
                + " tf=" + Integer.toString(refcourbe.tf)
                + " dt=" + Integer.toString(refcourbe.dt)
                + " t=" + Integer.toString(refcourbe.t), 10, 20);

    // Calcule la zone de dessin
    cx = 5;
    cy = 5;
    cw = r.width - 12;
    ch = r.height - 12;

    // Dessin de l'axe Y:
    g.drawLine(cx, cy, cx, cy+ch);

    // Dessin de l'axe X:
    g.drawLine(cx, cy+ch/2, cx+cw, cy+ch/2);

    // Dessin de la courbe:
    g.setColor(Color.red);

    // Dessin de la courbe
    for (i=1; i<=refcourbe.n; i++)
    {
      x1 = (int)((double)(i)*(double)cw/(double)refcourbe.n);
      x2 = (int)((double)(i+1)*(double)cw/(double)refcourbe.n);
      y1 = - (int)(refcourbe.U0[i]*(ch/2)/(2*refcourbe.S));
      y2 =  - (int)(refcourbe.U0[i+1]*(ch/2)/(2*refcourbe.S));
      if (y1 < -(ch/2) )
        y1 = -(ch/2);
      if (y2 < -(ch/2) )
        y2 = -(ch/2);
      if (y1 > (ch/2) )
        y1 = (ch/2);
      if (y2 > (ch/2) )
        y2 = (ch/2);

      g.drawLine( cx + x1, cy + (ch/2) + y1, cx + x2, cy + (ch/2) + y2);

    }
  }
}

