/*
 * NAT - An universal Translator
 * Copyright (C) 2005 Bruno Mascret
 * Contact: bmascret@free.fr
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package ui;

import gestionnaires.GestionnaireExporter;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.io.IOException;

import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JCheckBox;
import javax.swing.KeyStroke;
import javax.swing.border.LineBorder;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import javax.swing.undo.UndoManager;

import nat.ConfigNat;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.RandomAccessFile;

import outils.Embosseur;
import outils.FileToolKit;
import outils.TextSender;

import java.awt.event.KeyListener;
//import java.awt.Graphics;
import java.util.Hashtable;

/**
 * Cette classe de l'interface graphique permet d'afficher le fichier transcrit et d'intéragir avec lui
 * (édition, mode perkins, etc.).
 * @author Bruno Mascret
 */
public class Editeur extends JFrame implements ActionListener, KeyListener, ComponentListener, CaretListener, TextSender, DocumentListener, UndoableEditListener
{
	/** identifiant par défaut pour la sérialisation (non utilisé dans NAT)*/ 
	private static final long serialVersionUID = 1L;
	/** le label contenant le nom du fichier transcrit */
	private JLabel lFichier = new JLabel("Fichier: ");
	/** le panneau central contenant les éléments à afficher et le scrollPane*/
	private JPanel panneauAffichage = new JPanel();
	/** la zone d'affichage principale du fichier */
	private JTextPane resultat = new JTextPane();
	/** la zone secondaire d'affichage (affiche la ligne en cours dans la police secondaire)*/
	private JTextField ligneRes = new JTextField();
	/** le ScrollPane associé au JTextPane resultat */
	private JScrollPane scrollRes;
	/** Le panneau contenant les boutons d'action */
	private JPanel lesBoutons = new JPanel();
	/** JButton pour enregistrer le fichier */
	private JButton btEnregistrer = new JButton("Enregistrer",new ImageIcon("ui/icon/document-save.png"));
	/** JButton pour enregistrer le fichier */
	private JButton btEnregistrersous = new JButton("Enregistrer sous",new ImageIcon("ui/icon/document-save-as.png"));
	/** JButton pour fermer la fenêtre */
    private JButton btFermer = new JButton("Fermer",new ImageIcon("ui/icon/exit.png"));
	/** L'adresse du fichier transcrit */
	private String fichier = null;
	/** encodage du fichier transcrit */
	private String encodage ="UTF-8";
	/** Jlabel d'information pour l'enregistrement */
	private JLabel message= new JLabel("");
	/** longueur de la ligne braille */
	private int longueurLigne;
	/** taille du caractère de la police principale en point (ne fonctionnen qu'avec les polices à
	 * chasse fixe */
	private int tailleCaractere;
	/** tableau destiné à recevoir les codes perkins */
	private boolean [] tabPoint = new boolean[6];
	/** JCheckBoxpour l'activation du mode perkins */
	private JCheckBox jcbPerkins = new JCheckBox("Saisie Perkins");
	/** JButton pour lancer l'embossage */
	private JButton btEmbosser = new JButton("Embosser",new ImageIcon("ui/icon/document-print.png"));
	
	/** Rapport entre la taille du panneau d'affichage celle de la fenêtre */
	private double proportionPanneauAffichage = 0.8; 
	/** nombre de touches pressées lors d'une saisie perkins */
	private int nbTouches = 0;
	
	//private boolean resizing = false;
	/** Objet embosseur, pour l'embossage bien entendu...*/
	private Embosseur embosseur;
	/** table braille à utiliser pour la saisie perkins */
	private String tableBraille = "Brltab.ent";
	/** HashTable pour la correspondance entre les caractères braille saisis en mode perkins et leur
	 * représentation dans la table braille */
	private Hashtable<String,String> ptPerkins = new Hashtable<String,String>();
	
	//fonctionalités pour l'édition
	/** Undo manager */
	private UndoManager undoMng = new UndoManager();
	/** JButton pour annuler frappe */
	private JButton btUndo = new JButton(new ImageIcon("ui/icon/edit-undo.png"));
	/** JButton pour répéter frappe */
	private JButton btRedo = new JButton(new ImageIcon("ui/icon/edit-redo.png"));
	
