import javax.swing.border.EmptyBorder;
import javax.swing.border.TitledBorder;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;


import javax.swing.border.LineBorder;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.plaf.basic.BasicButtonListener;
import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.List;
import java.awt.*;

import java.awt.*;
import java.beans.DefaultPersistenceDelegate;
import java.beans.Encoder;
import java.beans.Statement;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;

import javax.swing.table.JTableHeader;

public class jdialog012 extends JDialog 
{
	private JTable table;
	private boolean close_Jdialog = false;
	private JButton btn_load_tree;
	private JButton btn_save_tree;
	private JButton btn_load_table;
	private JButton btn_save_table;
	
	private JButton btn_analyse;
	
	private JTextField filterText;
	private JLabel lbl_filter;
		
	private static final int BOOLEAN_COLUMN_INDEX = 0;
	
	String[] toolTipStr = {"Select/Deselect all" , "aqw"      ,"Java","French","Latin"};
	
	public jdialog012(JFrame f, boolean modal) 
	{
	       super(f, modal);
	      
	       // fermer la fenetre
	       addWindowListener(new java.awt.event.WindowAdapter() 
	       {
	           public void windowClosing(java.awt.event.WindowEvent e) 
	           {
	        	   dispose();
	           }
	       });
	      
	       init();
	}
  
