/*
 * Copyright 
 *   2005 axYus - www.axyus.com
 *   2005 C.Marchand - christophe.marchand@axyus.com
 * 
 * This file is part of XEMELIOS.
 * 
 * XEMELIOS 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, or
 * (at your option) any later version.
 * 
 * XEMELIOS 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 XEMELIOS; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package fr.gouv.finances.cp.xemelios.ui.export;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JRootPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;

import org.apache.log4j.Logger;
import org.jdesktop.swingx.JXTreeTable;
import org.jdesktop.swingx.treetable.DefaultTreeTableModel;

import fr.gouv.finances.cp.utils.xml.marshal.XmlOutputter;
import fr.gouv.finances.dgfip.xemelios.common.config.ChampModel;
import fr.gouv.finances.dgfip.xemelios.common.config.DocumentModel;
import fr.gouv.finances.dgfip.xemelios.common.config.ElementModel;
import fr.gouv.finances.dgfip.xemelios.common.config.EtatModel;
import fr.gouv.finances.dgfip.xemelios.data.DataLayerManager;
import fr.gouv.finances.dgfip.xemelios.export.ConfigModel;
import fr.gouv.finances.dgfip.xemelios.export.ConfigParser;
import fr.gouv.finances.dgfip.xemelios.export.ExportChampModel;
import fr.gouv.finances.dgfip.xemelios.export.ExportElementModel;
import fr.gouv.finances.dgfip.xemelios.export.ExportModel;
import fr.gouv.finances.cp.xemelios.ui.MainWindow;
import fr.gouv.finances.dgfip.xemelios.auth.XemeliosUser;
import java.io.OutputStreamWriter;

/**
 *
 * @author  nicolas.lecorre
 */
public class EditConfig extends JDialog {

    private static final long serialVersionUID = 5669669876743219771L;
    private static Logger logger = Logger.getLogger(EditConfig.class);
    private DocumentModel dm;
    private ConfigModel cm;
    private String docID,  etatID;
    // la structure contenant la configuration
    private ExportModel data = new ExportModel(ExportModel.QN);
    // la structure contenant la configuration à modifier
    private ExportModel dataToBeModified = null;
    private AbstractAction escapeAction;
    private XemeliosUser user;

    /** Creates new form EditConfig */
    public EditConfig(JDialog parent, DocumentModel d, ConfigModel c, XemeliosUser user) {
        super(parent);
        this.dm = d;
        docID = dm.getId();
        this.cm = c;
        etatID = cm.getEtatID();
        this.user = user;
        try {
            ConfigParser cp = new ConfigParser();
            cp.parse(new ByteArrayInputStream(c.getConfigLines()));
            dataToBeModified = (ExportModel) cp.getMarshallable();
        } catch (Exception e) {
            logger.error("Erreur lors de la lecture de la configuration à modifier", e);
        }
        initComponents();
        tCode.setText(c.getCode());
        tLibelle.setText(c.getLibelle());
        setLocationRelativeTo(getParent());
        treeTable.setTreeTableModel(createModel(dm, cm.getEtatID()));
        updateModel();
        treeTable.addTreeExpansionListener(new TreeExpansionListener() {

            public void treeCollapsed(TreeExpansionEvent event) {
            }

            public void treeExpanded(TreeExpansionEvent event) {
                treeTable.packAll();
            }
        });
        treeTable.getColumnModel().getColumn(1).setMaxWidth(25);
        treeTable.expandAll();
    }

    public EditConfig(JDialog parent, DocumentModel d, String etatID) {
        super(parent);
        this.dm = d;
        docID = dm.getId();
        this.etatID = etatID;
        initComponents();
        setLocationRelativeTo(getParent());
        treeTable.setTreeTableModel(createModel(dm, etatID));
        treeTable.addTreeExpansionListener(new TreeExpansionListener() {

            public void treeCollapsed(TreeExpansionEvent event) {
            }

            public void treeExpanded(TreeExpansionEvent event) {
                treeTable.packAll();
            }
        });
        treeTable.getColumnModel().getColumn(1).setMaxWidth(25);
        treeTable.expandAll();
    }

    /**
     * Merge le model créé à partir du fichier métier Xemelios et de la configuration que l'on tente de modifier
     */
    private void updateModel() {
        if (dataToBeModified != null) {
            for (ExportElementModel eemDest : data.getEnfants()) {
                String eID = eemDest.getId();
                for (ExportElementModel eemRef : dataToBeModified.getEnfants()) {
                    if (eemRef.getId().equals(eID)) {
                        updateEEM(eemRef, eemDest);
                    }
                }
            }
        }
    }

