import java.awt.Graphics; 
import java.awt.Color;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.BorderLayout; 
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.Dimension;
import javax.swing.JPanel; 
import java.awt.Font; 
import java.util.Timer;
import java.util.TimerTask; 
import javax.swing.JFrame;	// applet 

import java.awt.*;
import java.awt.event.*;  
import javax.swing.*; 
 
//public class fenetreifs extends JPanel {	//applet JFrame
public class fenetreifs extends JFrame {
        static panneauifs pan = new panneauifs();
        static JLabel lpas = new JLabel();
 //       "<html>pas du traveling="+pan.pastravel+" , vers le haut ou vers la droite<br>montre les bassins d'attraction<br>C=0 <br>+ 0 i<br>Mandelbrot pour Zn+1=Zn*Zn+C en cours</html>");
   			static JLabel lvide = new JLabel("");
   			
        static JButton baleatoire = new JButton("<html>Aléatoire : itérer<br>une transformation<br>sur un point</html>");
        static JButton bprogressif = new JButton("Rapide");
        static JButton bmanuel = new JButton("Automatique");
        static JButton bdetermine = new JButton("<html>Determiné :<br>1 fois chaque<br>transformation</html>");
        static JButton bcycle = new JButton("<html>Cycle<br>suivant</html>");
        static JButton bdetail = new JButton("<html>Détail des<br>transformations</html>");
        static JButton bcoloration = new JButton("<html>Coloration</html>");
      
        static JButton bt1 = new JButton("<html>Transformation<br>1</html>");
        static JButton bt2 = new JButton("<html>Transformation<br>2</html>");
        static JButton bt3 = new JButton("<html>Transformation<br>3</html>");
        static JButton bt4 = new JButton("<html>Transformation<br>4</html>");
        static JButton bt5 = new JButton("<html>Transformation<br>5</html>");
        static JButton bt6 = new JButton("<html>Transformation<br>6</html>");
        static JButton bt7 = new JButton("<html>Transformation<br>7</html>");
        static JButton bt8 = new JButton("<html>Transformation<br>8</html>");
        static JButton bt9 = new JButton("<html>Transformation<br>9<html>");
        static JButton bunzoom = new JButton("<html>unZoom</html>"); 
        static JButton bnextgroupe = new JButton("<html>groupe<br>d'IFS<br>suivant<br></html>");
        static JButton bnextifs = new JButton("<html>IFS<br>suivant<br>du groupe</html>");
        static JButton bmodifier = new JButton("<html>Modifier les<br>transformations<br>de l'IFS identité</html>");
        static JButton bretirer = new JButton("<html>Retirer une<br>transformation<br>de l'ifs identité</html>");
        static JButton bajouter = new JButton("<html>Ajouter une<br>transformation<br>à l'ifs identité</html>");
        static JButton bdepart = new JButton("<html>Structure<br>de départ=<br>segment</html>"); 
        static JButton bhelp = new JButton("<html>Aide et<br>commentaires</html>");
				private Dimension dim = new Dimension(95, 60);	//95
				static JPanel menu = new JPanel();  
				static JPanel menugauche = new JPanel();
				Font police = new Font("Arial", Font.BOLD, 12);
				static String str=new String();
				Timer t;
 
				static double deltravy;
				static double deltravx; 
 
