/*
editeurconfig - Editeur de Fichiers de Config de Jaxe

Copyright (C) 2011 Observatoire de Paris-Meudon

Ce programme est un logiciel libre ; vous pouvez le redistribuer et/ou le modifier conformément aux dispositions de la Licence Publique Générale GNU, telle que publiée par la Free Software Foundation ; version 2 de la licence, ou encore (à votre choix) toute version ultérieure.

Ce programme est distribué dans l'espoir qu'il sera utile, mais SANS AUCUNE GARANTIE ; sans même la garantie implicite de COMMERCIALISATION ou D'ADAPTATION A UN OBJET PARTICULIER. Pour plus de détail, voir la Licence Publique Générale GNU .

Vous devez avoir reçu un exemplaire de la Licence Publique Générale GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free Software Foundation Inc., 675 Mass Ave, Cambridge, MA 02139, Etats-Unis.
*/

package editeurconfig;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import javax.swing.border.*;
import java.util.*;
import org.w3c.dom.*;
import javax.swing.text.BadLocationException;


/**
* Affiche dans un jframe l'éditeur des textes général.
* Pour chaque langue on affiche: une description de la config, les Menus, les Eléments et les Exports
*/
public class EditeurDesTextes extends JFrame {
    
    private String laSelection = "";
    private ArrayList<String> listeAttributs = new ArrayList<String>();
    private InfosNoeud infosNoeud;
    private Node monNoeud;
    
    private FenetreEdition fe;
    private ListeElements listeElements;
    
    private Document doc;
    private Element racine;
    private Element menus;
    private Element affichage_noeuds;
    private Element exports;
    
    private JPanel panelAF;
    private JPanel panelFormulaire;
    
    private JPanel panelArbres;
    
    private JButton bRetirer;
    private JButton bOKK;
    
    
    public EditeurDesTextes(final FenetreEdition fe, final Document doc, final Element racine, final ListeElements listeElements) {
        super(Strings.get("titre.EditeurDesTextes"));
        this.fe = fe;
        this.doc = doc;
        this.racine = racine;
        this.listeElements = listeElements;
        menus = Outils.premierEnfantDeNom(racine, "MENUS");
        affichage_noeuds = Outils.premierEnfantDeNom(racine, "AFFICHAGE_NOEUDS");
        exports = Outils.premierEnfantDeNom(racine, "EXPORTS");
        
        setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        
        afficher();
    }
    
    
    
    private void afficher() {
        
        setLayout(new BorderLayout());
        
        final JPanel panelHaut = new JPanel(new FlowLayout(FlowLayout.CENTER));
        add(panelHaut,BorderLayout.NORTH);
        
        final JButton bAjouter = new JButton(new AbstractAction(Strings.get("bouton.AjouterLangue")) {
            public void actionPerformed(ActionEvent e) {
                ajouterLangue();
            }
        });
        panelHaut.add(bAjouter);
        
        bRetirer = new JButton(new AbstractAction(Strings.get("bouton.RetirerLangue")) {
            public void actionPerformed(ActionEvent e) {
                retirer();
            }
        });
        bRetirer.setEnabled(false);
        panelHaut.add(bRetirer);
        
        panelAF = new JPanel(new GridLayout(1,2));
        add(panelAF,BorderLayout.CENTER);
        
        panelArbres = new JPanel();
        /** Recuperation des langues **/    
        NodeList listeNoeud = racine.getElementsByTagName("STRINGS");
        
        for (int i=0; i<listeNoeud.getLength(); i++) {
            if (listeNoeud.item(i) instanceof Element) {
                Element strings = (Element)listeNoeud.item(i);
                remplirDOM(strings);
                creerArbre(strings);
            }
        }
        
        //panelArbres.setLayout(new GridLayout(listeNoeud.getLength(),1));
        panelArbres.setLayout(new BoxLayout(panelArbres, BoxLayout.Y_AXIS));
        panelArbres.setBorder(new TitledBorder(Strings.get("label.DefinirLesTextes")));
        //panelArbres.add(Box.createHorizontalGlue());
        
        /*final JScrollPane defilementArbres = new JScrollPane(panelArbres);
        defilementArbres.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        defilementArbres.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        defilementArbres.setPreferredSize(new Dimension(400, 800));*/
        panelAF.add(panelArbres);
        
        panelFormulaire = new JPanel();
        panelFormulaire.setLayout(new BoxLayout(panelFormulaire, BoxLayout.Y_AXIS));
        final JScrollPane defilementFormulaire = new JScrollPane(panelFormulaire);
        defilementFormulaire.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        defilementFormulaire.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        defilementFormulaire.setPreferredSize(new Dimension(500, 800));
        panelAF.add(defilementFormulaire);
        
        final JPanel panelBoutons = new JPanel(new FlowLayout());
        add(panelBoutons,BorderLayout.SOUTH);
        
        final JButton bFermer = new JButton(new AbstractAction(Strings.get("bouton.Fermer")) {
            public void actionPerformed(ActionEvent e) {
                nettoyerDOM();
                setVisible(false);
                fe.afficher();
            }
        });
        panelBoutons.add(bFermer);
        
        final JButton bTester = new JButton(new AbstractAction("Tester") {
            public void actionPerformed(ActionEvent e) {
                EditeurFichierConfig.convertToString(doc);
            }
        });
        //panelBoutons.add(bTester);
                
        pack();
        final Dimension dim = getSize();
        final Dimension ecran = getToolkit().getScreenSize();
        setLocation((ecran.width - dim.width)/2, (ecran.height - dim.height)/2);
        setVisible(true);
    }
    
    
    
