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.*;
import javax.swing.JFrame;	// applet 
import java.awt.Dimension;
import java.awt.*;

public class Fenetrenewton extends JFrame {	//applet
//public class Fenetrenewton extends JPanel {	//applet 
				static JLabel ldegre = new JLabel("degre");
				static JLabel lrac = new JLabel("racines");
        static Panneaunewton pan = new Panneaunewton();
        static JButton bmandel = new JButton("<html>Vitesse de<br>convergence</html>");
        static JButton bjulia = new JButton("<html>Racines de<br>convergence</html>");
        static JButton bnextpointc = new JButton("<html>Fonction<br>suivante</html>");
        static JButton bmemepointc = new JButton("<html>Meme<br>fonction</html>");
        static JButton btravelingh = new JButton("<html>Traveling racine<br>horizontal</html>");
        static JButton btravelingv = new JButton("<html>Traveling racine<br>vertical</html>");
        static JButton btravelingstop = new JButton("<html>Arret<br>traveling</html>");
        static JButton baccelere = new JButton("<html>Accelere<br>traveling</html>");
        static JButton bralenti = new JButton("<html>Ralenti<br>traveling</html>");
        static JButton binverse = new JButton("<html>Inverse<br>traveling</html>");
        static JButton bselect = new JButton("<html>Selectionner<br>racine<br>suivante</html>");
        static JButton bunzoom = new JButton("<html>unZoom</html>"); 
        static JButton bmontre = new JButton("<html>Montre<br>racines</html>"); 
        static JButton bstopdyna = new JButton("<html>Arret<br>Zoom</html>");
        static JButton bstartdyna = new JButton("<html>Zoom<br>dynamique</html>");
        static JButton bracine = new JButton("<html>Déplacer la<br>racine selectionnée</html>");
        static JButton bhelp = new JButton("<html>Aide et<br>commentaires</html>");
        
				private Dimension dim = new Dimension(95, 45);
				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 x;  
        static double y; 
        static double deltaX;
        static double deltaY;
        static double deltravy;
				static double deltravx;

public void affiche(String str,String str2)
{
JOptionPane.showMessageDialog
	    							(null, 
	     							str, 
	     							str2, 
	     							JOptionPane.INFORMATION_MESSAGE);
}

public void help()
{
int indexhelp=0;
String tabhelp[]={"Fractales de Newton","zoom","racines","cycles","souris"};
	     							
String reponse="help";
while (reponse!= null)
	{
	reponse= (String) JOptionPane.showInputDialog
	    							(null,
	     							"Choisir une rubrique de l'aide des fractales de Newton",
	     							"Aide des fractales de Newton- 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="<html> L'approximation de Newton pour rechercher les zéros d'une fonction consiste à approximer la courbe par sa tangente ";
str=str+"<br> F(Z)- F(r) = (Z-r) * F'(Z) or F(r)=0.<br> Selon le point de départ, la suite Zn+1 = Zn - F(Zn) / F'(Zn), converge ou non vers une des n racines du polynome<br>l'ensemble des points ne convergeant pas a la forme des ensembles de Julia associés à l'ensemble de Mandelbrot<br>La 1ère fonction présentée, de degré 3, est un cas où tous les points ne convergent pas<br>pour les suivantes ils convergent, à moins de déplacer les racines (souris du milieu)";
str=str+"<br>les points sont colorés selon la racine vers laquelle ils convergent ou selon la rapidité de convergence - noir indique une divergence vers l'infini ou un cycle au voisinage de 2 racines<br><br>";
str=str+"Ri étant une des racines, F(Z)=(Z-R1)(Z-R2)...(Z-Rn)<br>";
str=str+"la dérivée F'(Z) est la somme des n produits de n-1 racines</html>";
								break;}
	 					case 1:{str="<html>Pour un zoom, cliquer gauche sur les points colorés voisins des frontières, ce qui place le point au centre de l'écran.<br>";
str=str+"ou utiliser le bouton \"zoom dynamique\", qui zoom sur le centre de l'écran<br>";
str=str+"la page html doit être à 100%</html>";break;}
						case 2:{str="<html>Augmenter le degré du polynome revient à ajouter une racine<br>";
str=str+"les racines sont initialement réparties sur le cercle unité<br>";
str=str+"On peut selectionner une des n racines (elle apparait alors avec une croix rouge)<br>";
str=str+"puis effectuer un traveling ou un changement de position<br>";
str=str+"en cliquant avec la souris du milieu ou avec le bouton \"déplacer la racine selectionnée\"</html>";break;}	 					
	 					case 3:{str="<html>cliquer droit pour définit le point de départ d'un cycle de convergence<br>";
str=str+"si on choisit un point dans les ensembles noirs (Julia) le cycle ne converge pas vers une racine</html>";break;}
						case 4:{str="souris gauche : zoom une étape\nsouris droite : debut de cycle de convergence vers une racine\nsouris du milieu : déplacer la racine selectionnée";}
	 					default:{}
	 					}
	 				affiche(str,reponse);
	 				indexhelp++; 
	 				if (indexhelp==tabhelp.length) {indexhelp=0;}
	 				} // switch
	 		} // for
	 } // while
} // help