    private void updateEEM(ExportElementModel reference, ExportElementModel destination) {
        for (ExportChampModel ecmDest : destination.getChamps()) {
            String cID = ecmDest.getId();
            for (ExportChampModel ecmRef : reference.getChamps()) {
                if (ecmRef.getId().equals(cID)) {
                    ecmDest.setSelectionne(ecmRef.isSelectionne());
                }
            }
        }
        for (ExportElementModel eemDest : destination.getEnfants()) {
            String eID = eemDest.getId();
            for (ExportElementModel eemRef : reference.getEnfants()) {
                if (eemRef.getId().equals(eID)) {
                    updateEEM(eemRef, eemDest);
                }
            }
        }
    }

    private ConfigTreeTableModel createModel(DocumentModel dm, String etatID) {
        ConfigTreeTableModel ret = new ConfigTreeTableModel(data);
        EtatModel em = dm.getEtatById(etatID);
        ElementModel emROOT = null;
        for (String k : em.getElements().keySet()) {
            ElementModel tmp = em.getElements().get(k);
            if (tmp.getSimpleParent() == null) {
                emROOT = tmp;
                break;
            }
        }
        // maintenant, on dispose de l'élément ROOT pour notre arbre
        if (emROOT != null) {
            try {
                ExportModel exm = new ExportModel(ExportModel.QN);
                exm.setId((cm != null ? cm.getId() : ""));
                exm.setCode((cm != null ? cm.getCode() : ""));
                exm.setLibelle((cm != null ? cm.getLibelle() : ""));
                // les champs de l'élément ROOT
                ExportElementModel eem = buildEEM(emROOT, null);
                if (emROOT.getEnfant() != null) {
                    eem.setEnfants(readChildren(emROOT, em, eem));
                // les fils
                }
                exm.addEnfant(eem);
                data = exm;
                ret.setData(exm);
            } catch (Exception e) {
                logger.error("Erreur lors de la lecture de la définition de la configuration", e);
            }
        } else {
            logger.error("Impossible de trouver l'élément ROOT");
        }

        return ret;
    }

    private Vector<ExportElementModel> readChildren(ElementModel p, EtatModel em, ExportElementModel parent) throws Exception {
        Vector<ExportElementModel> ret = new Vector<ExportElementModel>();
        for (String k : p.getEnfant().getEnfants().keySet()) {
            ElementModel child = em.getElementById(k);
            ExportElementModel eem = buildEEM(child, parent);
            if (child.getEnfant() != null && child.getEnfant().getEnfants().size() > 0) {
                eem.setEnfants(readChildren(child, em, eem));
            }
            ret.add(eem);
        }
        return ret;
    }

    private ExportElementModel buildEEM(ElementModel em, ExportElementModel parent) throws Exception {
        ExportElementModel ret = new ExportElementModel(ExportElementModel.QN);
        ret.setId(em.getId());
        ret.setLibelle(em.getTitre());
        ret.setParent(parent);

        // l'éventuel ExportElementModel présente dans la config correspondant
        ExportElementModel eemRef = null;
        if (dataToBeModified != null) {
            eemRef = findCorrespondingEEM(ret, dataToBeModified.getEnfants());
        }

        // champs de l'élément ROOT
        for (ChampModel tmpC : em.getListeResultat().getListeChamps()) {
            if (tmpC.isExportable()) {
                ExportChampModel ecm = new ExportChampModel(ExportChampModel.QN);
                ecm.setId(tmpC.getId());
                ecm.setLibelle(tmpC.getLibelle());
                ecm.setEditable(!tmpC.isIdentifiant());
                ecm.setIdentifiant(tmpC.isIdentifiant());
                //TODO
                if (eemRef != null) {
                    ExportChampModel ecmRef = findCorrespondingECM(ecm, eemRef);
                    if (ecmRef != null) {
                        ecm.setSelectionne(ecmRef.isSelectionne());
                    } else {
                        ecm.setSelectionne(false);
                    }
                } else {
                    ecm.setSelectionne(false);
                }
                ret.addChamp(ecm);
            }
        }
        return ret;
    }

    private ExportChampModel findCorrespondingECM(ExportChampModel ecm, ExportElementModel eem) {
        for (ExportChampModel e : eem.getChamps()) {
            if (e.getId().equals(ecm.getId())) {
                return ecm;
            }
        }
        return null;
    }