        static double deltaX;
        static double deltaY;
        static double x;
        static double y;
        static String tabdepart[]={"Segment","Triangle","Carré","Pts fixes","Pt.fixe 2","Photo"};
        
private void pointfixes()
 {
 pan.nbfixe=0;
 int nbtrans=pan.ifs[pan.numifs].length;
 for (int i=0;i<nbtrans;i++)
   {
   double a=pan.ifs[pan.numifs][i][0];
	 double b=pan.ifs[pan.numifs][i][1];
	 double c=pan.ifs[pan.numifs][i][2];
	 double d=pan.ifs[pan.numifs][i][3];
	 double e=pan.ifs[pan.numifs][i][4];
	 double f=pan.ifs[pan.numifs][i][5];
	 double det=(d-1)*(a-1)-b*c;
	 pan.pf[i]=-1;
	 if ((b!=0) && (det!=0))
	 	{
	 	pan.pfx[pan.nbfixe]=(b*f-(d-1)*e)/det;
	 	pan.pfy[pan.nbfixe]=((1-a)*pan.pfx[pan.nbfixe]-e)/b;
	  pan.pf[i]=pan.nbfixe;
	 	pan.nbfixe=pan.nbfixe+1;
//	 	System.out.println("t"+i+" a");
	 	}
	 if ((b==0) && ((a!=1) && (d!=1)))
	 	{
	 	pan.pfx[pan.nbfixe]=e/(1-a);
	 	pan.pfy[pan.nbfixe]=(c*pan.pfx[pan.nbfixe]+f)/(1-d);
	 	pan.pf[i]=pan.nbfixe;
	 	pan.nbfixe=pan.nbfixe+1;
//	 	System.out.println("t"+i+" b");
	 	}
	 if ((b==0) && ((a!=1) && (d==1)))
	 	{
	 	pan.pfx[pan.nbfixe]=x=e/(1-a);
	 	pan.pfy[pan.nbfixe]=y=e*c/(1-a)+f;
	 	pan.pf[i]=pan.nbfixe;
	 	pan.nbfixe=pan.nbfixe+1;
//	 	System.out.println("t"+i+" c");
	 	}
	 }
 }

public void affiche(String str,String str2)
{
JOptionPane.showMessageDialog
	    							(null, 
	     							str, 
	     							str2, 
	     							JOptionPane.INFORMATION_MESSAGE);
}
   
public void help()
{
int indexhelp=0;
String tabhelp[]={"Transformations affines","Analyse d'une transformation","l'ensemble point fixe attracteur","algorithme aléatoire ou déterministe","Dynamique de la convergence","zoom"};
	     							
String reponse="help";
while (reponse!= null) 
	{
	reponse = (String) JOptionPane.showInputDialog
	    							(null,
	     							"Choisir une rubrique de l'aide des IFS",
	     							"Iterated Fonction System- http://www.pdbzro.com/gags", 
	     							JOptionPane.QUESTION_MESSAGE,
	     							null,
	     							tabhelp,
	     							tabhelp[indexhelp]);
	 for (int i=0;i<tabhelp.length;i++)	
	 		{
	 		if (reponse==tabhelp[i])
	 				{
	 				switch (i)
	 					{
case 0:{str="On considère les transformations affines du plan : \n";
	str=str+"- les homothéties Zn+1 = r * Zn dont la matrice de transformation est :\n";
	str=str+"       (r   0)   ou 	( r  0 )\n";
	str=str+"       (0   r)     	   ( 0  s )\n";
	str=str+"  si r # s, l'homothétie est déformante\n";
	str=str+"  on se limite aux homothéties contractantes, dont |r| < 1\n";
	str=str+"  ce qui empêche la divergence vers l'infini, et explique la présence dans l'image résultat d'images plus petites, autosimilaires\n\n";
	str=str+"- les rotations Zn+1 = exp(i t) * Zn\n";
	str=str+"dont la matrice est :\n";
	str=str+"       ( cos(t)  -sin(t) )   ou  (cos(t)   -sin(phi)\n";
	str=str+"       ( sin(t)   cos(t) )	          (sin(t)    cos(phi)\n";
	str=str+" si t # phi il y a déformation par cisaillement selon les axes\n";
	str=str+"une homothétie ou une rotation par rapport à un autre centre que (0,0) se décompose en une homothéthie ou une rotation autour de (0,0) suivie d'une translation\n";
	str=str+"x'=(x-x0)*cos(t) - (y-y0)*sin(t) + x0\n";
	str=str+"y'=(x-x0)*sin(t) + (y-y0)*cos(t) + y0\n\n";
 
	str=str+"- les symetries Zn+1 = Zn' = Rn - i * In (axe des x) et Zn+1 = -Zn' = -Rn + i * In (axe des y)\n";
	str=str+"ont pour  matrices respectives :\n";
	str=str+"       (  1   0 )    et   (-1   0)\n";
	str=str+"       (  0  -1 )          (0    1)\n"; 
	
	str=str+"en composant ces transformations, ces matrices se multiplient en :\n";
	str=str+"       ( r cos(t)    -s sin(phi) )   soit   ( a   b)\n";
	str=str+"       ( r sin(t)     s cos(phi) )             ( c   d)\n\n"; 
	str=str+"- on considère aussi la translation Zn+1 = Zn + Cst\n";
	str=str+"       (e)\n";
	str=str+"       (f)\n";
	str=str+"soit :\n"; 
	str=str+"Zn+1 = (Xn+1) = ( a    b )  *  ( Xn )  +  ( e )\n"; 
	str=str+"             (Yn+1)     ( c    d )      ( Yn )       ( f )\net donc :\n";
	str=str+"Xn+1 = a * Xn + b * Yn + e    = r * cos(theta) * Xn - s * sin(phi) * Yn + e\n";
	str=str+"Yn+1 = c * Xn + d * Yn + f     = r * sin(theta) * Xn + s * cos(phi) * Yn + f\n\n"; 
	str=str+"- on considère enfin une probabilité p pour choisir la transformation à appliquer par l'algorithme aléatoire\n\n";
	str=str+"une transformation est donc complètement définie par le nuplet constitué de nombres réels: (a, b, c, d, e, f, p)\n";break;}

case 1:{
	str="Etant donné la transformation (a, b, c, d, e, f, p), on peut calculer r, s, t et phi\n";
	str=str+"r=sqrt(a2+c2) et s=sqrt(b2+d2)\n";
	str=str+"t=arccos(a/r)*sign(c) et phi=arccos(d/s)*signe(-b)\n\n";
	str=str+"pour trouver le point fixe éventuel de chaque transformation, il faut résoudre :\n";
	str=str+"    x=ax+by+e\n";
	str=str+"    y=cx+dy+f\n";
	str=str+"soit :\n";
	str=str+"si b#0 et (d-1)*(a-1)-b*c#0, x=(b*f-(d-1)*e)/((d-1)*(a-1)-b*c) et y=((1-a)*x-e)/b\n";
	str=str+"si b=0, a#1, et d#1, x=e/(1-a) et y=(c*x+f)/(1-d)  \n";
	str=str+"si b=0 et a#1 et d=1, x=e/(1-a) et y=e*c/(1-a)+f\n";
	break;}

case 2:{
	str="Un ensemble de n transformations de ce type définit un système d'itérateurs (IFS) convergeant vers un ensemble de points,\nnommé l'attracteur, qui est en quelque sorte le \"point\" fixe du système\n";
	str=str+"\n";
	break;}
	
case 3:{str="- L'algorithme aléatoire (cliquer sur \"aléatoire\") consiste à prendre un point Z et à lui appliquer une des transformations, choisie au hasard\n";
	str=str+"puis à recommencer avec le point résultat.\n";
	str=str+"il suffit de ne pas afficher les 100 premiers points, le temps que la convergence se fasse, puis d'afficher tous les autres.\n";
	str=str+"On peut choisir un affichage progressif (un groupe de points par 500 ms) ou rapide (tous les points calculés d'un coup)\n\n";
	str=str+"- L'algorithme déterministe (cliquer sur \"déterminé\") consiste à partir d'un ensemble de points (un segment, un triangle, un carré, les points fixes, le 2ème point fixe, une photo....) et à lui appliquer un cycle constitué d'une fois chacune des transformations\n";
	str=str+"puis à recommencer avec l'ensemble des points images ainsi obtenus par l'application des n transforations\n";
	str=str+"la ligne joignant les points fixes est un bon ensemble de départ pour l'algorithme déterministe\n(il faut parfois retirer ceux qui servent à faire des connections, des troncs, ...)\n\n";
	str=str+"0n peut choisir un affichage \"manuel\", cycle par cycle, à chaque appui sur le bouton \"cycle suivant\" ou automatique (un cycle toutes les 500ms pendant une vingtaine de cycles).\n";
	str=str+"Choisir une photo comme structure de départ implique le passage à l'algorithme déterminé, et montre que quelque soit l'image de départ, on parvient au même résultat\n";
	str=str+"Dans le cas de l'affichage \"manuel\", pour bien comprendre le rôle de chaque transformation, on peut les appliquer une par une\n";
	str=str+"mais dans ce cas, comme on n'applique qu'une seule transformation à l'image d'une seule transformation, contractante, on ne peut pas atteindre l'attracteur";
	break;}

case 4:{
	str="Il y a plusieurs cas de convergence :\n";
	str=str+"- vers une surface remplie de points\n";
	str=str+"  En choisissant bien l'ensemble de départ, l'algorithme déterministe permet alors de distinguer la\n";
	str=str+"     convergence vers une courbe qui, par ses circonvolutions de plus en plus serrées, remplit la surface\n";
	str=str+"     c'est le cas des dragons de Heighway, Sierpinski, Levy, du twindragon et de leurs dérivés, des courbes de Hilbert, Peano, Gosper\n";
	str=str+"     l'alorithme déterministe montre alors à chaque cycle l'évolution de la courbe\n";
	str=str+"- vers une courbe, continue mais non dérivable en tous points, de longueur infinie, mais de surface enclose finie\n";
	str=str+"     c'est le cas de la courbe et du flocon de von Koch et de leurs dérivés\n";
	str=str+"     F1(0)=0, fn(1) et Fi(0)=Fi-1(1)\n";
	str=str+"- vers un compact dit \"ouvert\", contenant des trous\n";
	str=str+"     les images de chaque transformations sont disjointes - c'est le cas du triangle et du tapis de Sierpinski : on place par exemple des homothéties aux sommets d'un polygone\n";
	str=str+"- vers une spirale autour d'un point fixe, par une rotation d'angle faible et de rapport voisin de 1 et une homothétie de fort rapport pour constituer une réduction de l'ensemble près d'un 2ème point fixe";
	str=str+"\n";
	str=str+"\n";
	break;}
	
case 5:{str="Le zoom (souris gauche) recentre sur le point choisit et effectue un aggrandissement\n";break;}

case 6:{str=str+"on peut modifier les transformations de l'IFS \"identité\", en modifiant ses transformations en en rajoutant ou retirant\n\n";
str=str+"on peut aussi définir un ensemble de départ et appliquer successivement l'une ou l'autre des transformations du système sur la structure de départ et ses images successives";break;}
	 					
	 					default:{}
	 					} 
	 				affiche(str,reponse);
	 				indexhelp++; 
	 				if (indexhelp==tabhelp.length) {indexhelp=0;}
	 				} // switch
	 		} // for
	 } // while
} // help

        
public void mmaj()
{ 
str="<html>"+pan.nomifs[pan.numifs]+"</html>";
lpas.setText(str);
lpas.repaint();
}
        
public void maj()
{
mmaj();
 
if (pan.flag==true) {pan.repaint();}
} 

public void initifs()
	{ 
                  double minX = -2.4;
									double maxX = 2.4;
									double minY = -1.5; 
									double maxY =  1.5;
									
									bt3.setVisible(false);
									bt4.setVisible(false);
            			bt5.setVisible(false);
            			bt6.setVisible(false);
            			bt7.setVisible(false);
            			bt8.setVisible(false);
            			bt9.setVisible(false);
            	int nbtrans=pan.ifs[pan.numifs].length;
            	if (nbtrans>2){bt3.setVisible(true);}
							if (nbtrans>3){bt4.setVisible(true);}
            	if (nbtrans>4){bt5.setVisible(true);}
            	if (nbtrans>5){bt6.setVisible(true);}
            	if (nbtrans>6){bt7.setVisible(true);}
            	if (nbtrans>7){bt8.setVisible(true);}
            	if (nbtrans>8){bt9.setVisible(true);}
            	pan.depart=0;
            	pan.forme=3; 
            	pan.aleatoire=true; 
            	if (pan.numgroupe==2)
            		{pan.aleatoire=false;
            		pan.initdetermine=true;}
									switch (pan.numifs)
										{
										case 0:{minX=0.5-0.96;maxX=0.5+0.96;minY=0.5-0.6;maxY=0.5+0.6;pan.depart=0;break;} //sierpinski
										case 1:{minX=0.5-3.6;maxX=0.5+3.6;minY=1.5-2.3;maxY=1.5+2.3;pan.depart=0;break;} //sierpinski2
										case 2:{minX=0.5-1.8;maxX=0.5+1.8;minY=0.5-1.2;maxY=0.5+1.2;pan.depart=4;break;} //tapis
										case 3:{minX=0.5-1;maxX=0.5+1;minY=0.5-0.6;maxY=0.5+0.6;pan.depart=1;break;} //cristal1
										case 4:{minX=0.5-10;maxX=0.5+10;minY=6-6.4;maxY=6+6.4;break;} //cristal2
										case 5:{minX=0.4-1;maxX=0.4+1;minY=0.4-0.6;maxY=0.4+0.6;break;} // rameau 
										case 6:{minX=0-7;maxX=0+7;minY=0-4.4;maxY=0+4.4;pan.depart=1;break;} // arbre
										case 7:{minX=0-0.4;maxX=0+0.4;minY=0.2-0.24;maxY=0.2+0.24;pan.depart=2;break;} // lorenz
										case 8:{minX=0-10;maxX=0+10;minY=-0.7-6;maxY=-0.7+6;pan.depart=1;break;} // feuille 
										case 9:{minX=0.3-10;maxX=0.3+10;minY=5.2-6.4;maxY=5.2+6.4;pan.depart=1;break;} // fougère
										case 10:{minX=-0.66-10;maxX=-0.66+10;minY=3.6-6.4;maxY=3.6+6.4;break;} // etoile 
										case 11:{minX=0.65-9;maxX=0.65+9;minY=4.5-5.6;maxY=4.5+5.6;break;} // zigzag
										case 12:{minX=-0.42-10;maxX=-0.42+10;minY=4.8-6.4;maxY=4.8+6.4;break;} // dragon 
										case 13:{minX=1-9;maxX=1+9;minY=4.5-5.6;maxY=4.5+5.6;break;} // binary
										case 14:{minX=-0.88-9;maxX=-0.88+9;minY=5.3-5.6;maxY=5.3+5.6;break;} // corail
										case 15:{minX=0.5-1;maxX=0.5+1;minY=0.5-0.6;maxY=0.5+0.6;break;} // spirale2
										case 16:{minX=0.1-1;maxX=0.1+1;minY=0.5-0.6;maxY=0.5+0.6;break;} // spirale3
										case 17:{break;} // spirale4
										case 18:{break;} // spirale5 
										case 19:{pan.depart=1;break;} // spirale6
										case 20:{minX=0.5-1;maxX=0.5+1;minY=0-0.6;maxY=0+0.6;pan.depart=2;break;} // koch
										case 21:{minX=0.46-1.3;maxX=0.46+1.3;minY=0.295-0.8;maxY=0.295+0.8;pan.forme=0;break;} // dragon heigway 
										case 22:{minX=0-5;maxX=0+5;minY=0-3;maxY=0+3;pan.depart=0;break;} // twin dragon
										case 23:{minX=0.5-1;maxX=0.5+1;minY=0.5-1;maxY=0.5+1;pan.forme=0;break;} // hilbert
										case 24:{minX = -1.2; maxX = 1.2; minY = -0.85; maxY =  0.85;;pan.forme=0;pan.depart=0;break;} // peano
										case 25:{pan.depart=0;break;} // sierpinski
										case 26:{pan.depart=0;break;} // gosper
										case 27:{pan.depart=0;break;} // levy 
										case 28:{minX=0.5-2;maxX=0.5+2;minY=0.7-1.3;maxY=0.7+1.3;break;} // pentagone de sierpinski
										case 29:{minX=0.5-1;maxX=0.5+1;minY=0.5-0.6;maxY=0.5+0.6;break;} // christmas tree
										case 30:{minX=0.7-0.7;maxX=0.7+0.7;minY=0.0-0.5;maxY=0.0+0.5;pan.depart=3;break;} // feuille
										case 31:{minX=0.7-4.6;maxX=0.7+4.6;minY=1.5-3;maxY=1.5+3;pan.depart=1;break;} // hexa
										case 32:{minX=0.9-3.5;maxX=0.9+3.5;minY=0.8-2;maxY=0.8+2;pan.depart=1;break;} // thexa
										case 33:{minX=0.5-1;maxX=0.5+1;minY=0.5-0.6;maxY=0.5+0.6;pan.depart=1;break;} // sand dollar
										case 34:{pan.depart=4;break;} // arbren
										case 35:{minX=0.0-2;maxX=0.0+2;minY=0.0-2;maxY=0.0+2;break;} // arbrep
										case 36:{break;} //koch2
										case 37:{break;} //3moins 
										case 38:{minX=0.0-5;maxX=0.0+5;minY=0.0-3.3;maxY=0.0+3.3;break;} //3plus
										case 39:{break;} //5moins
										case 40:{minX=0.0-5;maxX=0.0+5;minY=0.0-3;maxY=0.0+3;break;} //5plus
										case 41:{break;} //6moins 
										case 42:{break;} //6plusplus
										case 43:{break;} //z
										case 44:{break;} //t
										case 45:{minX = -0.5; maxX = 1.7;	minY = -0.90;maxY =  0.90;pan.forme=0;break;} // gosper
										case 46:{minX=0.5-1;maxX=0.5+1;minY=0-0.6;maxY=0+0.6;pan.depart=2;break;} // koch 70
										case 47:{minX=0.5-1;maxX=0.5+1;minY=0-0.6;maxY=0+0.6;pan.depart=2;break;} // koch 80
										case 48:{minX=0.5-1;maxX=0.5+1;minY=0-0.6;maxY=0+0.6;pan.depart=2;break;} // koch 85
										case 49:{minX=0.5-1;maxX=0.5+1;minY=0-0.6;maxY=0+0.6;pan.depart=2;break;} // koch 88
										case 50:{minX=0.5-1;maxX=0.5+1;minY=0-0.6;maxY=0+0.6;pan.depart=2;break;} // koch 90
										case 51:{minX=0.5-0.96;maxX=0.5+0.96;minY=0.5-0.6;maxY=0.5+0.6;pan.depart=0;break;} //Sierpinski à 3
										case 52:{minX=0.5-1;maxX=0.5+1;minY=0.45-0.6;maxY=0.45+0.6;break;} //tour Eiffel
										case 53:{minX=0.5-2.2;maxX=0.5+2.2;minY=0-1.32;maxY=0+1.32;break;} //nautilus
										case 54:{minX=0.5-2.2;maxX=0.5+2.2;minY=0-1.32;maxY=0+1.32;break;} //nautils2
										case 55:{minX=0.5-0.8;maxX=0.5+0.8;minY=0.3-0.5;maxY=0.3+0.5;pan.depart=0;break;} //pentadentrite
										case 56:{minX=0.33-1;maxX=0.33+1;minY=0.3-0.6;maxY=0.3+0.6;break;} // Petigree
										case 57:{break;} // Eisenstein
										case 58:{minX=0.5-1;maxX=0.5+1;minY=0.34-0.6;maxY=0.34+0.6;pan.forme=0;break;} // dragon de Sierpinski
				
										default:{}
										}
									pan.minX=minX;
									pan.maxX=maxX;
									pan.minY=minY;
									pan.maxY=maxY;
									pointfixes();
									bdepart.setText("<html>structure<br>de départ=<br>"+tabdepart[pan.forme]+"</html>");
}
 
public fenetreifs()
						{ 
/* applet*/
  this.setTitle("Iterated Fonction System - IFS");
  Dimension dime = Toolkit.getDefaultToolkit().getScreenSize();
  int theight = (int)dime.getHeight()-50;
	int twidth  = (int)dime.getWidth()-50;
	System.out.println("Current Screen resolution : "
                           + "width : " + twidth
                           + " height : " + theight);
  this.setSize(twidth, theight);	/* 1280 720 et 1920 1080 j'avais 1500 900 */
  this.setLocationRelativeTo(null);                           
  this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	this.setUndecorated(false); 


//int i=Toolkit.getDefaultToolkit().getScreenSize().height; 
//System.out.println(""+i);
//i=Toolkit.getDefaultToolkit().getScreenSize().width; 
//System.out.println(""+i); 
                
            this.setLayout(new BorderLayout()); 
						pan.haut=theight-100; 
						pan.longueur=twidth-50;           
            menu.setPreferredSize(new Dimension(pan.longueur+200, 70)); 
            menugauche.setPreferredSize(new Dimension(160, pan.haut)); 
    				pan.setPreferredSize(new Dimension(pan.longueur, pan.haut));
          
            lpas.setPreferredSize(new Dimension(400, 70)); //270
            lvide.setPreferredSize(new Dimension(10, 60)); 
              
            //baleatoire.setPreferredSize(dim);
            bprogressif.setPreferredSize(dim);
            bmanuel.setPreferredSize(dim);
            bdetail.setPreferredSize(dim);
            bcoloration.setPreferredSize(dim);
            bdetermine.setPreferredSize(dim);
            bcycle.setPreferredSize(dim);
						bt1.setPreferredSize(dim);
						bt2.setPreferredSize(dim);
						bt3.setPreferredSize(dim);
						bt4.setPreferredSize(dim);
						bt5.setPreferredSize(dim);
						bt6.setPreferredSize(dim);
					  bt7.setPreferredSize(dim);
					  bt8.setPreferredSize(dim); 
						bt9.setPreferredSize(dim); 
						bunzoom.setPreferredSize(dim); 

						bmodifier.setPreferredSize(dim);
					  bajouter.setPreferredSize(dim);
					  bretirer.setPreferredSize(dim);
						bnextifs.setPreferredSize(dim);
						bnextgroupe.setPreferredSize(dim);
						bdepart.setPreferredSize(dim);
						bhelp.setPreferredSize(dim);						

						baleatoire.addActionListener(new faleatoire());
						bprogressif.addActionListener(new fprogressif());
						bmanuel.addActionListener(new fmanuel());
						bdetail.addActionListener(new fdetail());
						bdetermine.addActionListener(new fdetermine());
						bcycle.addActionListener(new fcycle());
						bcoloration.addActionListener(new fcoloration());
						
						
						bt1.addActionListener(new ft1());
						bt2.addActionListener(new ft2());
						bt3.addActionListener(new ft3());
						bt4.addActionListener(new ft4());
						bt5.addActionListener(new ft5());
						bt6.addActionListener(new ft6());
						bt7.addActionListener(new ft7());
						bt8.addActionListener(new ft8());
						bt9.addActionListener(new ft9());
						bunzoom.addActionListener(new funzoom());
						bmodifier.addActionListener(new fmodifier());
						bajouter.addActionListener(new fajouter());
						bretirer.addActionListener(new fretirer());
						bnextifs.addActionListener(new fnextifs());
						bnextgroupe.addActionListener(new fnextgroup());	
						bdepart.addActionListener(new fdepart());
						bhelp.addActionListener(new fhelp());
	
						menu.add(lpas);
            menu.add(baleatoire);
            menu.add(bprogressif);
            menu.add(bdetail);
            menugauche.add(bdetermine);
            menugauche.add(bmanuel);
            menugauche.add(bdepart);
            menugauche.add(bcycle);
            menugauche.add(bt1);
            menugauche.add(bt2);
            menugauche.add(bt3);
           	menugauche.add(bt4);
            menugauche.add(bt5);
            menugauche.add(bt6);
            menugauche.add(bt7);
            menugauche.add(bt8);
            menugauche.add(bt9);
            
            menu.add(bunzoom); 
            menu.add(bcoloration);
        /*	menu.add(bmodifier);
            menu.add(bajouter);
            menu.add(bretirer);	*/
            menu.add(lvide); 
            menu.add(bnextifs); 
            menu.add(bnextgroupe);
            menu.add(bhelp);
           
            this.add(menu, BorderLayout.NORTH);
            this.add(menugauche,BorderLayout.WEST);
            this.add(pan, BorderLayout.CENTER);
   			
      			//	this.setContentPane(container);
            this.setVisible(true);
            // les 4 premieres sont visibles car c'est koch le 1er ifs
            bt5.setVisible(false);
            bt6.setVisible(false);
            bt7.setVisible(false);
            bt8.setVisible(false);
            bt9.setVisible(false);
            
            pointfixes();   						
 						t=new Timer(); 
 						t.schedule(new timetask(),500,100);
      str="bbbb";
      mmaj();
        		} 
        class timetask extends TimerTask 
        	{
        	public void run() 
        		{ 
        		mmaj();
        		
						//maj(); 
         		}
        }
        class fprogressif implements ActionListener
        	{
                @Override 
                public void actionPerformed(ActionEvent e) 
                	{
                      //  String str = ((JButton)e.getSource()).getText();
                  if (pan.progressif==true)
        						{bprogressif.setText("Progressif");
        						pan.progressif=false;}
        					else
        						{bprogressif.setText("Rapide");
        						pan.progressif=true;}
        					bprogressif.repaint();
                	}  
        	}
        class fmanuel implements ActionListener
        	{
                @Override 
                public void actionPerformed(ActionEvent e) 
                	{
                      //  String str = ((JButton)e.getSource()).getText();
                  if (pan.manuel==true)
        						{bmanuel.setText("Manuel");
        						pan.manuel=false;}
        					else 
        						{bmanuel.setText("Automatique");
        						pan.manuel=true;}
        					bmanuel.repaint();
                	}  
        	}
        class faleatoire implements ActionListener
        	{
                @Override 
                public void actionPerformed(ActionEvent e) 
                	{
                      //  String str = ((JButton)e.getSource()).getText();
        					pan.initaleatoire=true;
        					pan.aleatoire=true;
        					pan.thei=0;
        					pan.initdetermine=false;
        					pan.max=pan.maxdebut;
        					
           				pan.repaint();
                	}  
        	}
       