public void maj()
{pan.repaint();
}

public void reinitrac()
{
int i;
												switch (pan.numfon)
	     									{
	     									case 0:{
	     										pan.degre=3;
	     										pan.racx[0]=1.0;pan.racy[0]=0.0;
	     										pan.racx[1]=-0.5-0.00508;pan.racy[1]=0.33136;
	     										pan.racx[2]=-0.5+0.00508;pan.racy[2]=-0.33136;
	     										break;}
	     									case 1:{
	     										pan.degre=3;
	     										for (i=0;i<pan.degre;i++)
                						{ 
                						pan.racx[i]=Math.cos(i*2*Math.PI/pan.degre);
                						pan.racy[i]=Math.sin(i*2*Math.PI/pan.degre);
                						}
                					break;}
	     									case 2:{
	     										pan.degre=4;
	     										for (i=0;i<pan.degre;i++)
                						{ 
                						pan.racx[i]=Math.cos(i*2*Math.PI/pan.degre);
                						pan.racy[i]=Math.sin(i*2*Math.PI/pan.degre);
                						}
                					break;}
	     									case 3:{
	     										pan.degre=5;
	     										for (i=0;i<pan.degre;i++)
                						{ 
                						pan.racx[i]=Math.cos(i*2*Math.PI/pan.degre);
                						pan.racy[i]=Math.sin(i*2*Math.PI/pan.degre);
                						}
                					break;}
	     									case 4:{ // z4 + z3 + z - 1 = 0
	     										pan.degre=4;
	     										pan.racx[0]=0.0;pan.racy[0]=-1;
	     										pan.racx[1]=0;pan.racy[1]=1;
	     										pan.racx[2]=0.618034;pan.racy[2]=0;
	     										pan.racx[3]=-1.618034;pan.racy[3]=0;
	     										break;}
	     									case 5:{  //z4 + 3 z3 + 2 z2 + 0.2 z + 1 = 0
	     										pan.degre=4;
	     										pan.racx[0]=-1.675245;pan.racy[0]=-0.11495;
	     										pan.racx[1]=-1.675245;pan.racy[1]=0.11495;
	     										pan.racx[2]=0.175245;pan.racy[2]=-0.569159;
	     										pan.racx[3]=0.175245;pan.racy[3]=0.569159;
	     										break;}
	     									case 6:{ //z4 + z3 - 1 = 0
	     										pan.degre=4;
	     										pan.racx[0]=-0.219447;pan.racy[0]=-0.914474;
	     										pan.racx[1]=-0.219447;pan.racy[1]=0.914474;
	     										pan.racx[2]=0.819173;pan.racy[2]=0;
	     										pan.racx[3]=-1.380278;pan.racy[3]=0;
	     										break;}
	     									case 7:{ //-2 z4 + z3 + z2 - 2 z - 1 = 0
	     										pan.degre=4;
	     										pan.racx[0]=0.877439;pan.racy[0]=-0.744862;
	     										pan.racx[1]=0.877439;pan.racy[1]=0.744862;
	     										pan.racx[2]=-0.5;pan.racy[2]=0;
	     										pan.racx[3]=-0.754878;pan.racy[3]=0;
	     										break;}
	     									
	     									case 8:{ // z3 + 2 z2 + z + 3 = 0
	     										pan.degre=3;
	     										pan.racx[0]=-2.174559;pan.racy[0]=0;
	     										pan.racx[1]=0.08728;pan.racy[1]=-1.171312;
	     										pan.racx[2]=0.08728;pan.racy[2]=1.171312;
	     										break;}
	     									case 9:{ // z2-1 = 0
	     										pan.degre=2;
	     										pan.racx[0]=1;pan.racy[0]=0;
	     										pan.racx[1]=-1;pan.racy[1]=0;
	     										break;}
	     									default:{}
	     									} // switch	
} 
 