	private void init()
	{
		  	setResizable( false );
			setBounds(100, 100, 926, 550);
			setTitle("Filter table - debug ...");
			getContentPane().setLayout(null);
	     	
			ImageIcon icon = null;
			icon = createImageIcon("resources/settings.png", "");
			setIconImage( icon.getImage() );
			
			setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
			
			JScrollPane scrollPane = new JScrollPane();
			scrollPane.setBounds(294, 39, 532, 159);
			getContentPane().add(scrollPane);
			
			String[] columnNames =  { "", "Test", "Deux" , "rien", "plus"};
	     		  
		    //Object[][] data = {	{ "", "", ""}  };
		    
			Object [] nom_colum = {"", "Test", "Deux" , "rien", "plus"};
			
		    Object[][] data = 
		    	{
		            { Boolean.TRUE, "USA", "Washington DC", "179", "false"},
		            { Boolean.TRUE, "Canada", "Ottawa", "32", "true"},
		            { Boolean.TRUE, "United Kingdom", "London", "60", "false"},
		            { Boolean.TRUE, "Germany", "Berlin", "83", "true"},
		            { Boolean.TRUE, "France", "Paris", "28", "true"},
		            { Boolean.FALSE, "Norway", "Oslo", "79", "false"},
		            { Boolean.TRUE, "India", "New Delhi", "1079", "false"}
		        };
		    
		    // Boolean.TRUE, "India", "New Delhi", new Integer(1079), true
		    
		    Class[] columnTypes = new Class[] { Boolean.class, Object.class };
		    
		   
		    
		/*    
		    table.setModel(new DefaultTableModel(new Object[][] {
				{ Boolean.TRUE, "V1" },
				{ false, "V2" },
				{ Boolean.TRUE, "V3" },
				{ false, "V4" },
				{ Boolean.TRUE, "V5" },
				{ false, "V6" }, }, new String[] { "", "Valeur" }) {
			Class[] columnTypes = new Class[] { Boolean.class, Object.class };

			@Override
			public Class getColumnClass(final int columnIndex) {
				return columnTypes[columnIndex];
			}
		});
		*/    
		    
////////		    TableModel model = new DefaultTableModel(data, columnNames); 
		    
		    /*{
		        public Class getColumnClass(int column) 
		        {
		          Class returnValue;
		          if ((column >= 0) && (column < getColumnCount())) 
		          {
		        	  returnValue = getValueAt(0, column).getClass();
		          } 
		          else 
		          {
		        	  returnValue = Object.class;
		          }
		          
		          return returnValue;
		        }
		    };*/
		    
		    TableModel model = new DefaultTableModel(data,  columnNames)
		    {		
		    	/*@Override
		    	public Class getColumnClass(final int columnIndex) 
		    	{
		    		return columnTypes[columnIndex];
		    	}*/
		    	
		    	 @Override
			        public boolean isCellEditable(int row, int column)
			        {
			            // make read only fields except column 0,13,14
			            return column == 0 ;
			        }
		    	
		    	@Override
		        public Class<?> getColumnClass(int columnIndex) 
		    	{
		            if (columnIndex == BOOLEAN_COLUMN_INDEX) 
		            {
		                return Boolean.class;
		            } 
		            else 
		            {
		                return String.class;
		            }
		            
		            
		           // if (columnIndex >= 0 && columnIndex <= getColumnCount())
		           //     return getValueAt(0, columnIndex).getClass();
		            //  else
		            //    return Object.class;
		            
		            
		        }
		    	
		    	
		    	
		    };
		    
		    
		    table = new JTable(model);
		    
		    JTableHeader anHeader = table.getTableHeader();
		    anHeader.setForeground(Color.yellow);
		    anHeader.setBackground(Color.black);
		    //JTableHeader headerx = table.getTableHeader();
		    //headerx.setBackground(Color.black);
		    //headerx.setForeground(Color.yellow);
		    
		    
		    // pas désactiver le classement
		    //table.getTableHeader().setEnabled(false);
		    
		    // bloquer le deplacement des colonnes
		    table.getTableHeader().setReorderingAllowed(false);
		    // dimension
		    table.setRowHeight(30);
		    table.setFont(new Font("Serif", Font.BOLD, 20));
			
		    // on n'a pas le droit de faire une modif
		    table.setEnabled(true);
		    
		    TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
		    table.setRowSorter(sorter);
		    
		    
		    List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
            sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));
            sortKeys.add(new RowSorter.SortKey(3, SortOrder.ASCENDING));
            sorter.setSortKeys(sortKeys);
		    
	    
		    scrollPane.setViewportView(table);
		    
		    
		    
		    ToolTipHeader header = new ToolTipHeader(table.getColumnModel());
		    header.setToolTipStrings(toolTipStr);
		    //header.setToolTipText("Default ToolTip TEXT");
		    table.setTableHeader(header);
		    
			
			/*******************/
			
		    lbl_filter = new JLabel();
		    lbl_filter.setText("Filter :");
		    lbl_filter.setBounds(350, 357, 89, 23);
			getContentPane().add(lbl_filter);
		    
		    
			filterText = new JTextField();
			filterText.setBounds(450, 357, 89, 23);
			getContentPane().add(filterText);
			
			 
			 filterText.getDocument().addDocumentListener(new DocumentListener() 
			 {
				  public void changedUpdate(DocumentEvent e) 
				  {
					  System.out.println("update");
					  String text = filterText.getText();
					     if (text.length() == 0) 
					     {
					          sorter.setRowFilter(null);
					     } 
					     else 
					     {
					    	 sorter.setRowFilter(RowFilter.regexFilter(text));
					     }
				  }

				  public void removeUpdate(DocumentEvent e) 
				  {
					  System.out.println("remove");
					  String text = filterText.getText();
					     if (text.length() == 0) 
					     {
					          sorter.setRowFilter(null);
					     } 
					     else 
					     {
					    	 sorter.setRowFilter(RowFilter.regexFilter(text));
					     }
				  }

				  public void insertUpdate(DocumentEvent e) 
				  {
					 System.out.println("insert");
					  
					 String text = filterText.getText();
				     if (text.length() == 0) 
				     {
				          sorter.setRowFilter(null);
				     } 
				     else 
				     {
				    	 sorter.setRowFilter(RowFilter.regexFilter(text));
				     }
					
				     
				     
				  }
				 
			});
			 
				final TableColumn booleanColumn = table.getTableHeader().getColumnModel().getColumn(BOOLEAN_COLUMN_INDEX);

			 
			// Création de la checkBox qui sera affichée en en-tête de colonne.
				final JCheckBox checkBoxHeader = new JCheckBox();

				checkBoxHeader.setSelected(true);
				// Création et affectation du cell renderer qui aura en charge la représentation de l'en-tête de colonne
				// (affichant une checkbox en plus du rendu par défaut)
				booleanColumn.setHeaderRenderer(new CheckBoxHeaderRenderer(checkBoxHeader));

				// Ajout du "forwarder". Listener qui va être informé des clics sue l'en-tête de colonne et les transmettre à la
				// checkbox.
				final HeaderMouseEventsForwarder eventFrowarder =
						new HeaderMouseEventsForwarder(checkBoxHeader, BOOLEAN_COLUMN_INDEX);
				table.getTableHeader().addMouseListener(eventFrowarder);

				// Ajout du listener qui va cocher/décocher toutes les checkbox
				checkBoxHeader.addActionListener(new ActionListener() {

					@Override
					public void actionPerformed(final ActionEvent e) {
						if (!(e.getSource() instanceof JCheckBox)) {
							return;
						}
						final boolean selected = ((JCheckBox) e.getSource()).isSelected();
						final TableModel model = table.getModel();
						for (int i = 0; i < model.getRowCount(); i++) {
							model.setValueAt(selected, i, BOOLEAN_COLUMN_INDEX);
						}

					}
				});
			 
			 
			/*******************/
			
			JSeparator separator = new JSeparator();
			separator.setBounds(240, 302, 440, 2);
			getContentPane().add(separator);
		
			/*******************/
		
			JButton btn_ok = new JButton("OK");
			btn_ok.addActionListener(new ActionListener() 
			{
				public void actionPerformed(ActionEvent arg0) 
				{
					close_Jdialog = false;
					System.out.println("Btn Cancel  \n");
					dispose();
				}
			});
			btn_ok.setBounds(135, 391, 89, 23);
			getContentPane().add(btn_ok);
	
			/*******************/
			
			JButton btn_cancel = new JButton("Cancel");
			btn_cancel.addActionListener(new ActionListener() 
			{
				public void actionPerformed(ActionEvent e) 
				{
					close_Jdialog = false;
					System.out.println("Btn Cancel  \n");
					dispose();
				}
			});
			btn_cancel.setBounds(359, 391, 89, 23);
			getContentPane().add(btn_cancel);
		
			/*******************/
			
			JButton btn_process = new JButton("Process");
			btn_process.addActionListener(new ActionListener() 
			{
				public void actionPerformed(ActionEvent e) 
				{
					close_Jdialog = false;
					System.out.println("Btn Process  \n");
					
					boolean value;
					
					for (int i = 0; i < model.getRowCount(); i++) 
					{
						value = ((Boolean)model.getValueAt(i, 0)).booleanValue();
						
						String pipo = "123";
						System.out.println(value);
					}  
					
				}
			});
			btn_process.setBounds(559, 391, 89, 23);
			getContentPane().add(btn_process);
	}
    
	public ImageIcon createImageIcon(String path,  String description) 
	{
		URL imgURL = getClass().getResource(path);

		if (imgURL != null)
		{
  			return new ImageIcon(imgURL, description);
		} 
		else 
		{
			System.err.println("Couldn't find file: " + path);
			return null;
		}
	}
	
	class ToolTipHeader extends JTableHeader {
	    String[] toolTips;
	   
	    public ToolTipHeader(TableColumnModel model) {
	      super(model);
	    }
	     
	    public String getToolTipText(MouseEvent e) {
	      int col  = columnAtPoint(e.getPoint());
	      int modelCol = getTable().convertColumnIndexToModel(col);
	      String retStr;
	      try {
	        retStr = toolTips[modelCol];
	      } catch (NullPointerException ex) {
	        retStr = "";
	      } catch (ArrayIndexOutOfBoundsException ex) {
	        retStr = "";
	      }
	      if (retStr.length() < 1) {
	        retStr = super.getToolTipText(e);
	      }
	      return retStr;
	    }  
	     
	    public void setToolTipStrings(String[] toolTips) {
	      this.toolTips = toolTips;
	    }
	  }
    
}
/****************************************************************************************/