        class fdetermine implements ActionListener 
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
             			pan.initaleatoire=false;
             			pan.thei=pan.max;
             			pan.initdetermine=true;
             			pan.aleatoire=false;
             			pan.trans=-1; 
             			if (pan.forme==5) {pan.coloration=3;}
             			pan.repaint(); 
                	}   
        	}
        
         class fcycle implements ActionListener 
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
             			pan.initaleatoire=false;
             			pan.thei=pan.max;
             		/*	pan.manuel=true;
             			bmanuel.setText("Automatique");
             			bmanuel.repaint();*/
             			if ((pan.forme==5) && (pan.numgroupe==4))
             				{pan.cptdetermine=44;}
             			else
             				{pan.cptdetermine=22;}
             			pan.initdetermine=false;
             			pan.aleatoire=false;
             			pan.trans=-1; 
             			pan.repaint();
                	}
                
        	} 
   		class ft1 implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
   	            	{ 
   	            	pan.aleatoire=false;
   	            	pan.manuel=true;
   	            	bmanuel.setText("Automatique");
   	            	pan.trans=0;
   	            	pan.repaint();
                	}
        	}  
      class ft2 implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
                	pan.aleatoire=false;
   	            	pan.manuel=true;
   	            	bmanuel.setText("Automatique");
   	            	pan.trans=1;
   	            	pan.repaint();
                	}
               
        	}
        class ft3 implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
              		pan.aleatoire=false;
   	            	pan.manuel=true;
   	            	bmanuel.setText("Automatique");
   	            	pan.trans=2;
   	            	pan.repaint();
                	}
                
        	}
       class ft4 implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
                  pan.aleatoire=false;
   	            	pan.manuel=true;
   	            	bmanuel.setText("Automatique");
   	            	pan.trans=3;
   	            	pan.repaint();    
                	}
           }
       class ft5 implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                  pan.aleatoire=false;
   	            	pan.manuel=true;
   	            	bmanuel.setText("Automatique");
   	            	pan.trans=4;
   	            	pan.repaint();    
                	}
           } 
        class ft6 implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                  pan.aleatoire=false;
   	            	pan.manuel=true;
   	            	bmanuel.setText("Automatique");
   	            	pan.trans=5;
   	            	pan.repaint();    
                	}
        	}   
       class ft7 implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{  
                	pan.aleatoire=false;
   	            	pan.manuel=true;
   	            	bmanuel.setText("Automatique");
   	            	pan.trans=6;
   	            	pan.repaint();
                	}
              
        	} 
 				class ft8 implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                	pan.aleatoire=false;
   	            	pan.manuel=true;
   	            	bmanuel.setText("Automatique");
   	            	pan.trans=7;
   	            	pan.repaint();
                	} 
              
        	}
        class ft9 implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{  
                	pan.aleatoire=false;
   	            	pan.manuel=true;
   	            	bmanuel.setText("Automatique");
   	            	pan.trans=8;
   	            	pan.repaint();
                	}
               
        	}
      class fdetail implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent ev) 
                	{ 
                  int nbtrans=pan.ifs[pan.numifs].length;
                  str="<html>"+pan.descifs[pan.numifs]+"<br><br>";
                  for (int i=0;i<nbtrans;i++)
                  	{
                    double a=pan.ifs[pan.numifs][i][0];
										double b=pan.ifs[pan.numifs][i][1];
										double c=pan.ifs[pan.numifs][i][2];
										double d=pan.ifs[pan.numifs][i][3];
										double e=pan.ifs[pan.numifs][i][4];
										double f=pan.ifs[pan.numifs][i][5];
										double p=pan.ifs[pan.numifs][i][6];
										str=str+"Transformation "+(i+1)+" : ";
										for (int j=0;j<7;j++)
											{if (j!=0) {str=str+",";}
											str=str+" "+pan.ifs[pan.numifs][i][j];}
										double r=Math.sqrt(a*a+c*c);
										double s=Math.sqrt(d*d+b*b);
										int t=(int) Math.floor(Math.acos(a/r)*180/Math.PI+0.01);
										int phi=(int) Math.floor(Math.acos(d/s)*180/Math.PI+0.01);
									
										str=str+"<br>   ";
										if (Math.abs(r-s)<0.01) 
											{str=str+"homothétie de rapport "+r+"<br>";}
										else
											{str=str+"r="+r+" s="+s+"<br>";}
										if (Math.abs(t-phi)<0.01) 
											{if (t!=0) {str=str+"rotation d'angle "+t+"<br>";};}
										else
											{str=str+"t="+t+" phi="+phi+"<br>";}
										if ((Math.abs(e)>0.01) || (Math.abs(f)>0.01)) {str=str+" translation : "+e+","+f+"<br>";}
										str=str+"probabilité : "+p+"<br>";
										
										if (pan.pf[i]!=-1)
											{str=str+"point fixe=("+pan.pfx[pan.pf[i]]+", "+pan.pfy[pan.pf[i]]+")<br>";}
										str=str+"<br>";
										}
									str=str+"</html>";
									affiche(str,"détail des transformations");
                	}
             
        	}
 
    	class fhelp implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                       help(); 
                	}
          
        	}
       class fmodifier implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                 
                	}
           
        	} 
     class fajouter implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                 
                	}
           
        	} 
     class fretirer implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                 
                	}
           
        	}  
        class funzoom implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
                	deltaX=(pan.maxX-pan.minX)*1.1;
 									deltaY=(pan.maxY-pan.minY)*1.1; 
 									x=(pan.minX+pan.maxX)/2.0;
 									pan.minX=x-deltaX;
 									pan.maxX=x+deltaX;
 									y=(pan.minY+pan.maxY)/2.0;
 									pan.minY=y-deltaY;
 									pan.maxY=y+deltaY;
 									if (pan.aleatoire==true) 
 										{pan.initaleatoire=true;}
 									else
 										{pan.initdetermine=true;}
 									maj(); 
                	} 
                
        	}
      class fnextgroup implements ActionListener
        	{ 
                @Override 
                public void actionPerformed(ActionEvent e) 
                	{
              
                	int i=pan.numgroupe+1;
 									if (i==pan.nomgroupe.length) {i=0;}
									String  reponse = (String) JOptionPane.showInputDialog
	    							(null, 
	     							"Choisir un groupe d'IFS à analyser", 
	     							"Boutons personnalises", 
	     							JOptionPane.QUESTION_MESSAGE,
	     							null,
	     							pan.nomgroupe, 
	     							pan.nomgroupe[i]);
	     						for (i=0;i<pan.nomgroupe.length;i++)
	     							if (reponse==pan.nomgroupe[i])
	     								{pan.numgroupe=i;
	     								pan.numifsg=0;}
	     						reponse=pan.nomifsparg[pan.numgroupe][0];
	     						for (i=0;i<pan.nomifs.length;i++)
	     							if (reponse==pan.nomifs[i])
	     								{pan.numifs=i;}
	     						pan.initaleatoire=true;
	     						pan.initdetermine=false;
	     						pan.aleatoire=true;
	     						pan.max=pan.maxdebut;
	     						initifs();
	     						maj();
	     						}
	     		}
       class fnextifs implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                	int i=pan.numifsg+1;
 									if (i==pan.nomifsparg[pan.numgroupe].length) {i=0;}
									String  reponse = (String) JOptionPane.showInputDialog
	    							(null, 
	     							"Choisir un IFS à analyser", 
	     							"Boutons personnalises", 
	     							JOptionPane.QUESTION_MESSAGE,
	     							null,
	     							pan.nomifsparg[pan.numgroupe], 
	     							pan.nomifsparg[pan.numgroupe][i]); 
	     						for (i=0;i<pan.nomifsparg[pan.numgroupe].length;i++)
	     							if (reponse==pan.nomifsparg[pan.numgroupe][i])
	     								{
	     								pan.numifsg=i;
	     								}	
	     						for (i=0;i<pan.nomifs.length;i++)
	     							if (reponse==pan.nomifs[i])
	     								{
	     								pan.numifs=i; 
	     								pan.initaleatoire=true;
	     								pan.initdetermine=false;
	     								pan.aleatoire=true;
	     								pan.max=pan.maxdebut;
                      } 
									initifs();
									maj();
                	} 
        	}
       class fcoloration implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                	int i=pan.coloration+1;
 									if (i==pan.nomcoloration.length) {i=0;}
									String  reponse = (String) JOptionPane.showInputDialog
	    							(null, 
	     							"Choisir un mode de coloration", 
	     							"Boutons personnalises", 
	     							JOptionPane.QUESTION_MESSAGE,
	     							null,
	     							pan.nomcoloration, 
	     							pan.nomcoloration[pan.coloration]);
	     						for (i=0;i<pan.nomcoloration.length;i++)
	     							if (reponse==pan.nomcoloration[i])
	     								{ 
	     								pan.coloration=i;
	     								if (i==3) {pan.forme=5;pan.aleatoire=false;pan.initdetermine=true;
	     								bdepart.setText("<html>structure<br>de départ=<br>"+tabdepart[pan.forme]+"</html>");};
	     								} 
									maj();
                	} 
        	}

        class fdepart implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
  								int indexhelp=0;
	     							
									String reponse="help";
									while (reponse!= null) 
										{
										reponse = (String) JOptionPane.showInputDialog
	    								(null,
	     								"Choisir une structure de départ pour l'algorithme déterministe",
	     								"Iterated Fonction System- http://www.pdbzro.com/gags", 
	     								JOptionPane.QUESTION_MESSAGE,
	     								null, 
	     								tabdepart,
	     								tabdepart[indexhelp]);
	 									for (int i=0;i<tabdepart.length;i++)	
	 										{ 
	 										if (reponse==tabdepart[i])
	 											{ 
	 											pan.forme=i;
	 											if (i==5) {pan.coloration=3;pan.aleatoire=false;pan.initdetermine=true;} // photo
	 											bdepart.setText("<html>structure<br>de départ=<br>"+tabdepart[pan.forme]+"</html>");
	 											reponse=null; 
	 											}
	 										}
	 									}       			
                	}
        	} 
}