public Fenetrenewton() 
	{
/* applet*/
  this.setTitle("Approximation de Newton");
  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.setSize(twidth, theight);
  this.setLocationRelativeTo(null);                                
  this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	this.setUndecorated(false);
                 
            this.setLayout(new BorderLayout());
						pan.haut=theight-50; /*1030 */
						pan.longueur=twidth-50;       /* 1870 */       
            menu.setPreferredSize(new Dimension(pan.longueur, 50)); 
            menugauche.setPreferredSize(new Dimension(165, pan.haut));
    				pan.setPreferredSize(new Dimension(pan.longueur, pan.haut));  
            
            ldegre.setPreferredSize(new Dimension(300, 45));
            lrac.setPreferredSize(new Dimension(95, 400));
            bmandel.setPreferredSize(dim);
            bjulia.setPreferredSize(dim);
						bnextpointc.setPreferredSize(dim); 
					  bmemepointc.setPreferredSize(dim);
					  btravelingh.setPreferredSize(dim);
						btravelingv.setPreferredSize(dim);
						btravelingstop.setPreferredSize(dim);
						baccelere.setPreferredSize(dim);
						bralenti.setPreferredSize(dim);
						binverse.setPreferredSize(dim);
						bstartdyna.setPreferredSize(dim); 
						bstopdyna.setPreferredSize(dim);
						bunzoom.setPreferredSize(dim); 
						bmontre.setPreferredSize(dim); 
						bselect.setPreferredSize(dim); 
						bracine.setPreferredSize(dim); 
						bhelp.setPreferredSize(dim); 

						bmandel.addActionListener(new fmandel());
						bjulia.addActionListener(new fjulia());
						bnextpointc.addActionListener(new fnextpointc());
						bmemepointc.addActionListener(new fmemepointc());
						btravelingv.addActionListener(new ftravelingv());
						btravelingh.addActionListener(new ftravelingh());
						btravelingstop.addActionListener(new ftravelingstop());
						baccelere.addActionListener(new faccelere());
						bralenti.addActionListener(new fralenti());
						binverse.addActionListener(new finverse());
						bunzoom.addActionListener(new funzoom());
						bmontre.addActionListener(new fmontre());
						bselect.addActionListener(new fselect());
						bracine.addActionListener(new fracine());
						bhelp.addActionListener(new fhelp());
						
						bstartdyna.addActionListener(new fstartdyna());
						bstopdyna.addActionListener(new fstopdyna());
				
						menu.add(ldegre);
						menu.add(bmontre);
            menu.add(bmandel);
            menu.add(bjulia);
            menu.add(bnextpointc);
            menu.add(bmemepointc);
            menu.add(bunzoom); 
            menu.add(bstartdyna);
            menu.add(bstopdyna);
            menu.add(bhelp);
            menugauche.add(btravelingh);
            menugauche.add(btravelingv);
            menugauche.add(btravelingstop);
           	menugauche.add(baccelere);
            menugauche.add(bralenti);
            menugauche.add(binverse);
            menugauche.add(bselect);
            menugauche.add(bracine);
            menugauche.add(lrac);
          
            this.add(menu, BorderLayout.NORTH); 
            this.add(menugauche,BorderLayout.WEST); 
            this.add(pan, BorderLayout.CENTER);
   			
      			//	this.setContentPane(container);
            this.setVisible(true);
     					
 						t=new Timer(); 
 						t.schedule(new timetask(),1000,500);
      str="bbbb"; 
        		} 


       class timetask extends TimerTask 
        	{
        	public void run() 
        		{ 
        		if (pan.pastravel>0)
							{str="<br>Pas du traveling="+pan.pastravel+"<br>vers le haut ou vers la droite";}
						else 
							{str="<br>Pas du traveling="+pan.pastravel+"<br>vers le bas ou vers la gauche";}
        		ldegre.setText("<html>Degré="+pan.degre+str+"</html>");
        		
        		str="<html>";
        		for (int j=0;j<pan.degre;j++)
        			{
        			str=str+"  "+pan.racx[j]+"<br>  +"+pan.racy[j]+" i<br><br>";
        			}
        		lrac.setText(str+"</html>");
        		
        						if ((pan.flag==true) && (pan.traveling==true))
        							{pan.racx[pan.ractravel]=pan.racx[pan.ractravel]-deltravx*pan.pastravel;
        							pan.racy[pan.ractravel]=pan.racy[pan.ractravel]-deltravy*pan.pastravel;
        							maj();
        							}
        			     	if ((pan.flag==true) && (pan.dyna==true) && (pan.nbi<30))
 										    { 
 										    deltaX=(pan.maxX-pan.minX)/3.0;
 									 	    deltaY=(pan.maxY-pan.minY)/3.0; 
 										    //System.out.println("min "+pan.minX+" "+pan.maxX);
 										    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;
 										    pan.nbi=pan.nbi+1;
 										     
 										    pan.nb=pan.nb+30;
 										    //System.out.println("x "+x+" "+y+" "+pan.nbi);
 										    pan.flag=false;
 										    pan.repaint();
      									}  
        		} 
        	}
       
        class fmandel implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
                      //  String str = ((JButton)e.getSource()).getText();
        
                	pan.racines=false;
                	pan.repaint(); 
                	}    
        	} 
        
        class fjulia implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
             			pan.racines=true;
                
                	pan.repaint();
                	} 
 
        	}
      
        class fnextpointc implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                	int i=pan.numfon+1;
 									if (i==pan.tabfon.length) {i=0;}
									String  reponse = (String) JOptionPane.showInputDialog
	    							(null, 
	     							"Choisir un polynome à analyser", 
	     							"Boutons personnalises", 
	     							JOptionPane.QUESTION_MESSAGE,
	     							null,
	     							pan.tabfon,
	     							pan.tabfon[i]);
	     						
	     						for (int j=0;j<pan.tabfon.length;j++)
	     							if (reponse==pan.tabfon[j])
	     								{
	     								pan.numfon=j;
	     								for (i=0;i<pan.degre;i++)
                				{ 
                				pan.racx[i]=0;
                				pan.racy[i]=0;
                				} 
	     							reinitrac();
                		pan.dyna=false;
                		pan.traveling=false;
                		pan.ractravel=1;
                		
                		double del=3.0;
                		pan.minX=-del;
                		pan.maxX=pan.minX+2*del;
                		pan.minY=-del/2.0;
                		pan.maxY=pan.minY+del;
                		pan.nb=200;
                		pan.repaint();
                		}
                	}
              
        	}
	
        class fmemepointc implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{  
                		reinitrac();
                		double del=3.0;
                		pan.minX=-del;
                		pan.maxX=pan.minX+2*del;
                		pan.minY=-del/2.0;
                		pan.maxY=pan.minY+del;
                		pan.nb=200;
                	pan.repaint();
                	}
                
        	}
       class fstopdyna implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
                        pan.dyna=false;  
                        pan.cycle=false;  
                	}
              
        	}
        class fstartdyna implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
                        pan.dyna=true; 
                        pan.flag=true;
                        pan.cycle=false;
                        pan.nbi=0;    
                	}
                
        	} 
       class faccelere implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                        if (Math.abs(pan.pastravel)<0.01) {pan.pastravel=1.5*pan.pastravel; }
                        maj();
                	} 
           }
       class fralenti implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                        pan.pastravel=pan.pastravel/1.5; 
                        maj();   
                	}
           }
        class finverse implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                        pan.pastravel=-pan.pastravel;
                        maj();  
                	}
        	}   

      class fmontre implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
                        if (pan.montre==true)
                        	{pan.montre=false; }
                        else 
                        	{pan.montre=true;}
                        maj();
                	}
                
        	}
    	class ftravelingh implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
   	            	{
               
                				pan.dyna=false;
                				pan.cycle=false;
                	 			deltravx=-1.0;
                	   		deltravy=0.0;  
                        if (pan.traveling==false)
                        	{
                        	btravelingstop.setVisible(true);
                        	pan.traveling=true;
        									
                					}  
                	}
                
        	}  
      class ftravelingv implements ActionListener
        	{
                @Override 
                public void actionPerformed(ActionEvent e) 
                	{
                	pan.dyna=false;
                	pan.cycle=false;
									deltravx=0.0;
                	deltravy=1.0;
                        if (pan.traveling==false) 
                        	{
                        	btravelingstop.setVisible(true);
                        	pan.traveling=true;
                
                					}  
                	}
                
        	}
        class ftravelingstop implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{
                	pan.traveling=false; 
                	pan.cycle=false;
                	btravelingstop.setVisible(false);  
                	}
                
        	}
       	class fselect implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{if (pan.ractravel==pan.degre-1)
                		{pan.ractravel=0;}
                	else
                		{pan.ractravel=pan.ractravel+1;} 
                	maj();
                	}
                
        	}
        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;
 									pan.nbi=pan.nbi+1;
 									maj();
                          
                	}
           }
        class fracine implements ActionListener
        	{
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
            			String  reponse = (String) JOptionPane.showInputDialog
	    							(null, 
	     							"Coordonnées x et y de la racine selectionnée (avec un point décimal)\nsans espace, séparées par une virgule\non peut aussi effectuer un traveling de cette racine", 
	     							"Point C", 
	     							JOptionPane.QUESTION_MESSAGE);
	     							int i=reponse.indexOf(",");
	     							if (i>1)
	     								{
	     								try
		     								{pan.resux=Double.parseDouble(reponse.substring(0,i));
	     									pan.resuy=Double.parseDouble(reponse.substring(i+1,reponse.length()));}
	     								catch(Exception ee)
	     									{i=0;}
	     								if (i>1)
            						{pan.racx[pan.ractravel]=pan.resux;
            						pan.racy[pan.ractravel]=pan.resuy;
            						}
                     maj();
                     }
                	}
        	} 
   	class fhelp implements ActionListener
        	{ 
                @Override
                public void actionPerformed(ActionEvent e) 
                	{ 
                        help(); 
                	}
           
        	}
}