	/** 
	 * Construit un objet Editeur
	 * @param taille la longueur de la ligne braille
	 * @param emb l'objet Embosseur à utiliser pour l'embossage
	 */
	public Editeur(int taille, Embosseur emb)
	{
	    super("Editeur");
		embosseur = emb;
		
		addComponentListener(this);
		//resultat.addKeyListener(this);//plus là, mais dans lors de l'activation de jcbPerkins
		longueurLigne = taille;
		//panneauAffichage.setPreferredSize(new Dimension(500,400));
		
		btEnregistrer.addActionListener(this);
		btEnregistrer.getAccessibleContext().setAccessibleName("Bouton enregistrer");
		btEnregistrer.getAccessibleContext().setAccessibleDescription("Valider pour enregistrer le fichier");
		btEnregistrer.setToolTipText("Enregistrer le fichier");
		btEnregistrer.setMnemonic('s');
		
		btEnregistrersous.addActionListener(new GestionnaireExporter(this,this,GestionnaireExporter.EXPORTER_BRF));
		btEnregistrersous.getAccessibleContext().setAccessibleName("Bouton enregistrer sous");
		btEnregistrersous.getAccessibleContext().setAccessibleDescription("Valider pour enregistrer le fichier avec un nouveau nom");
		btEnregistrersous.setToolTipText("Enregistrer le fichier avec un nouveau nom");
		btEnregistrersous.setMnemonic('n');
		// btEnregistrersous.setEnabled(false); //en attendant que ça marche
		
		btFermer.addActionListener(this);
		btFermer.getAccessibleContext().setAccessibleName("Bouton fermer l'éditeur");
		btFermer.getAccessibleContext().setAccessibleDescription("Valider pour fermer l'éditeur");
		btFermer.setToolTipText("Fermer l'éditeur");
		btFermer.setMnemonic('f');
		
		btEmbosser.addActionListener(this);
		btEmbosser.getAccessibleContext().setAccessibleName("Bouton embosser");
		btEmbosser.getAccessibleContext().setAccessibleDescription("Valider pour embosser le document");
		btEmbosser.setToolTipText("Embosser le document");
		btEmbosser.setMnemonic('e');
		if(embosseur==null)
		{
			btEmbosser.setEnabled(false);
		}
		
		jcbPerkins.getAccessibleContext().setAccessibleName("Case à cocher saisie Perkins");
		jcbPerkins.getAccessibleContext().setAccessibleDescription("Cocher cette case pour activer ou désactiver la saisie Perkins");
		jcbPerkins.setToolTipText("Saisie Perkins : saisissez les points braille avec FDS et JKL");
		jcbPerkins.setMnemonic('p');
		jcbPerkins.addActionListener(this);
		
		btUndo.addActionListener(this);
		btUndo.getAccessibleContext().setAccessibleName("Bouton annuler édition");
		btUndo.getAccessibleContext().setAccessibleDescription("Valider pour annuler la dernière modification");
		btUndo.setToolTipText("Annuler la dernière modification");
		btUndo.setMnemonic('u');
		btUndo.setEnabled(false);
		
		btRedo.addActionListener(this);
		btRedo.getAccessibleContext().setAccessibleName("Bouton rétablir édition");
		btRedo.getAccessibleContext().setAccessibleDescription("Valider pour rétablir la dernière modification");
		btRedo.setToolTipText("Rétablir la dernière modification");
		btRedo.setMnemonic('r');
		btRedo.setEnabled(false);
		
		lesBoutons.setLayout(new GridBagLayout());
		GridBagConstraints c = new GridBagConstraints();

		c.gridx = 0;
		c.gridy = 0;
		c.gridwidth = 3;
		lesBoutons.add(message,c);
		c.gridwidth=1;
		c.gridy++;
		lesBoutons.add(btEnregistrer,c);
		c.gridx++;
		lesBoutons.add(btEnregistrersous,c);
		c.gridx++;
		lesBoutons.add(btFermer,c);
		
		scrollRes = new JScrollPane (resultat);
		scrollRes.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		scrollRes.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		
		ligneRes.setEditable(false);//ne fait que de l'affichage
		
		panneauAffichage.setLayout(new BorderLayout());
		panneauAffichage.add("Center",scrollRes);
		panneauAffichage.add("South",ligneRes);
		
		JPanel pLateral = new JPanel();
		LineBorder l = new LineBorder(pLateral.getBackground(),12);
		pLateral.setBorder(l);
		
		//pLateral.setLayout(new BoxLayout(pLateral,BoxLayout.Y_AXIS));
		pLateral.setLayout(new GridBagLayout());
		c.gridx = 0;
		c.gridy = 0;
		pLateral.add(btUndo,c);
		c.gridx++;
		pLateral.add(btRedo,c);
		c.gridx=0;
		c.ipady=50;
		c.gridy++;
		c.gridwidth = 2;
		pLateral.add(jcbPerkins,c);
		c.gridy++;
		c.ipady=10;
		pLateral.add(btEmbosser,c);
		
		/*mise en page*/
		JPanel panneau = new JPanel();
		panneau.setLayout(new BorderLayout());
		panneau.add("North",lFichier);
		panneau.add("Center",panneauAffichage);
		panneau.add("South",lesBoutons);
		panneau.add("East",pLateral);
		JPanel p = new JPanel();
		p.setPreferredSize(new Dimension(10,10));
		panneau.add("West",p);
		setContentPane(panneau);
		if(ConfigNat.getCurrentConfig().getMemoriserFenetre())
		{
			int x= ConfigNat.getCurrentConfig().getWidthEditeur();
			int y=ConfigNat.getCurrentConfig().getHeightEditeur();
			if(x+y != 0){setPreferredSize(new Dimension(x,y));}
		}
		if(ConfigNat.getCurrentConfig().getCentrerFenetre())
		{
			Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
			Dimension size = this.getPreferredSize();
			screenSize.height = screenSize.height/2;
			screenSize.width = screenSize.width/2;
			size.height = size.height/2;
			size.width = size.width/2;
			int y = screenSize.height - size.height;
			int x = screenSize.width - size.width;
			setLocation(x, y);
		}
	}
	/** Méthode d'accès, modifie la valeur de l'encodage */
	public void setEncodage(String enc){encodage = enc;}
	/** Méthode d'accès, indique le nom de la table braille à utiliser */
	public void setTableBraille(String tb){tableBraille = tb;}
	/** Méthode d'accès, rend visible la ligne secondaire de l'éditeur */
	public void setAfficheLigneSecondaire(boolean b){ligneRes.setVisible(b);}
	