    /**
    * Remplie le DOM, STRINGS_MENU, STRINGS_ELEMENT, STRINGS_EXPORT
    * @param L'élément strings
    */
    private void remplirDOM(final Element strings) {
        remplirStringMenu(menus, strings);
        
        if (affichage_noeuds != null) {
            for (Node n = affichage_noeuds.getFirstChild(); n != null; n = n.getNextSibling()) {
                if ("AFFICHAGE_ELEMENT".equals(n.getNodeName()))
                    enregistrerStringsElement(strings, ((Element)n).getAttribute("element"));
            }
        }
        
        if (exports != null) {
            for (Node n = exports.getFirstChild(); n != null; n = n.getNextSibling()) {
                if ("EXPORT".equals(n.getNodeName()))
                    enregistrerStringsExport(strings, ((Element)n).getAttribute("nom"));
            }
        }
    }
    
    
    /**
    * Remplie DOM, STRINGS_MENU
    * @param Le menu parent, l'élément 
    */
    private void remplirStringMenu(final Node menuP, final Element stringsM) {
        if (menuP != null) {
            for (Node n = menuP.getFirstChild(); n != null; n = n.getNextSibling()) {
                if ("MENU".equals(n.getNodeName())) {
                    Element strings_menu = enregistrerStringsMenu(stringsM, ((Element)n).getAttribute("nom"));
                    remplirStringMenu(n, strings_menu);
                }
            }
        }
    }
    
    
    /**
    * Crée un arbre JTree pour chaque langue
    * @param L'élément strings du DOM
    */
    private void creerArbre(final Element strings) {
        
        DefaultMutableTreeNode root = new DefaultMutableTreeNode(new InfosNoeud(strings));
        final DefaultTreeModel treemodel = new DefaultTreeModel(root);
        final JTree arbre = new JTree(treemodel);
        arbre.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        arbre.setShowsRootHandles(true);
        remplirArbre(root, treemodel, strings);
        
        final JScrollPane defilement = new JScrollPane(arbre);
        //defilement.setPreferredSize(new Dimension(70, 100));
        panelArbres.add(defilement);
        panelArbres.revalidate();
        
        arbre.addTreeSelectionListener(new TreeSelectionListener() {
            public void valueChanged(TreeSelectionEvent e) {
                Object selectionCourante = arbre.getLastSelectedPathComponent();
                if (selectionCourante != null) {
                    laSelection = selectionCourante.toString();
                    DefaultMutableTreeNode noeudSelectionne = (DefaultMutableTreeNode) selectionCourante;
                    deselectionner(arbre);
                    
                    if (noeudSelectionne.getUserObject() instanceof InfosNoeud) {
                        if (noeudSelectionne.isRoot()) {
                            panelFormulaire.setVisible(false);
                            bRetirer.setEnabled(true);
                        }
                        else {
                            panelFormulaire.setVisible(true);
                            bRetirer.setEnabled(false);
                        }
                        
                        infosNoeud = (InfosNoeud)noeudSelectionne.getUserObject();
                        monNoeud = infosNoeud.getNoeud();
                        
                        if ("DESCRIPTION_CONFIG".equals(monNoeud.getNodeName()))
                            afficherTextesDescriptionConfig(strings);
                        
                        if ("STRINGS_MENU".equals(monNoeud.getNodeName()))
                            afficherTextesMenu(strings);
                        if ("STRINGS_ELEMENT".equals(monNoeud.getNodeName()))
                            afficherTextesElement(strings);
                        
                        if ("STRINGS_EXPORT".equals(monNoeud.getNodeName()))
                            afficherTextesExport(strings);
                    }
                    else
                        panelFormulaire.setVisible(false);
                }
                else {
                    panelFormulaire.setVisible(false);
                    bRetirer.setEnabled(false);
                }
            }
        });
    }
    
    
    /**
    * Déselectionne les autres arbres
    */
    private void deselectionner(final JTree arbre) {
        for (int i=0; i<panelArbres.getComponentCount(); i++) {
            Component comp = panelArbres.getComponent(i);
            for (int j=0; j<((JScrollPane)comp).getComponentCount(); j++) {
                Component comp1 = ((JScrollPane)comp).getComponent(j);
                if (comp1 instanceof JViewport) {
                    for (int k=0; k<((JViewport)comp1).getComponentCount(); k++) {
                        Component monArbre = ((JViewport)comp1).getComponent(k);
                        if (monArbre instanceof JTree) {
                            if ((JTree)monArbre != arbre) {
                                ((JTree)monArbre).clearSelection();
                            }
                        }
                    }
                }
            }
        }
    }
    
    
    /**
    * Remplie l'arbre
    * @param la racine root
    * @param le modèle de l'arbre
    */
    private void remplirArbre(final DefaultMutableTreeNode root, final DefaultTreeModel treemodel, final Element strings) {
        Element description_config = Outils.premierEnfantDeNom(strings, "DESCRIPTION_CONFIG");
        if (description_config == null)
            description_config = enregistrerDescriptionConfig(strings, null);
        DefaultMutableTreeNode descriptionConfig = new DefaultMutableTreeNode(new InfosNoeud(description_config));
        root.add(descriptionConfig);
        
        if (menus != null) {
            DefaultMutableTreeNode textesMenu = new DefaultMutableTreeNode(Strings.get("texte.textesMenu"));
            root.add(textesMenu);
            remplirTextesMenu(strings, textesMenu);
        }
        
        if (affichage_noeuds != null) {
            DefaultMutableTreeNode textesElement = new DefaultMutableTreeNode(Strings.get("texte.textesElement"));
            root.add(textesElement);
            remplirTextesElement(strings, textesElement);
        }
   
        if (exports != null) {
            DefaultMutableTreeNode textesExport = new DefaultMutableTreeNode(Strings.get("texte.textesExport"));
            root.add(textesExport);
            remplirTextesExport(strings, textesExport);
        }
        
        treemodel.reload();
    }
    
    
    
