import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;

/**
 * Affichage graphique haute résolution en Java.
 *
 */

public class EcranHD {

  private static class MyFrame extends Frame
                               implements WindowListener,
			                                    ActionListener,
                                          KeyListener{
    public static boolean open = false;
    public MyCanvas mc;
    public ScrollPane sp;
    private MenuBar mb = new MenuBar();
    private Menu m1 = new Menu("Fichier");
    private MenuItem mff = new MenuItem("Quitter");

    public void ouvre(int px,int py,int tx,int ty,String titre) {
      if ( !open ) {
        open = true;
        setMenuBar(mb);
        mb.add(m1);
        m1.add(mff);
        mff.addActionListener(this);
        addWindowListener(this);
        setTitle(titre);
        setSize(tx,ty);
        setLocation(px,py);
        sp = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);
        sp.add(mc = new MyCanvas(this));
        add(sp);
        setVisible(true); }
    }

    public void setKeyListeners() {
    }

    public void windowClosed(WindowEvent e) {
    }

    public void windowClosing(WindowEvent e) {
      dispose();
      System.out.println();
      System.exit(0);
    }

    public void windowActivated(WindowEvent e) {
    }

    public void windowDeactivated(WindowEvent e) {
    }

    public void windowDeiconified(WindowEvent e) {
    }

    public void windowIconified(WindowEvent e) {
    }

    public void windowOpened(WindowEvent e) {
    }

    public void actionPerformed(ActionEvent e) {
      if ( e.getSource() == mff ) {
        System.out.println();
        System.exit(0); }
    }

    public void keyPressed(KeyEvent e) {
    }

    public void keyReleased(KeyEvent e) {
    }

    public void keyTyped(KeyEvent e) {
    }
  }
  
  private static class MyCanvas extends Canvas {
    public static boolean open = false;
    public static BufferedImage image = null;
  
    public MyCanvas(MyFrame mf) {
    }

    public void paint(Graphics g) {
      if ( image != null )
        g.drawImage(image,0,0,this);
    }
  }
  
  private static MyFrame mf = new MyFrame();

  /**
    * Initialisation et ouverture d'une fenetre d'affichage graphique.<br>
    * La fenetre est ouverte et affiche initialement une surface vide a fond blanc.<br>
    * Une fois la fenetre ouverte, l'application peut etre arretee via l'option "Quitter" du menu "Fichier".<br>
    * La methode main peut etre utilisee normalement pour envoyer des ordres a la fenetre.<br>
    * Pour quitter, la methode main devra executer un EcranHD.quit() pour fermer la fenetre et s'interrompre. 
    * 
    *
    * @param px L'abscisse du coin superieur gauche de la fenetre.
    * @param py L'ordonnee du coin superieur gauche de la fenetre.
    * @param tx La resolution (nombre de pixels) en x de la fenetre.
    * @param ty La resolution (nombre de pixels) en y de la fenetre.
    * @param titre Le titre donne a la fenetre.
    */
  
  public static void init(int px,int py,int tx,int ty,String titre) {
    mf.ouvre(px,py,tx,ty,titre);
  }

  /**
    * Affichage d'un rectangle de pixels dans la fenetre d'affichage.<br>
    * Le tableau passe en parametre decrit l'image a afficher.<br>
    * Il s'agit d'un tableau à deux indices.<br>
    * La taille selon le premier indice est la resolution en x de l'image.<br>
    * La taille selon le second indice est la resolution en y de l'image.<br>
    * Chaque entier contenu dans le tableau decrit un pixel de l'image code en 24 bits<br>
    * au moyen d'une valeur comprise entre 0 et (2^24)-1=16777215.<br>
    * Les 8 bits de poids faible code la composante rouge.<br>
    * Les 8 bits de poids intermediaire code la composante verte.<br>
    * Les 8 bits de poids fort code la composante bleue.
    *
    * @param img Le tableau de int décrivant l'image.
    */

  public static void set(int [][] img) {
    if ( img == null ) {
      mf.mc.image = null; }
      else {
      int tx = img.length;
      int ty = img[0].length;
      int [] t = new int[tx*ty*3];
      int p = 0;
      for ( int y = 0 ; y < ty ; y++ )
        for ( int x = 0 ; x < tx ; x++ ) {
          t[p] = img[x][y]%256 ;
          t[p+1] = (img[x][y]/256)%256;
          t[p+2] = img[x][y]/65536;
          p = p+3; }
      mf.mc.image = new BufferedImage(tx,ty,BufferedImage.TYPE_3BYTE_BGR);
      WritableRaster wr = mf.mc.image.getRaster();
      wr.setPixels(0,0,tx,ty,t); }
    mf.mc.repaint();
  }

  /**
    * Effacement de la fenetre de dessin.
    *
    */
  
  public static void clear() {
    mf.mc.image = null;
    mf.mc.repaint();
  }

  /**
    * Interruption du fonctionnement de la fenetre et de l'application.
    *
    */
  
  public static void quit() {
    System.exit(0);
  }
}