	/** 
	 * Implémente la méthode actionPerformed d'ActionListener
	 * Gère les actions des boutons et met à jour l'InputMap du JTextPane resultat en fonction de
	 * l'état du JCheckBox jcbPerkins
	 * @param evt l'objet ActionEvent
	 */
	public void actionPerformed(ActionEvent evt)
	{
		if(evt.getSource()==btEnregistrer){enregistrerFichier();}
		else if (evt.getSource() == btFermer){this.dispose();}
		else if (evt.getSource() == btUndo && undoMng.canUndo())
		{
			undoMng.undo();
			verifBtEdit();
		}
		else if (evt.getSource() == btRedo && undoMng.canRedo())
		{
			undoMng.redo();
			verifBtEdit();
		}
		else if (evt.getSource()==jcbPerkins)
		{
			if (jcbPerkins.isSelected())
			{
				/* Changement de l'action par défaut pour les touches de la saisie
				 * perkins (s, d, f j, k, l). Amélioration possible: plutôt que d'utiliser
				 * writableAction, fabriquer une Action qui ne fait rien
				 */
				InputMap inputMap = resultat.getInputMap();
		        KeyStroke key = KeyStroke.getKeyStroke('s');
		        inputMap.put(key, DefaultEditorKit.writableAction);
		        key = KeyStroke.getKeyStroke('d');
		        inputMap.put(key, DefaultEditorKit.writableAction);
		        key = KeyStroke.getKeyStroke('f');
		        inputMap.put(key, DefaultEditorKit.writableAction);
		        key = KeyStroke.getKeyStroke('j');
		        inputMap.put(key, DefaultEditorKit.writableAction);
		        key = KeyStroke.getKeyStroke('k');
		        inputMap.put(key, DefaultEditorKit.writableAction);
		        key = KeyStroke.getKeyStroke('l');
		        inputMap.put(key, DefaultEditorKit.writableAction);
		        
		        resultat.addKeyListener(this);
			}
			else
			{
				/* rétablissement de l'action par défaut associée au touches de la saisie perkins*/
				InputMap inputMap = resultat.getInputMap();
		        KeyStroke key = KeyStroke.getKeyStroke('s');
		        inputMap.put(key, DefaultEditorKit.defaultKeyTypedAction);
		        key = KeyStroke.getKeyStroke('d');
		        inputMap.put(key, DefaultEditorKit.defaultKeyTypedAction);
		        key = KeyStroke.getKeyStroke('f');
		        inputMap.put(key, DefaultEditorKit.defaultKeyTypedAction);
		        key = KeyStroke.getKeyStroke('j');
		        inputMap.put(key, DefaultEditorKit.defaultKeyTypedAction);
		        key = KeyStroke.getKeyStroke('k');
		        inputMap.put(key, DefaultEditorKit.defaultKeyTypedAction);
		        key = KeyStroke.getKeyStroke('l');
		        inputMap.put(key, DefaultEditorKit.defaultKeyTypedAction);
		        resultat.removeKeyListener(this);
			}
		}
		else if (evt.getSource()==btEmbosser)
		{
			String table1 = ConfigNat.getCurrentConfig().getTableBraille();
			String table2 = ConfigNat.getCurrentConfig().getTableEmbossage();
			
			//table brailles fichier transcrit/embossage différentes?
			//UPDATE : curieusement, le textconverter crlf utilisé dans embosseurldc a l'air de ne marcher qu'avec "tmpImp.txt"
			//donc on fait la transfo dans tous les cas.
			/*if(!table1.equals(table2))
			{
				//embosseur.convertiTable();
				//embosseur.Embosser(embosseur.getFichImp());*/
				
				String fichierTemp = "./tmp/sourceText.txt" ;
				String fichImp = "./tmp/tmpImp.txt";
				FileToolKit.saveStrToFile (resultat.getText(), fichierTemp);
				FileToolKit.convertBrailleFile(fichierTemp, fichImp,table1,table2,embosseur.getGest());
				embosseur.Embosser(fichImp);
			/*}
			else{embosseur.Embosser(fichier);}*/
		}
	}
	/** Vérifie l'état du manager undo et active ou désactive les boutons undo/redo */
	private void verifBtEdit() 
	{
		btUndo.setEnabled(undoMng.canUndo());
		btRedo.setEnabled(undoMng.canRedo());
	}
	/** Méthode redéfinie de ComponentListener
	 * Ne fait rien
	 * @param arg0 Le ComponentEvent
	 */
	public void componentHidden(ComponentEvent arg0){}
	/** Méthode redéfinie de ComponentListener
	 * Ne fait rien
	 * @param arg0 Le ComponentEvent
	 */
	public void componentMoved(ComponentEvent arg0){}
	/** Méthode redéfinie de ComponentListener
	 * Ne fait rien
	 * @param arg0 Le ComponentEvent
	 */
	public void componentShown(ComponentEvent arg0){}
	/** Méthode redéfinie de ComponentListener
	 * Mis à jour de l'affichage lors du redimensionement
	 * @param arg0 Le ComponentEvent
	 */
	public void componentResized(ComponentEvent arg0)
	{
		ConfigNat.getCurrentConfig().setWidthEditeur(getWidth());
		ConfigNat.getCurrentConfig().setHeightEditeur(getHeight());
		repaint();
	}