    /**
    * Remplie le noeud Textes pour Menu par l'ensemble des menus
    * @param le noeud textesMenu
    */
    private void remplirTextesMenu(final Node strings, final DefaultMutableTreeNode textesMenu) {
        for (Node n = strings.getFirstChild(); n != null; n = n.getNextSibling()) {
            if ("STRINGS_MENU".equals(n.getNodeName())) {
                DefaultMutableTreeNode nouveauNoeud = new DefaultMutableTreeNode(new InfosNoeud(n));
                textesMenu.add(nouveauNoeud);
                remplirTextesMenu(n, nouveauNoeud);
            }
        }
    }
    
    /**
    * Remplie le noeud Textes pour Element par l'ensemble des éléments
    * @param le noeud textesElement
    */
    private void remplirTextesElement(final Element strings, final DefaultMutableTreeNode textesElement) {
        for (Node n = strings.getFirstChild(); n != null; n = n.getNextSibling()) {
            if ("STRINGS_ELEMENT".equals(n.getNodeName())) {
                DefaultMutableTreeNode nouveauNoeud = new DefaultMutableTreeNode(new InfosNoeud(n));
                textesElement.add(nouveauNoeud);
            }
        }
    }
    
    /**
    * Remplie le noeud Textes pour Export par l'ensemble des exports
    * @param le noeud textesExport
    */
    private void remplirTextesExport(final Element strings, final DefaultMutableTreeNode textesExport) {
        for (Node n = strings.getFirstChild(); n != null; n = n.getNextSibling()) {
            if ("STRINGS_EXPORT".equals(n.getNodeName())) {
                DefaultMutableTreeNode nouveauNoeud = new DefaultMutableTreeNode(new InfosNoeud(n));
                textesExport.add(nouveauNoeud);
            }
        }
    }
    
    
    
