package pg.coursjava.logo;
import java.awt.* ;
import java.awt.event.* ;
/**
*
* Un objet de cette classe définit une fenêtre munie d'un repère dont :
* - l'origine est au centre de la fenêtre,
* - l'axe des X est horizontal et orienté de gauche à droite,
* - l'axe des Y vertical et orienté de bas en haut.
*
* De plus cette fenêtre définit un objet Plume qui permet de dessiner "à la logo".
* (la plume possède des méthodes "à la Logo" pour écrire dans la fenêtre : avancer, tourner,
* lever, baisser, ...).
*
* @author Philippe Genoud d'après Laurent Mounier
* @version 15 février 1999
*/
public class Fenetre extends Frame
implements ActionListener, MouseListener {
private Plume laPlume;
// gestion de la fenetre d'affichage
int offsetX;
int offsetY ; // decalage de l'origine du repere
private Image offImage; // image associe a l'offscreen
private Graphics offGraphics; // contexte graphique de l'offscreen
private Button boutonQuitter = new Button ("Quitter ...") ;
// gestion des clics souris
private boolean clic=false;
private boolean attendsClic=false ;
private int clicX = 0;
private int clicY = 0; // position du dernier clic souris
private Color couleurPlume ; // couleur courante
/**
*
* crée et affiche une fenêtre de dessin "à la logo".
* Une plume de classe Plume est automatiquement créee et est associée à la fenêtre.
* La plume est placée au centre de la fenêtre, en position basse avec un cap de 0
* (sur axe des x positifs).
*
* @param titre le titre de la fenêtre.
* @param largeur largeur de la fenêtre en pixels.
* @param hauteur hauteur de la fenetre en pixels.
*/
public Fenetre (String titre, int largeur, int hauteur) {
/* on cree la fenetre et on l'affiche */
super (titre);
setSize (largeur, hauteur) ;
add ("South", boutonQuitter) ;
boutonQuitter.addActionListener (this) ;
addMouseListener (this) ;
laPlume = new Plume(this);
show () ;
/* on cree un offscreen pour y effectuer les affichages */
Dimension offDimension = getSize () ;
offImage = createImage(offDimension.width, offDimension.height);
offGraphics = offImage.getGraphics () ;
offsetX = (getInsets().left + largeur)/2 ;
offsetY = (getInsets().top + hauteur)/2 ;
offGraphics.translate (offsetX, offsetY) ;
}
/**
*
* crée et affiche une fenêtre de dessin "à la logo".
* La Plume associée à la fenêtre est passée en paramètre et doit être créée explicitement.
*
* @param titre le titre de la fenêtre.
* @param largeur largeur de la fenêtre en pixels.
* @param hauteur hauteur de la fenetre en pixels.
* @param p la Plume à associer à la fenêtre
*/
public Fenetre (String titre, int largeur, int hauteur, Plume p) {
/* on cree la fenetre et on l'affiche */
this(titre,largeur,hauteur);
laPlume = p;
p.setFenetre(this);
repaint(); // tout cela est très sale et mal programmé, mais cela urge !!!!
}
/**
*
* Suspend l'exécution de l'appelant
* @param x durée de suspension en millisecondes
*/
public void pause (int x)
{
try
{
Thread.sleep(x) ;
}
catch (InterruptedException signal)
{
signal.printStackTrace();
System.exit(1);
}
}
/**
* Affiche un point.
* @param p le point à afficher
*/
public void affichePoint ( Pt p)
{
afficheDisque (p, 2) ;
}
/**
* Efface un point.
* @param p le point à effacer
*/
public void effacePoint ( Pt p)
{
couleurPlume = getForeground () ;
offGraphics.setColor (getBackground ()) ;
affichePoint (p) ;
offGraphics.setColor (couleurPlume) ;
}
/**
* Affiche un cercle.
* @param c le centre du cercle
* @param r le rayon du cercle
*/
public void afficheCercle (Pt c, double r)
{
offGraphics.drawOval ((int) Math.round(c.x-r), -(int) Math.round(c.y-r),
(int) Math.round(r*2), (int) Math.round(r*2)) ;
repaint () ;
}
/**
* Efface un cercle.
* @param c le centre du cercle
* @param r le rayon du cercle
*/
public void effaceCercle (Pt c, double r)
{
couleurPlume = getForeground () ;
offGraphics.setColor (getBackground ()) ;
afficheCercle (c, r) ;
offGraphics.setColor (couleurPlume) ;
}
/**
* Affiche un disque (cercle plein).
* @param c le centre du cercle
* @param r le rayon du cercle
*/
public void afficheDisque (Pt c, double r)
{
offGraphics.fillOval ((int) Math.round(c.x-r), -(int) Math.round(c.y-r),
(int) Math.round(r*2), (int) Math.round(r*2)) ;
repaint () ;
}
/**
* Efface un disque.
* @param c le centre du cercle
* @param r le rayon du cercle
*/
public void effaceDisque (Pt c, double r)
{
couleurPlume = getForeground () ;
offGraphics.setColor (getBackground ()) ;
afficheDisque (c, r) ;
offGraphics.setColor (couleurPlume) ;
}
/**
* Affiche un segment.
* @param p1 point origine du segment
* @param p2 point extremité du segment
*/
public void afficheSegment ( Pt p1, Pt p2)
{
offGraphics.drawLine ((int)Math.round(p1.x), (int)Math.round(-p1.y),
(int) Math.round(p2.x), (int) Math.round(-p2.y)) ;
repaint () ;
}
/**
* Efface un segment.
* @param p1 origine du segment
* @param p2 extremité du segment
*/
public void effaceSegment ( Pt p1, Pt p2)
{
couleurPlume = getForeground () ;
offGraphics.setColor (getBackground ()) ;
afficheSegment (p1, p2) ;
offGraphics.setColor (couleurPlume) ;
}
/**
*
* Bloque l'appelant jusqu'à ce qu'un clic souris ait eu lieu
* dans la fenetre.
* Lorrsqu'un clic est effectué retourne les coordonnées du point correspondant
* Le point sur lequel le clic a eu lieu est affiché.
* Attention ne marche pas toujours très bien sous Windows (mauvaise gestion des threads ?).
* @return le point où était le mulôt au moment du clic.
*/
public Pt attendsClic () {
int mx, my ;
// Change le titre du bouton
boutonQuitter.setLabel("Cliquez dans la fenetre") ;
boutonQuitter.setEnabled(false);
repaint () ;
// on attends qu'un clic ait lieu
clic = false ;
attendsClic = true ;
while (! clic) {
try
{
Thread.sleep(5) ;
}
catch (InterruptedException e)
{
e.printStackTrace();
System.exit(1);
}
}
attendsClic = false ;
// Restitue le titre du bouton
boutonQuitter.setLabel("Quitter ...") ;
boutonQuitter.setEnabled(true);
repaint () ;
/* on renvoie les coordonnees du point clique */
return (new Pt (clicX, -clicY)) ;
}
/**
* retourne la plume pour dessiner dans la fenêtre
* @return reference de l'objet Plume associé à la fenêtre
*/
public Plume getPlume()
{
return laPlume;
}
/**
* retourne une chaîne (String) représentant la fenêtre et la plume qu'elle contient.
* @return la chaîne représentant la fenêtre.
* "je suis une fenêtre"
* "ma taile : ... ..."
* "je suis une Plume"
* "ma position : x = .. y =.."
* "mon cap : ..."
* "je suis levée" ou "je suis baissée"
*/
public String toString()
{
return "Je suis une Fenetre\n" +
"ma taille " + getSize().width + " " + getSize().height + "\n" +
laPlume;
}
/* ----------------------------------------------------------------
Methodes de gestion de la fenetre
---------------------------------------------------------------- */
public void update (Graphics g) {
if (offImage != null)
g.drawImage(offImage, 0, 0, this); // on affiche l'offscreen
if (laPlume.estVisible())
laPlume.dessineToi(g);
}
public void paint (Graphics g) {
update (g) ;
}
/* ----------------------------------------------------------------
Methodes de l'interface MouseListener
---------------------------------------------------------------- */
public void mouseClicked (MouseEvent e) {
}
public void mousePressed (MouseEvent e) {
} ;
public void mouseEntered (MouseEvent e) {
} ;
public void mouseReleased (MouseEvent e) {
if (attendsClic) {
clic = true ;
clicX = e.getX() - offsetX ; clicY = e.getY() - offsetY ;
}
} ;
public void mouseExited (MouseEvent e) {
} ;
/* ----------------------------------------------------------------
Methodes de l'interface ActionListener
---------------------------------------------------------------- */
public void actionPerformed (ActionEvent e) {
if (e.getSource() == boutonQuitter) {
System.exit (0) ;
} ;
}
/* ----------------------------------------------------------------
Programme de TEST
---------------------------------------------------------------- */
static void main(String[] args)
{
Fenetre f = new Fenetre("TEST",600,600);
Plume laPlume = f.getPlume();
laPlume.avance(50);
Pt pt = f.attendsClic();
f.pause(1000);
laPlume.tourne(120);
laPlume.avance(100);
f.pause(300);
laPlume.tourne(120);
laPlume.avance(100);
f.pause(300);
laPlume.tourne(120);
laPlume.avance(50);
f.pause(300);
laPlume.positionne(0,-100);
laPlume.avance(1000);
laPlume.leve();
laPlume.positionne(-50,-60);
laPlume.tourne(-45);
pt = f.attendsClic();
for (int i = 0; i < 10; i++)
{
laPlume.baisse();
laPlume.avance(10);
laPlume.leve();
laPlume.avance(10);
}
}
}