	/** Méthode redéfinie de JFrame
	 * met à jour les dimensions du JTextPane avant de faire le paint()
	 * 
	 * @param g L'objet Graphics
	 */
	public void paint(Graphics g)
	{
		repaintResultat();
		super.paint(g);
	}
	
	/** Méthode redéfinie de KeyListener
	 * Gère la saisie en mode Perkins
	 * L'affichage est réalisé dans la méthode keyReleased
	 * @param e L'objet KeyEvent intercepté
	 */
	public void keyPressed(KeyEvent e)
	{
		//System.out.println(e.getSource().getClass().getCanonicalName());
		char ch = ' ';
		ch = e.getKeyChar();
		
		//System.out.println("Caractère " + ch);

		switch (ch)
		{
			case 's':
				tabPoint[3]=true;
				nbTouches++;
			break;
			case 'd':
				tabPoint[4]=true;
				nbTouches++;
			break;
			case 'f':
				tabPoint[5]=true;
				nbTouches++;
			break;
			case 'l':
				tabPoint[0]=true;
				nbTouches++;
			break;
			case 'k':
				tabPoint[1]=true;
			break;
			case 'j':
				tabPoint[2]=true;
				nbTouches++;
			break;	
		}
		
	}

	/** Méthode redéfinie de KeyListener
	 * Gère la saisie en mode Perkins
	 * Réalise l'affichage du caractère braille dans le JTextPane resultat
	 * @param e L'objet KeyEvent intercepté
	 */
	public void keyReleased(KeyEvent e) 
	{
		char ch = e.getKeyChar();
		
		if(ch == 's' || ch == 'd' || ch=='f' || ch=='j' || ch=='k' || ch == 'l')
		{
			nbTouches--;
			if(nbTouches <= 0)
			{
				int res =0;
				for (int i=0;i<tabPoint.length;i++)
				{
					if (tabPoint[i])
					{
						res = res + (int)Math.pow(2, tabPoint.length - i -1);
						tabPoint[i] = false;
					}
				}
				//System.out.println("code " + res);
				if (res>0)
				{
					try
					{
						resultat.getDocument().insertString(resultat.getCaretPosition(), ptPerkins.get(Integer.toString(res)), resultat.getInputAttributes());
					}
					catch (Exception exp){}
				}
			}
		}
	}