    /**
    * Ajoute une nouvelle langue
    */
    private void ajouterLangue() {
        final JDialog jd = new JDialog(this, Strings.get("titre.SaisirLaLangue"));
        final JPanel panel = new JPanel(new FlowLayout());
        
        final JTextField texte = new JTextField(6);
    
        panel.add(texte);
        texte.addKeyListener(new KeyListener() {
            public void keyTyped(KeyEvent e) {
                if(texte.getText().length() > 2 || texte.getText().length() < 2) {
                    texte.setForeground(Color.red);
                    bOKK.setEnabled(false);
                }
                else {
                    texte.setForeground(Color.black);
                    bOKK.setEnabled(true);
                }
            }
            public void keyPressed(KeyEvent e) {
                if(texte.getText().length() > 2 || texte.getText().length() < 2) {
                    texte.setForeground(Color.red);
                    bOKK.setEnabled(false);
                }
                else {
                    texte.setForeground(Color.black);
                    bOKK.setEnabled(true);
                }
            }
            public void keyReleased(KeyEvent e) {
                if(texte.getText().length() > 2 || texte.getText().length() < 2) {
                    texte.setForeground(Color.red);
                    bOKK.setEnabled(false);
                }
                else {
                    texte.setForeground(Color.black);
                    bOKK.setEnabled(true);
                }
            }
        });
        
        final JButton bAnnuler = new JButton(new AbstractAction(Strings.get("bouton.Annuler")) {
            public void actionPerformed( ActionEvent e ) {
                jd.setVisible(false);
            }
        });
        panel.add(bAnnuler);
        
        bOKK = new JButton(new AbstractAction(Strings.get("bouton.OK")) {
            public void actionPerformed( ActionEvent e ) {
                if (!codeLangueValide(texte.getText())) {
                    JOptionPane.showMessageDialog(jd, Strings.get("message.CodeLangueNonValide"));
                    texte.requestFocus();
                    texte.selectAll();
                }
                else {
                    Element strings = enregistrerStrings(texte.getText());
                    if (strings == null) {
                        JOptionPane.showMessageDialog(jd, Strings.get("message.LangueExiste"));
                        texte.requestFocus();
                        texte.selectAll();
                    }
                    else {
                        jd.setVisible(false);
                        remplirDOM(strings);
                        creerArbre(strings);
                    }
                }
            }
        });
        
        panel.add(bOKK);
        bOKK.setEnabled(false);
        
        jd.add(panel);
        jd.pack();
        final Dimension dim = getSize();
        final Dimension ecran = getToolkit().getScreenSize();
        jd.setLocation((ecran.width - dim.width)/2, (ecran.height - dim.height)/2);
        jd.setVisible(true);
    }
    
    
    /**
    * Retire la langue sélectionnée
    */
    private void retirer() {
        if (JOptionPane.showConfirmDialog(this, Strings.get("message.SupprimerCetteLangue"), "", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
            Element strings = (Element)monNoeud;
            if (strings != null) {
                racine.removeChild(strings);
                EditeurFichierConfig.setModif(true);
            
                for (int i=0; i<panelArbres.getComponentCount(); i++) {
                    Component comp = panelArbres.getComponent(i);
                    for (int j=0; j<((JScrollPane)comp).getComponentCount(); j++) {
                        Component comp1 = ((JScrollPane)comp).getComponent(j);
                        if (comp1 instanceof JViewport) {
                            for (int k=0; k<((JViewport)comp1).getComponentCount(); k++) {
                                Component monArbre = ((JViewport)comp1).getComponent(k);
                                if (monArbre instanceof JTree) {
                                    if (((JTree)monArbre).getModel().getRoot().toString().equals(strings.getAttribute("langue"))) {
                                        panelArbres.remove(comp);
                                        panelArbres.revalidate();
                                        panelArbres.repaint();
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else System.out.println("strings NULL");
        }
    }
    
    
    
    /**
    * Affiche le formulaire pour Description Config
    */
    private void afficherTextesDescriptionConfig(final Element strings) {
        panelFormulaire.removeAll();
        panelFormulaire.setBorder(new TitledBorder(Strings.get("label.TextePour")+" "+laSelection));
        
        final JPanel panDescription = new JPanel(new GridLayout(2,1));
        panelFormulaire.add(panDescription);
        JLabel description_l = new JLabel(Strings.get("label.DescriptionConfig")+": ");
        JTextArea description_t = new JTextArea(4, 12);
        description_t.setLineWrap(true);
        description_t.setWrapStyleWord(true);
        JScrollPane scrollDesc = new JScrollPane(description_t);
        scrollDesc.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollDesc.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        panDescription.add(description_l);
        panDescription.add(scrollDesc);
        
        Element description_config = Outils.premierEnfantDeNom(strings, "DESCRIPTION_CONFIG");
        if (description_config != null)
            description_t.setText(Outils.getValeurElement(description_config));
        
        // écouteur sur Description
        description_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurDescription(de, strings);
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurDescription(de, strings);
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurDescription(de, strings);
            }
        });
        
        panelFormulaire.revalidate();
    }
    
    
    
    
    /**
    * Affiche le formulaire pour Textes Menu
    * @param L'élément strings du DOM
    */
    private void afficherTextesMenu(final Element strings) {
        panelFormulaire.removeAll();
        panelFormulaire.setBorder(new TitledBorder(Strings.get("label.TextePour")+" "+laSelection));
        
        final Element strings_menu = (Element)monNoeud;
        
        afficherTitreDocumentation(strings_menu, panelFormulaire);
                
        panelFormulaire.revalidate();
    }
    
    
    /**
    * Affiche le formulaire pour Textes Element
    * @param L'élément strings du DOM
    */
    private void afficherTextesElement(final Element strings) {
        panelFormulaire.removeAll();
        panelFormulaire.setBorder(new TitledBorder(Strings.get("label.TextePour")+" "+laSelection));
        
        final Element strings_element = (Element)monNoeud;
        final Element affichage_element = Outils.getElementSelectionne(affichage_noeuds, "AFFICHAGE_ELEMENT", infosNoeud.toString(), "element");
        
        afficherTitreDocumentation(strings_element, panelFormulaire);
        
        for (Node n = affichage_element.getFirstChild(); n != null; n = n.getNextSibling()) {
            if (n instanceof Element && "VALEUR_SUGGEREE".equals(n.getNodeName())) {
                afficherTitreValeur(strings_element, (Element)n, panelFormulaire);
            }
        }
        
        if (listeAttributs != null)
            listeAttributs.clear();
        listeAttributs = listeElements.getAttributElement(listeElements.getReferenceElement(infosNoeud.toString()));
        if (listeAttributs != null) {
            for (int i = 0; i < listeAttributs.size(); i++) 
                afficherTextesAttribut(strings_element, affichage_element, listeAttributs.get(i).toString());
        }
        
        panelFormulaire.revalidate();
    }
    
    
    
    
    /**
    * Affiche le panel Titre Documentation
    * @param L'élément parent
    * @param panel destination
    */
    private void afficherTitreDocumentation(final Element element_parent, final JPanel panelDest) {
        final JPanel panTitre = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panelDest.add(panTitre);
        JLabel titre_l = new JLabel(Strings.get("label.Titre")+": ");
        JTextField titre_t = new JTextField(15);
        panTitre.add(titre_l);
        panTitre.add(titre_t);
        
        Element titre = Outils.premierEnfantDeNom(element_parent, "TITRE");
        if (titre != null)
            titre_t.setText(Outils.getValeurElement(titre));
            
        // écouteur sur titre
        titre_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurTitre(de, element_parent);
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurTitre(de, element_parent);
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurTitre(de, element_parent);
            }
        });
        
        final JPanel panDocumentation = new JPanel(new GridLayout(2,1));
        panelDest.add(panDocumentation);
        JLabel documentation_l = new JLabel(Strings.get("label.Documentation")+": ");
        JTextArea documentation_t = new JTextArea(4, 12);
        documentation_t.setLineWrap(true);
        documentation_t.setWrapStyleWord(true);
        JScrollPane scrollDoc = new JScrollPane(documentation_t);
        scrollDoc.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollDoc.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        panDocumentation.add(documentation_l);
        panDocumentation.add(scrollDoc);
        
        Element documentation = Outils.premierEnfantDeNom(element_parent, "DOCUMENTATION");
        if (documentation != null)
            documentation_t.setText(Outils.getValeurElement(documentation));
            
        // écouteur sur documentation
        documentation_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurDocumentation(de, element_parent);
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurDocumentation(de, element_parent);
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurDocumentation(de, element_parent);
            }
        });
    }
    
    
    
    
    /**
    * Affiche le panel Titre Valeur
    * @param L'élément parent
    * @param L'élément valeur_suggerre
    * @param panel destination
    */
    private void afficherTitreValeur(final Element element_parent, final Element valeur_suggerre, final JPanel panelDest) {
        final JPanel panTitreValeur = new JPanel(new FlowLayout(FlowLayout.LEFT));
        panelDest.add(panTitreValeur);
        final String valeur = Outils.getValeurElement(valeur_suggerre);
        JLabel titreValeur_l = new JLabel(Strings.get("label.TitreValeur")+" '"+valeur+"'");
        JTextField titreValeur_t = new JTextField(15);
        if (valeur != null) {
            panTitreValeur.add(titreValeur_l);
            panTitreValeur.add(titreValeur_t);
        }
        
        Element titre_valeur = Outils.getElementSelectionne(element_parent, "TITRE_VALEUR", valeur, "valeur");
        if (titre_valeur != null)
            titreValeur_t.setText(Outils.getValeurElement(titre_valeur));
            
        // écouteur sur titre valeur
        titreValeur_t.getDocument().addDocumentListener(new DocumentListener() {
            public void changedUpdate(DocumentEvent de) {
                ecouteurTitreValeur(de, element_parent, valeur);
            }
            public void insertUpdate(DocumentEvent de) {
                ecouteurTitreValeur(de, element_parent, valeur);
            }
            public void removeUpdate(DocumentEvent de) {
                ecouteurTitreValeur(de, element_parent, valeur);
            }
        });
    }
    
    
    
    /**
    * Affiche le panel Textes Attribut
    * @param L'élément strings_element
    * @param L'élément affichage_element
    * @param L'attribut de l'élément
    */
    private void afficherTextesAttribut(final Element strings_element, final Element affichage_element, final String attr) {
        final JPanel panTextesAttribut = new JPanel();
        panTextesAttribut.setLayout(new BoxLayout(panTextesAttribut, BoxLayout.Y_AXIS));
        //panTextesAttribut.setBorder(BorderFactory.createLineBorder(Color.cyan));
        panTextesAttribut.setBorder(new TitledBorder(Strings.get("label.TextesAttribut")+" '"+attr+"'"));
        panelFormulaire.add(panTextesAttribut);
        
        final Element strings_attribut = enregistrerStringsAttribut(strings_element, attr);
        
        afficherTitreDocumentation(strings_attribut, panTextesAttribut);
        
        Element affichage_attribut = Outils.getElementSelectionne(affichage_element, "AFFICHAGE_ATTRIBUT", attr, "attribut");
        
        if (affichage_attribut != null) {
            for (Node n = affichage_attribut.getFirstChild(); n != null; n = n.getNextSibling()) {
                if (n instanceof Element && "VALEUR_SUGGEREE".equals(n.getNodeName())) {
                    afficherTitreValeur(strings_attribut, (Element)n, panTextesAttribut);
                }
            }
        }
    }
    
    
    /**
    * Affiche le formulaire pour Textes Export
    * @param L'élément strings du DOM
    */
    private void afficherTextesExport(final Element strings) {
        panelFormulaire.removeAll();
        panelFormulaire.setBorder(new TitledBorder(Strings.get("label.TextePour")+" "+laSelection));
        
        final Element strings_export = (Element)monNoeud;
        
        afficherTitreDocumentation(strings_export, panelFormulaire);
        
        panelFormulaire.revalidate();
    }
    
    /****************************** Ecouteurs *******************************************/
    /**
    * Ecouteur sur le champ Description
    * @param Un DocumentEvent
    * @param L'élément strings du DOM
    */
    private void ecouteurDescription(final DocumentEvent de, final Element strings) {
        javax.swing.text.Document source = de.getDocument();
        try {
            String texteD = source.getText(0, source.getLength());
            enregistrerDescriptionConfig(strings, texteD);
            
            EditeurFichierConfig.setModif(true);
        }
        catch (BadLocationException bex) {
            System.out.println(bex);
        }
    }
    
    
    
    /**
    * Ecouteur sur le champ Titre
    * @param Un DocumentEvent
    * @param L'élément parent
    */
    private void ecouteurTitre(final DocumentEvent de, final Element element_parent) {
        javax.swing.text.Document source = de.getDocument();
        try {
            String texteTitre = source.getText(0, source.getLength());
            enregistrerTitre(element_parent, texteTitre);
            
            EditeurFichierConfig.setModif(true);
        }
        catch (BadLocationException bex) {
            System.out.println(bex);
        }
    }
    
    /**
    * Ecouteur sur le champ Documentation
    * @param Un DocumentEvent
    * @param L'élément parent
    */
    private void ecouteurDocumentation(final DocumentEvent de, final Element element_parent) {
        javax.swing.text.Document source = de.getDocument();
        try {
            String texteDocumentation = source.getText(0, source.getLength());
            enregistrerDocumentation(element_parent, texteDocumentation);
            
            EditeurFichierConfig.setModif(true);
        }
        catch (BadLocationException bex) {
        }
    }
    
    /**
    * Ecouteur sur le champ Titre valeur
    * @param Un DocumentEvent
    * @param L'élément parent
    */
    private void ecouteurTitreValeur(final DocumentEvent de, final Element element_parent, final String valeur) {
        javax.swing.text.Document source = de.getDocument();
        try {
            String texteTitreV = source.getText(0, source.getLength());
            enregistrerTitreValeur(element_parent, valeur, texteTitreV);
            
            EditeurFichierConfig.setModif(true);
        }
        catch (BadLocationException bex) {
            System.out.println(bex);
        }
    }
    
    
    
    /*********************************** Opérations DOM *****************************************/
    // STRINGS
    private Element enregistrerStrings(final String langue) {
        Element e = Outils.getElementSelectionne(racine, "STRINGS", langue.toLowerCase(), "langue");
        if (e == null) {
            Element strings = doc.createElement("STRINGS");
            racine.appendChild(strings);
            if (langue != null)
                strings.setAttribute("langue", langue.toLowerCase());
                
            EditeurFichierConfig.setModif(true);
            
            return strings;
        }
        else
            return null;
    }
    
    
    // DESCRIPTION_CONFIG
    private Element enregistrerDescriptionConfig(final Element strings, final String valeurD) {
        Element description_config = Outils.premierEnfantDeNom(strings, "DESCRIPTION_CONFIG");
        if (description_config == null) {
            description_config = doc.createElement("DESCRIPTION_CONFIG");
            strings.insertBefore(description_config, Outils.premierEnfantDeNom(strings, "STRINGS_MENU"));
        }
        if (valeurD != null)
            Outils.setValeurElement(doc, description_config, valeurD);
            
        EditeurFichierConfig.setModif(true);
        
        return description_config;
    }
    
    // STRINGS_MENU
    private Element enregistrerStringsMenu(final Element stringsM, final String titre) {
        Element strings_menu = Outils.getElementSelectionne(stringsM, "STRINGS_MENU", titre, "menu");
        if (strings_menu == null) {
            strings_menu = doc.createElement("STRINGS_MENU");
            if (Outils.premierEnfantDeNom(stringsM, "STRINGS_ELEMENT") != null)
                stringsM.insertBefore(strings_menu, Outils.premierEnfantDeNom(stringsM, "STRINGS_ELEMENT"));
            else
                stringsM.appendChild(strings_menu);
            strings_menu.setAttribute("menu", titre);
            
            EditeurFichierConfig.setModif(true);
        }
        return strings_menu;
    }
    
    // STRINGS_ELEMENT
    private Element enregistrerStringsElement(final Element strings, final String titre) {
        Element strings_element = Outils.getElementSelectionne(strings, "STRINGS_ELEMENT", titre, "element");
        if (strings_element == null) {
            strings_element = doc.createElement("STRINGS_ELEMENT");
            strings.appendChild(strings_element);
            strings_element.setAttribute("element", titre);
            
            EditeurFichierConfig.setModif(true);
        }
        return strings_element;
    }
    
    // TITRE
    private void enregistrerTitre(final Element parent, final String texteTitre) {
        Element titre = Outils.premierEnfantDeNom(parent, "TITRE");
        if (titre == null) {
            titre = doc.createElement("TITRE");
            parent.appendChild(titre);
        }
        Outils.setValeurElement(doc, titre, texteTitre);
    }
    
    // DOCUMENTATION
    private void enregistrerDocumentation(final Element parent, final String texteDocumentation) {
        Element documentation = Outils.premierEnfantDeNom(parent, "DOCUMENTATION");
        if (documentation == null) {
            documentation = doc.createElement("DOCUMENTATION");
            parent.appendChild(documentation);
        }
        Outils.setValeurElement(doc, documentation, texteDocumentation);
    }
    
    // STRINGS_ATTRIBUT
    private Element enregistrerStringsAttribut(final Element strings_element, final String nomAttribut) {
        Element strings_attribut = Outils.getElementSelectionne(strings_element, "STRINGS_ATTRIBUT", nomAttribut, "attribut");
        if (strings_attribut == null) {
            strings_attribut = doc.createElement("STRINGS_ATTRIBUT");
            strings_element.appendChild(strings_attribut);
        }
        strings_attribut.setAttribute("attribut", nomAttribut);
        return strings_attribut;
    }
    
    // TITRE_VALEUR
    private Element enregistrerTitreValeur(final Element element_parent, final String valeur, final String texteTitreV) {
        Element titre_valeur = Outils.getElementSelectionne(element_parent, "TITRE_VALEUR", valeur, "valeur");
        if (titre_valeur == null) {
            titre_valeur = doc.createElement("TITRE_VALEUR");
            element_parent.appendChild(titre_valeur);
        }
        titre_valeur.setAttribute("valeur", valeur);
        Outils.setValeurElement(doc, titre_valeur, texteTitreV);
        
        return titre_valeur;
    }
    
    // STRINGS_EXPORT
    private Element enregistrerStringsExport(final Element strings, final String titre) {
        Element strings_export = Outils.getElementSelectionne(strings, "STRINGS_EXPORT", titre, "export");
        if (strings_export == null) {
            strings_export = doc.createElement("STRINGS_EXPORT");
            strings.appendChild(strings_export);
            strings_export.setAttribute("export", titre);
            
            EditeurFichierConfig.setModif(true);
        }
        return strings_export;
    }
    
    
    /**
    * Vérifie le code de la langue suivant le format défini par la norme ISO-639 (2 lettres minuscules) 
    */
    private boolean codeLangueValide(final String langue) {
        String[] langages = Locale.getISOLanguages();
        if (Arrays.asList(langages).contains(langue))
            return true;
        else
            return false;
    }
    
    // nettoyer le DOM des éléments vide
    private void nettoyerDOM() {
        nettoyer_STRINGS_MENU();
        nettoyer_STRINGS_ELEMENT();
        nettoyer_STRINGS_ATTRIBUT();
        nettoyer_STRINGS_EXPORT();
    }
    
    private void nettoyer_STRINGS_MENU() {
        NodeList listeNoeud = racine.getElementsByTagName("STRINGS_MENU");
        for (int i=0; i<listeNoeud.getLength(); i++) {
            if (listeNoeud.item(i) instanceof Element) {
                Element element_parent = (Element)listeNoeud.item(i);
                for (Node n = element_parent.getFirstChild(); n != null; n = n.getNextSibling())
                    if ("TITRE".equals(n.getNodeName()) && (!n.hasChildNodes() || "".equals(Outils.getValeurElement((Element)n))))
                        element_parent.removeChild(n);
                        
                for (Node n1 = element_parent.getFirstChild(); n1 != null; n1 = n1.getNextSibling())
                    if ("DOCUMENTATION".equals(n1.getNodeName()) && (!n1.hasChildNodes() || "".equals(Outils.getValeurElement((Element)n1))))
                        element_parent.removeChild(n1);
            }
        }
    }
    
    private void nettoyer_STRINGS_ELEMENT() {
        NodeList listeNoeud = racine.getElementsByTagName("STRINGS_ELEMENT");
        for (int i=0; i<listeNoeud.getLength(); i++) {
            if (listeNoeud.item(i) instanceof Element) {
                Element element_parent = (Element)listeNoeud.item(i);
                for (Node n = element_parent.getFirstChild(); n != null; n = n.getNextSibling())
                    if ("TITRE".equals(n.getNodeName()) && (!n.hasChildNodes() || "".equals(Outils.getValeurElement((Element)n))))
                        element_parent.removeChild(n);
                        
                for (Node n1 = element_parent.getFirstChild(); n1 != null; n1 = n1.getNextSibling())
                    if ("DOCUMENTATION".equals(n1.getNodeName()) && (!n1.hasChildNodes() || "".equals(Outils.getValeurElement((Element)n1))))
                        element_parent.removeChild(n1);
            }
        }
    }
    
    private void nettoyer_STRINGS_ATTRIBUT() {
        NodeList listeNoeud = racine.getElementsByTagName("STRINGS_ATTRIBUT");
        for (int i=0; i<listeNoeud.getLength(); i++) {
            if (listeNoeud.item(i) instanceof Element) {
                Element element_parent = (Element)listeNoeud.item(i);
                for (Node n = element_parent.getFirstChild(); n != null; n = n.getNextSibling())
                    if ("TITRE".equals(n.getNodeName()) && (!n.hasChildNodes() || "".equals(Outils.getValeurElement((Element)n))))
                        element_parent.removeChild(n);
                        
                for (Node n1 = element_parent.getFirstChild(); n1 != null; n1 = n1.getNextSibling())
                    if ("DOCUMENTATION".equals(n1.getNodeName()) && (!n1.hasChildNodes() || "".equals(Outils.getValeurElement((Element)n1))))
                        element_parent.removeChild(n1);
            }
        }
    }
    
    private void nettoyer_STRINGS_EXPORT() {
        NodeList listeNoeud = racine.getElementsByTagName("STRINGS_EXPORT");
        for (int i=0; i<listeNoeud.getLength(); i++) {
            if (listeNoeud.item(i) instanceof Element) {
                Element element_parent = (Element)listeNoeud.item(i);
                for (Node n = element_parent.getFirstChild(); n != null; n = n.getNextSibling())
                    if ("TITRE".equals(n.getNodeName()) && (!n.hasChildNodes() || "".equals(Outils.getValeurElement((Element)n))))
                        element_parent.removeChild(n);
                        
                for (Node n1 = element_parent.getFirstChild(); n1 != null; n1 = n1.getNextSibling())
                    if ("DOCUMENTATION".equals(n1.getNodeName()) && (!n1.hasChildNodes() || "".equals(Outils.getValeurElement((Element)n1))))
                        element_parent.removeChild(n1);
            }
        }
    }
    
    
    
}