class CheckBoxHeaderRenderer extends JPanel implements TableCellRenderer 
{

	private static final Color TRANSPARENT_COLOR = new Color(0, 0, 0, 0);

	private static Integer CHECKBOX_LAYER_INDEX = new Integer(1);
	private static Integer DEFAULT_COMPONENT_LAYER_INDEX = new Integer(0);

	private Component defaultRendering;
	private final JCheckBox checkBox;
	private final JLayeredPane layeredPane;
	
	private JLabel label = new JLabel("Selection") ;

	public CheckBoxHeaderRenderer(final JCheckBox checkBox) 
	{
		setLayout(new BorderLayout());
		layeredPane = new JLayeredPane();
		add(layeredPane, BorderLayout.CENTER);

		this.checkBox = checkBox;
		this.checkBox.setBackground(TRANSPARENT_COLOR);
		layeredPane.add(checkBox, CHECKBOX_LAYER_INDEX);
		
		//this.label = label;
		layeredPane.add(label);
		//add(label);
		
		//layeredPane.add(checkBox, CHECKBOX_LAYER_INDEX);
		 //add(label);
		
	}

	
	

	@Override
	public Component getTableCellRendererComponent(
			final JTable table,
			final Object value,
			final boolean isSelected,
			final boolean hasFocus,
			final int row,
			final int column) {
		if (defaultRendering != null) 
		{
			layeredPane.remove(defaultRendering);
		}
		// On récupère le "rendu" par défaut afin de dessiner "au-dessus"
		defaultRendering = table
				.getTableHeader()
				.getDefaultRenderer()
				.getTableCellRendererComponent(table, "", isSelected, hasFocus, row, column);

		final int x = Math.round(this.getPreferredSize().width / 2f - checkBox.getPreferredSize().width / 2f);
		final int y = Math.round(this.getPreferredSize().height / 2f - checkBox.getPreferredSize().height / 2f);
		defaultRendering.setBounds(0, 0, this.getPreferredSize().width, this.getPreferredSize().height);
		layeredPane.add(defaultRendering, DEFAULT_COMPONENT_LAYER_INDEX);
		checkBox.setBounds(x - 1, y - 1, checkBox.getPreferredSize().width, checkBox.getPreferredSize().height);
		
		
		
	    // setBackground(Color.green);
	     
		
		
		return this;
	}

}