	/** Méthode redéfinie de KeyListener
	 * Ne fait rien
	 * @param e Le KeyEvent
	 */
	public void keyTyped(KeyEvent e){}	
	
	/** Méthode redéfinie de CaretListener
	 * Si ligne secondaire (ligneRes) présente, charge le contenu de la ligne de résultat dans
	 * la ligne secondaire, avec le curseur en position
	 * @param ce Le CaretEvent
	 */
	public void caretUpdate(CaretEvent ce) 
	{
		if(ligneRes.isVisible())
		{
			int posCurseur = ce.getDot();
			//recherche du début de ligne
			/*int debut = posCurseur-1;
			if(debut<0){debut = 0;}*/
			int fin = posCurseur;
			boolean trouve = false;
			try 
			{
				/*while (!trouve && debut > 0)
				{
					if (!(resultat.getText(debut, 1).compareTo("\n")==0)){debut--;}
					else{trouve = true;debut++;}
				}
				trouve = false;*/
				while (!trouve && fin < resultat.getDocument().getLength())
				{
					if (!(resultat.getText(fin, 1).compareTo("\n")==0)){fin++;}
					else{trouve = true;fin--;}
				}
				//calcul du début de la ligne à représenter
				//debut = posCurseur - (posCurseur - debut)%longueurLigne;
				ligneRes.setText(resultat.getText(posCurseur, fin-posCurseur+1));//fin - debut + 1));
				ligneRes.setCaretPosition(0);
			} 
			catch (BadLocationException e){e.printStackTrace();}
				
		}
	}
	
	/** 
	 *	Enregistre le fichier
	 */
	private void enregistrerFichier()
	{
		/* a virer une fois qu'on est sur de filetoolkit
		
		try
		{
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fichier),encodage));
			bw.write(resultat.getText());
			message.setText("Fichier enregistré");			
			bw.close();
		}
		catch (IOException e)
		{
			System.out.println("erreur dans: " + e);
			message.setText("<html><p color=\"red\">Erreur lors de l'enregistrement</p></html>");
		}*/
		if (FileToolKit.saveStrToFile(resultat.getText(), fichier))
			message.setText("Fichier enregistré");	
		else
			message.setText("<html><p color=\"red\">Erreur lors de l'enregistrement</p></html>");
		repaint();
	}
	