    private ExportElementModel findCorrespondingEEM(ExportElementModel eem, Vector<ExportElementModel> liste) {
        ExportElementModel ret = null;
        for (ExportElementModel e : liste) {
            if (e.getId().equals(eem.getId())) {
                ret = e;
                break;
            } else if (e.getEnfants().size() > 0) {
                ret = findCorrespondingEEM(eem, e.getEnfants());
                if (ret != null) {
                    break;
                }
            }
        }
        return ret;
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        tCode = new javax.swing.JTextField();
        tLibelle = new javax.swing.JTextField();
        jPanel2 = new javax.swing.JPanel();
        bSelectNone = new javax.swing.JButton();
        bSelectAll = new javax.swing.JButton();
        liste = new javax.swing.JScrollPane();
        treeTable = new JXTreeTablePropertyEditor();
        bEnregistrer = new javax.swing.JButton();
        bAnnuler = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Configuration d'export");

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Identification"));

        jLabel1.setText("Code");

        jLabel2.setText("Libellé");

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jLabel1)
                    .add(jLabel2))
                .add(26, 26, 26)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(tLibelle, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 581, Short.MAX_VALUE)
                    .add(tCode, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 581, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel1)
                    .add(tCode, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(tLibelle, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jLabel2))
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Configuration"));

        bSelectNone.setText("Tout désélectionner");
        bSelectNone.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bSelectNoneActionPerformed(evt);
            }
        });

        bSelectAll.setText("Tout sélectionner");
        bSelectAll.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bSelectAllActionPerformed(evt);
            }
        });

        treeTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_LAST_COLUMN);
        liste.setViewportView(treeTable);

        org.jdesktop.layout.GroupLayout jPanel2Layout = new org.jdesktop.layout.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel2Layout.createSequentialGroup()
                .addContainerGap(390, Short.MAX_VALUE)
                .add(bSelectAll)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(bSelectNone))
            .add(jPanel2Layout.createSequentialGroup()
                .add(liste, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 653, Short.MAX_VALUE)
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel2Layout.createSequentialGroup()
                .add(jPanel2Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(bSelectNone)
                    .add(bSelectAll))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 12, Short.MAX_VALUE)
                .add(liste, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        bEnregistrer.setText("Enregistrer");
        bEnregistrer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bEnregistrerActionPerformed(evt);
            }
        });

        bAnnuler.setText("Annuler");
        bAnnuler.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                bAnnulerActionPerformed(evt);
            }
        });

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jPanel2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .add(bAnnuler)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(bEnregistrer)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(bEnregistrer)
                    .add(bAnnuler))
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents
    private void bEnregistrerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bEnregistrerActionPerformed
        boolean needInsert = false;
        if (cm == null) {
            cm = new ConfigModel(ConfigModel.QN);
            needInsert = true;
        }
        try {
            cm.setCode(tCode.getText());
            cm.setLibelle(tLibelle.getText());
            data.setId(cm.getCode());
            data.setLibelle(cm.getLibelle());
            cm.setDocID(docID);
            cm.setEtatID(etatID);
            cm.setOwner(MainWindow.getInstance().getConnectedUser().getId());
            ensureKeysSelected();
            ByteArrayOutputStream sos = new ByteArrayOutputStream();
            OutputStreamWriter os = new OutputStreamWriter(sos, "ISO-8859-1");
            XmlOutputter xo = new XmlOutputter(os, "ISO-8859-1");
            data.marshall(xo);
            os.flush();
            cm.setConfigLines(sos.toByteArray());
            if (needInsert) {
                DataLayerManager.getImplementation().insertConfigExport(cm, user);
            } else {
                DataLayerManager.getImplementation().updateConfigExport(cm, user);
            }
            ((DlgSearchConfig) getParent()).bRechercherActionPerformed(null);
        } catch (Exception e) {
            logger.error("Erreur lors de la sauvegarde de la configuration", e);
        }
        this.dispose();
    }//GEN-LAST:event_bEnregistrerActionPerformed

    /**
     * Assure que pour chaque niveau, si un champs est sélectionné, les éléments formant la clef de ce niveau le sont aussi.
     * Assure aussi que si un champs est sélectionné pour un niveau, les clefs des niveaux parents le sont aussi.
     */
    private void ensureKeysSelected() {
        // la liste des éléments dont il faut sélectionner la clef
        Vector<ExportElementModel> toSelect = new Vector<ExportElementModel>();
        for (ExportElementModel ecm : data.getEnfants()) {
            browseChildrenToSelect(ecm, toSelect);
        }

// sélection de la clef de chaque élément identifié
        for (ExportElementModel e : toSelect) {
            e.selectChampsKey();
            e.selectParentChampsKey();
        }

    }

    private void browseChildrenToSelect(ExportElementModel parent, Vector<ExportElementModel> toSelect) {
        if (parent.hasChampSelected()) {
            toSelect.add(parent);
        }

        for (ExportElementModel ecm : parent.getEnfants()) {
            browseChildrenToSelect(ecm, toSelect);
        }

    }

    private void bAnnulerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bAnnulerActionPerformed
        this.dispose();
    }//GEN-LAST:event_bAnnulerActionPerformed

    private void bSelectNoneActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bSelectNoneActionPerformed
        toggleAll(false);
        treeTable.repaint();
    }//GEN-LAST:event_bSelectNoneActionPerformed

    private void bSelectAllActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bSelectAllActionPerformed
        toggleAll(true);
        treeTable.repaint();
    }//GEN-LAST:event_bSelectAllActionPerformed

    /**
     * Change l'état sélectionné de toutes les feuilles de l'arbre
     * @param select true => sélectionne, false => désélectionne
     */
    private void toggleAll(boolean select) {
        for (ExportElementModel eem : data.getEnfants()) {
            toggle(eem, select);
        }

    }

    private void toggle(ExportElementModel e, boolean select) {
        for (ExportChampModel ecm : e.getChamps()) {
            ecm.setSelectionne(select);
        }

        for (ExportElementModel eem : e.getEnfants()) {
            toggle(eem, select);
        }

    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton bAnnuler;
    private javax.swing.JButton bEnregistrer;
    private javax.swing.JButton bSelectAll;
    private javax.swing.JButton bSelectNone;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JScrollPane liste;
    private javax.swing.JTextField tCode;
    private javax.swing.JTextField tLibelle;
    private org.jdesktop.swingx.JXTreeTable treeTable;
    // End of variables declaration//GEN-END:variables
    private static class JXTreeTablePropertyEditor extends JXTreeTable {

        private static final long serialVersionUID = -5756581514191559300L;
        private TableCellRenderer booleanRenderer,  booleanDisabledRenderer,  blankRenderer;

        public JXTreeTablePropertyEditor() {
            super();
            booleanRenderer = new DefaultTableCellRenderer() {

                private JCheckBox chk = new JCheckBox();

                @Override
                public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                    JLabel lbl = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                    chk.setSelected(((Boolean) value).booleanValue());
                    chk.setBackground(lbl.getBackground());
                    chk.setBorder(lbl.getBorder());
                    return chk;
                }
            };
            booleanDisabledRenderer = new DefaultTableCellRenderer() {

                private JCheckBox chk = new JCheckBox();

                @Override
                public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                    JLabel lbl = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                    chk.setSelected(((Boolean) value).booleanValue());
                    chk.setBackground(lbl.getBackground());
                    chk.setBorder(lbl.getBorder());
                    chk.setEnabled(false);
                    return chk;
                }
            };
            blankRenderer = new DefaultTableCellRenderer() {

                @Override
                public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
                    JLabel lbl = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                    lbl.setText("");
                    return lbl;
                }
            };
        }

        @Override
        public TableCellRenderer getCellRenderer(int row, int column) {
            if (column == 1 && getTreeTableModel() instanceof ConfigTreeTableModel) {
                ConfigTreeTableModel model = (ConfigTreeTableModel) getTreeTableModel();
                Object node = getPathForRow(row).getLastPathComponent();
                if (node instanceof ExportChampModel) {
//                	ExportChampModel ecm = (ExportChampModel)node;
//                    if(!ecm.isEditable()) {
//                   	return booleanDisabledRenderer;
//                    } else {
                    return booleanRenderer;
//                    }
                } else if (node instanceof ExportElementModel) {
                    return blankRenderer;
                }
                return super.getCellRenderer(row, column);
            } else {
                return super.getCellRenderer(row, column);
            }
        }
    }

    private static class ConfigTreeTableModel extends DefaultTreeTableModel {

        private String[] columnNames = new String[]{"", ""};
        private ExportModel _data;

        public ConfigTreeTableModel(ExportModel data) {
            _data = data;
        }

        @Override
        public boolean isLeaf(Object node) {
            if (node instanceof ExportElementModel) {
                return (((ExportElementModel) node).getEnfants().size() == 0 && ((ExportElementModel) node).getChamps().size() == 0);
            } else if (node instanceof ExportChampModel) {
                return true;
            } else {
                return true;
            }
        }

        @Override
        public Class getColumnClass(int i) {
            if (i == 0) {
                return super.getColumnClass(i);
            } else if (i == 1) {
                return Boolean.class;
            } else {
                return super.getColumnClass(i);
            }
        }

        @Override
        public Object getValueAt(Object object, int i) {
            if (object instanceof ExportElementModel) {
                if (i == 0) {
                    return ((ExportElementModel) object).getLibelle();
                } else if (i == 1) {
                    return new Boolean(Boolean.FALSE);
                } else {
                    return "";
                }
            } else {
                if (i == 0) {
                    return ((ExportChampModel) object).getLibelle();
                } else if (i == 1) {
                    return new Boolean(((ExportChampModel) object).isSelectionne());
                } else {
                    return "";
                }
            }
        }

        @Override
        public void setValueAt(Object value, Object node, int column) {
            ExportChampModel ecm = (ExportChampModel) node;
            if (column == 1) {
                ecm.setSelectionne((Boolean) value);
            }
        }

        @Override
        public int getChildCount(Object parent) {
            if (parent instanceof ExportElementModel) {
                ExportElementModel eem = (ExportElementModel) parent;
                return (eem.getEnfants().size() + eem.getChamps().size());
            } else if (parent instanceof ExportChampModel) {
                return 0;
            } else {
                return 0;
            }
        }

        @Override
        public Object getChild(Object parent, int index) {
            if (parent instanceof ExportElementModel) {
                ExportElementModel eem = (ExportElementModel) parent;
                if (index < eem.getChamps().size()) {
                    return eem.getChamps().get(index);
                } else {
                    // les enfants sont après les champs
                    return eem.getEnfants().get(index - eem.getChamps().size());
                }
            } else {
                return null;
            }
        }

        @Override
        public boolean isCellEditable(Object object, int i) {
            if (object instanceof ExportChampModel) {
                return true;
            }//(i==1 && ((ExportChampModel)object).isEditable());
            else {
                return false;
            }
        }

        @Override
        public int getIndexOfChild(Object parent, Object child) {
            if (parent instanceof ExportElementModel) {
                ExportElementModel p = (ExportElementModel) parent;
                if (child instanceof ExportChampModel) {
                    ExportChampModel c = (ExportChampModel) child;
                    int i = 0;
                    for (; i < p.getChamps().size(); i++) {
                        ExportChampModel t = (ExportChampModel) p.getChamps().get(i);
                        if (t.getId().equals(c.getId())) {
                            return i;
                        }
                    }
                } else {
                    ExportElementModel c = (ExportElementModel) child;
                    int i = 0;
                    for (; i < p.getEnfants().size(); i++) {
                        ExportElementModel t = (ExportElementModel) p.getEnfants().get(i);
                        if (t.getId().equals(c.getId())) {
                            return (i + p.getChamps().size());
                        }
                    }
                }
            }
            return -1;
        }

        @Override
        public Object getRoot() {
            return _data.getEnfants().get(0);
        }

        @Override
        public int getColumnCount() {
            return columnNames.length;
        }

        public int getRowCount2() {
            int ret = getChampsCount(this._data);
            if (this._data.getEnfants().size() > 0) {
                ret += getChildsCount(_data);
            }
            return ret;
        }

        public int getChampsCount(Object parent) {
            return ((ExportElementModel) parent).getChamps().size();
        }

        public int getChildsCount(Object parent) {
            int ret = getChampsCount(parent);
            for (ExportElementModel eem : ((ExportElementModel) parent).getEnfants()) {
                ret += getChildsCount(eem);
            }
            return ret;
        }

        @Override
        public String getColumnName(int arg0) {
            return columnNames[arg0];
        }

        public ExportModel getData() {
            return _data;
        }

        public void setData(ExportModel data) {
            this._data = data;
        }
    }

    @Override
    protected JRootPane createRootPane() {
        KeyStroke ks = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
        JRootPane rp = new JRootPane();
        escapeAction =
                new AbstractAction("Fermer") {

                    /**
                     * Comment for <code>serialVersionUID</code>
                     */
                    private static final long serialVersionUID = 1L;

                    public void actionPerformed(ActionEvent evt) {
                        setVisible(false);
                    }
                };
        rp.registerKeyboardAction(escapeAction, "TOTOTOTO", ks, JComponent.WHEN_IN_FOCUSED_WINDOW);
        return rp;
    }
}