class HeaderMouseEventsForwarder implements MouseListener {

	private final BasicButtonListener buttonListener;

	private final AbstractButton button;

	private final int columnIndex;

	/**
	 * Constructeur.
	 * 
	 * @param button
	 *            : Button vers lequel on veut propager les évènements
	 * @param columnIndex
	 *            : Index de la colonne dont on veut propager les évènements
	 */
	public HeaderMouseEventsForwarder(final AbstractButton button, final int columnIndex) {
		// Ce constructeur n'utilise pas l'argument ...
		this.buttonListener = new BasicButtonListener(button);
		this.button = button;
		this.columnIndex = columnIndex;
	}

	@Override
	public void mouseClicked(final MouseEvent e) {
		if (!(e.getSource() instanceof JTableHeader)) {
			return;
		}

		final JTableHeader h = (JTableHeader) e.getSource();
		final TableColumnModel columnModel = h.getColumnModel();
		final int viewColumn = h.columnAtPoint(e.getPoint());
		if (viewColumn == -1) {
			return;
		}
		final int modelColumnIndex = columnModel.getColumn(viewColumn).getModelIndex();

		if (modelColumnIndex != columnIndex) {
			return;
		}

		final MouseEvent newMouseEvent =
				new MouseEvent(button, e.getID(), e.getWhen(), e.getModifiers(), e.getX()
						- button.getX(), e.getY() - button.getY(), e.getClickCount(), e.isPopupTrigger());

		buttonListener.mouseClicked(newMouseEvent);

	}