	/**
	 * Affiche le fichier dans le JTextPane resultat et configure la ligne secondaire
	 * @param nomFichier nom du fichier transcrit
	 * @param police police principale
	 * @param taillePolice taille de la police principale
	 * @param police2 police secondaire
	 * @param taillePolice2 taille de la police secondaire
	 */
	public void afficheFichier(String nomFichier,String police, int taillePolice, String police2, int taillePolice2)
	{
		afficheFichier(nomFichier, police, taillePolice);
		
	    Font f = new Font(police2, Font.PLAIN, taillePolice2);
		ligneRes.setFont(f);
	}
	
	/**
	 * Affiche le fichier dans le JTextPane
	 * @param nomFichier nom du fichier transcrit
	 * @param police police principale
	 * @param taillePolice taille de la police principale
	 */
	public void afficheFichier(String nomFichier,String police, int taillePolice)
    {

		this.setTitle("NAT " + nomFichier);
	    fichier = nomFichier;
	    lFichier.setText(lFichier.getText() + fichier);
		//Préparation des styles pour le JTextPane
	    StyledDocument doc = resultat.getStyledDocument();
	    
	    MutableAttributeSet attrs = resultat.getInputAttributes();
	    Font fonteBraille = new Font(police, Font.PLAIN, taillePolice);

	    StyleConstants.setFontFamily(attrs, fonteBraille.getFamily());
	    StyleConstants.setFontSize(attrs,taillePolice);
	    
	    FontMetrics fm = getFontMetrics(fonteBraille);
	    tailleCaractere =  fm.charWidth('a');
		resultat.setPreferredSize(new Dimension((int)(tailleCaractere*(longueurLigne+3)),380));
		this.pack();
		//System.out.println( fonteBraille.getSize() + " " + taille );;
		resultat.setText("");
	    try
	      {
			BufferedReader raf = new BufferedReader(new InputStreamReader(new FileInputStream(nomFichier),encodage));
	      //RandomAccessFile raf = new RandomAccessFile(nomFichier, "r");
	      String ligne;
	      while ( (ligne = raf.readLine()) != null )
		  	{
	    	  doc.insertString(doc.getLength(), ligne + "\n", attrs);
	  	    }
	      }
		   catch (BadLocationException ble)
		    {
		  	    System.err.println("Impossible d'afficher le texte");
		  	}
		   catch (IOException e)
		     {
		     System.out.println("erreur dans: " + e);
		     }
			
			initialiseMap();
			/*
			 * test de la map perkins pour la saisie braille
			for(int i =0; i<ptPerkins.size();i++)
			{
				System.out.println(i +" " + ptPerkins.get(Integer.toString(i)));
			}*/
			resultat.addCaretListener(this);
			resultat.setCaretPosition(0);
			resultat.getDocument().addDocumentListener(this);
			resultat.getDocument().addUndoableEditListener(this);
	    }	  
	/**
	 * Initialise la HashMap d'équivalence entre les entités de la forme &pt123456; et leur
	 * valeur en binaire
	 * @return true si succès, false si erreur lors du chargement
	 * @exception IOException problème d'entrée sortie avec la table braille
	 * @exception NumberFormatException problème lors de la conversion des entités, la table ne doit pas être valide
	 */
	private boolean initialiseMap()
	{
		boolean retour = true;
		//création de la hashtable pt -> caractère 
		String fichierTable = "xsl/tablesBraille/" + tableBraille + ".ent";
		try
		{
			RandomAccessFile raf = new RandomAccessFile(fichierTable, "r");
			String ligne;
			String[] enregistrement;
	      int i=0;
	      
	      ligne = raf.readLine();
	      //on cherche le début des entitées
	      while(!ligne.startsWith("<!ENTITY") && ligne!=null)
	      {
	    	  ligne = raf.readLine();
	      }
	      if (ligne==null)
	      {
	    	  System.out.println("Le fichier" + fichierTable + "n'est pas un fichier valide");
	    	  message.setText("<html><br><p color=\"red\">Le fichier" + fichierTable + "n'est pas un fichier valide</p></html>");
	    	  retour =false;
	      }
			else
			{
				do
				{
					String pt = "0";
					String code ="";
				   enregistrement = ligne.split(" ");
				   if(!enregistrement[2].startsWith("\"&#"))
				   {
					  if (enregistrement[2].startsWith("\"&apos;")){code = "'";}
					  else if (enregistrement[2].startsWith("\"&quot;")){code = "\"";}
					  else if (enregistrement[2].startsWith("\"&lt;")){code = "<";}
					  else if (enregistrement[2].startsWith("\"&gt;")){code = ">";}
					  else {code = "&";}
					}
				   else{ code = Character.toString((char)(Integer.parseInt(enregistrement[2].substring(3, enregistrement[2].length()-3))));}
				   pt = convertitPoint2Int(enregistrement[1].substring(2,enregistrement[1].length()));
				   ptPerkins.put(pt, code);
				   i++;
				}
			   while ((ligne = raf.readLine()) != null && i<64);
			}
			raf.close();
		}
	   catch (IOException e)
	   {
		   System.out.println("erreur dans: " + e);
		   message.setText(":Erreur d'entrée/sortie lors du chargement");
	   }
	   catch (NumberFormatException e)
	   {
		   System.out.println("La table Braille n'est pas valide: " + e);
		   message.setText("<html><br> <p color=\"red\">La table Braille n'est pas valide</p></html>");
	   }
	   return retour;
	}