	@Override
	public void mousePressed(final MouseEvent e) {
		if (!(e.getSource() instanceof JTableHeader)) {
			return;
		}

		final JTableHeader h = (JTableHeader) e.getSource();
		final TableColumnModel columnModel = h.getColumnModel();
		final int viewColumn = h.columnAtPoint(e.getPoint());
		if (viewColumn == -1) {
			return;
		}
		final int modelColumnIndex = columnModel.getColumn(viewColumn).getModelIndex();

		if (modelColumnIndex != columnIndex) {
			return;
		}

		final MouseEvent newMouseEvent =
				new MouseEvent(button, e.getID(), e.getWhen(), e.getModifiers(), e.getX()
						- button.getX(), e.getY() - button.getY(), e.getClickCount(), e.isPopupTrigger());

		buttonListener.mousePressed(newMouseEvent);

	}

	@Override
	public void mouseReleased(final MouseEvent e) {
		if (!(e.getSource() instanceof JTableHeader)) {
			return;
		}

		final JTableHeader h = (JTableHeader) e.getSource();
		final TableColumnModel columnModel = h.getColumnModel();
		final int viewColumn = h.columnAtPoint(e.getPoint());
		if (viewColumn == -1) {
			return;
		}
		final int modelColumnIndex = columnModel.getColumn(viewColumn).getModelIndex();

		if (modelColumnIndex != columnIndex) {
			return;
		}

		final MouseEvent newMouseEvent =
				new MouseEvent(button, e.getID(), e.getWhen(), e.getModifiers(), e.getX()
						- button.getX(), e.getY() - button.getY(), e.getClickCount(), e.isPopupTrigger());

		buttonListener.mouseReleased(newMouseEvent);

	}

	@Override
	public void mouseEntered(final MouseEvent e) {
		if (!(e.getSource() instanceof JTableHeader)) {
			return;
		}

		final JTableHeader h = (JTableHeader) e.getSource();
		final TableColumnModel columnModel = h.getColumnModel();
		final int viewColumn = h.columnAtPoint(e.getPoint());
		if (viewColumn == -1) {
			return;
		}
		final int modelColumnIndex = columnModel.getColumn(viewColumn).getModelIndex();

		final MouseEvent newMouseEvent =
				new MouseEvent(button, e.getID(), e.getWhen(), e.getModifiers(), e.getX()
						- button.getX(), e.getY() - button.getY(), e.getClickCount(), e.isPopupTrigger());

		buttonListener.mouseEntered(newMouseEvent);

	}

	@Override
	public void mouseExited(final MouseEvent e) {
		if (!(e.getSource() instanceof JTableHeader)) {
			return;
		}

		final JTableHeader h = (JTableHeader) e.getSource();
		final TableColumnModel columnModel = h.getColumnModel();
		final int viewColumn = h.columnAtPoint(e.getPoint());
		if (viewColumn == -1) {
			return;
		}
		final int modelColumnIndex = columnModel.getColumn(viewColumn).getModelIndex();

		if (modelColumnIndex != columnIndex) {
			return;
		}

		final MouseEvent newMouseEvent = new MouseEvent(button, e.getID(), e.getWhen(), e.getModifiers(), button.getX()
				+ button.getWidth() / 2, button.getY() + button.getHeight() / 2, e.getClickCount(), e.isPopupTrigger());

		buttonListener.mouseExited(newMouseEvent);

	}

}

// multi col sort
// setSortKeys

// http://esus.com/creating-a-jtable-with-headers-with-jtooltips/

// http://www.java2s.com/Tutorial/Java/0240__Swing/1020__JTable-Model.htm


// https://stackoverflow.com/questions/7137786/how-can-i-put-a-control-in-the-jtableheader-of-a-jtable/7137801#7137801