	/**
	 * Outil de conversion des entités 123456 par la notation "binaire"
	 * @param s La chaine d'origine sous forme 123456
	 * @return Une chaine représentant l'entier en base 10 obtenu par conversion binaire
	 */
	private String convertitPoint2Int(String s)
	{
		int retour = 0;
		if (s.indexOf("1")>= 0){retour = retour + 1;}
		if (s.indexOf("2")>= 0){retour = retour + 2;}
		if (s.indexOf("3")>= 0){retour = retour + 4;}
		if (s.indexOf("4")>= 0){retour = retour + 8;}
		if (s.indexOf("5")>= 0){retour = retour + 16;}
		if (s.indexOf("6")>= 0){retour = retour + 32;}
		return Integer.toString(retour);
	}
	/**
	 * Renvoie le texte contenu dans l'éditeur
	 * @return Le texte contenu dans le JTextPane
	 */
	public String getText(){return resultat.getText();}
	/**
	 * Recalcule la taille de resultat pour que le JTextPane prenne le maximum de place en hauteur
	 * mais conserve le nombre de caractères de la ligne braille en longueur
	 */
	private void repaintResultat()
	{
		int hauteurPanneau = getContentPane().getHeight(); 
		if(ligneRes.isVisible()){proportionPanneauAffichage = 1 -(lFichier.getHeight() - lesBoutons.getHeight() - ligneRes.getHeight())/hauteurPanneau ;}
		else{proportionPanneauAffichage = 1 - (hauteurPanneau - lFichier.getHeight() - lesBoutons.getHeight())/hauteurPanneau;}
		resultat.setPreferredSize(new Dimension((int)(tailleCaractere*(longueurLigne+3)),(int)(hauteurPanneau*proportionPanneauAffichage)));
		resultat.setSize(new Dimension((int)(tailleCaractere*(longueurLigne+3)),(int)(hauteurPanneau*proportionPanneauAffichage)));
		scrollRes.setPreferredSize(new Dimension(resultat.getWidth(),(int)(hauteurPanneau*proportionPanneauAffichage)));
		scrollRes.setSize(new Dimension(resultat.getWidth(),(int)(hauteurPanneau*proportionPanneauAffichage)));
		scrollRes.validate();
		panneauAffichage.setPreferredSize(new Dimension(resultat.getWidth(),(int)(hauteurPanneau- lFichier.getHeight()-lesBoutons.getHeight())));
		panneauAffichage.setSize(new Dimension(resultat.getWidth(),(int)(hauteurPanneau- lFichier.getHeight()-lesBoutons.getHeight())));
		panneauAffichage.validate();
		//panneauAffichage.validate();
	}
	public void changedUpdate(DocumentEvent de) 
	{
		message.setText("Fichier modifié");
		verifBtEdit();
	}
	public void insertUpdate(DocumentEvent de) 
	{
		message.setText("Fichier modifié");
		verifBtEdit();
	}
	public void removeUpdate(DocumentEvent de) 
	{
		message.setText("Fichier modifié");		
		verifBtEdit();
	}
	public void undoableEditHappened(UndoableEditEvent uee) 
	{
		undoMng.addEdit(uee.getEdit());
		verifBtEdit();
	}
}

