import java.awt.BorderLayout;
import java.awt.Component;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.net.URL;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

public class jfileviewer01 extends JDialog 
{

	private JTextArea preview;
	private JTree fileTree;
	private FileSystemModel fileSystemModel;
	private JTextArea fileDetailsTextArea = new JTextArea();
	  
	
	private DefaultMutableTreeNode root;

	private DefaultTreeModel treeModel;

	private JTree tree;
	
	public jfileviewer01(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, 900, 900);
			setTitle("Jtable et Progress bar...");
			getContentPane().setLayout(null);
	     	
			ImageIcon icon = null;
			icon = createImageIcon("resources/settings.png", "");
			setIconImage( icon.getImage() );
			
			
			tree = new JTree(new FileSelectorModel("c:\\"));

	       // preview = new JTextArea();
	       // preview.setWrapStyleWord(true);
	       // preview.setLineWrap(true);
	       // preview.setEditable(false);
			
			
			tree.addTreeSelectionListener(new TreeSelectionListener() 
			 {

		            public void valueChanged(TreeSelectionEvent e) 
		            {
		                FileNode selectedNode = (FileNode) tree.getLastSelectedPathComponent();
		                
		                if (selectedNode.isFile()) {
		                	fileDetailsTextArea.setText(null);
		                    try {
		                        BufferedReader br = new BufferedReader(new FileReader(selectedNode.getAbsolutePath()));
		                        String line = "";
		                        while ((line = br.readLine()) != null) {
		                        	fileDetailsTextArea.append(line);
		                        	fileDetailsTextArea.append(System.getProperty("line.separator"));
		                        }
		                    } catch (Exception exc) {
		                        exc.printStackTrace();
		                    }
		                }
		            }
		        });
			
			
			tree.setCellRenderer(new DefaultTreeCellRenderer() 
			{

	            @Override
	            public Component getTreeCellRendererComponent(
	                    JTree tree,
	                    Object value,
	                    boolean sel,
	                    boolean expanded,
	                    boolean leaf,
	                    int row,
	                    boolean hasFocus) {

	                // Call parent rendering to keep the default behaviour
	                super.getTreeCellRendererComponent(
	                        tree, value, sel,
	                        expanded, leaf, row,
	                        hasFocus);

	                // And now specific stuff
	                File currentFile = (File) value;
	                // If the current node is a directory, and if it has no child,
	                // or if they are not accessible, change the icon.
	                if (currentFile.isDirectory() && (currentFile.list() == null || currentFile.list().length == 0)) {
	                    if (expanded) {
	                        setIcon(openIcon);
	                    } else {
	                        setIcon(closedIcon);
	                    }
	                }

	                return this;
	            }
	        });
			
			
			//JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
	        //        new JScrollPane(tree),
	        //        new JScrollPane(preview));
	       // split.setContinuousLayout(true);

	        //getContentPane().add(BorderLayout.SOUTH, status);
	       // getContentPane().add(split);
	        
	     //   setVisible(true);
			
			
			JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
			                new JScrollPane(tree),
			                new JScrollPane(fileDetailsTextArea));
			splitPane.setResizeWeight(0.2);
			splitPane.setEnabled(false);
			splitPane.setBounds(10, 10, 750, 700);
			
			splitPane.setContinuousLayout(true);
			
			getContentPane().add(splitPane);
			
			
			fileDetailsTextArea.setTabSize(12);
			splitPane.setRightComponent(fileDetailsTextArea);
			
			
			
			splitPane.setLeftComponent(tree);
			
			
	/*		
			fileDetailsTextArea.setEditable(false);
		    fileSystemModel = new FileSystemModel(new File("c:\\"));
		    fileTree = new JTree(fileSystemModel);
		    fileTree.setEditable(true);
		    fileTree.addTreeSelectionListener(new TreeSelectionListener() {
		      public void valueChanged(TreeSelectionEvent event) {
		        File file = (File) fileTree.getLastSelectedPathComponent();
		        fileDetailsTextArea.setText(getFileDetails(file));
		      }
		    });
*/		    
		    
		  //  JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, new JScrollPane(
		   //     fileTree), new JScrollPane(fileDetailsTextArea));
		   // getContentPane().add(splitPane);
		  // add(splitPane);
		    // setDefaultCloseOperation(EXIT_ON_CLOSE);
		  //  setSize(640, 480);
		 //   setVisible(true);
		
	}	
	
	 private String getFileDetails(File file) {
		    if (file == null)
		      return "";
		    StringBuffer buffer = new StringBuffer();
		    buffer.append("Name: " + file.getName() + "\n");
		    buffer.append("Path: " + file.getPath() + "\n");
		    buffer.append("Size: " + file.length() + "\n");
		    return buffer.toString();
		  }
	
	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 FileSystemModel implements TreeModel {
		  private File root;
		 
		  private Vector listeners = new Vector();
		 
		  public FileSystemModel(File rootDirectory) {
		    root = rootDirectory;
		  }
		 
		  public Object getRoot() {
		    return root;
		  }
		 
		  public Object getChild(Object parent, int index) {
		    File directory = (File) parent;
		    String[] children = directory.list();
		    return new TreeFile(directory, children[index]);
		  }
		 
		  public int getChildCount(Object parent) {
		    File file = (File) parent;
		    if (file.isDirectory()) {
		      String[] fileList = file.list();
		      if (fileList != null)
		        return file.list().length;
		    }
		    return 0;
		  }
		 
		  public boolean isLeaf(Object node) {
		    File file = (File) node;
		    return file.isFile();
		  }
		 
		  public int getIndexOfChild(Object parent, Object child) {
		    File directory = (File) parent;
		    File file = (File) child;
		    String[] children = directory.list();
		    for (int i = 0; i < children.length; i++) {
		      if (file.getName().equals(children[i])) {
		        return i;
		      }
		    }
		    return -1;
		 
		  }
		 
		  public void valueForPathChanged(TreePath path, Object value) {
		    File oldFile = (File) path.getLastPathComponent();
		    String fileParentPath = oldFile.getParent();
		    String newFileName = (String) value;
		    File targetFile = new File(fileParentPath, newFileName);
		    oldFile.renameTo(targetFile);
		    File parent = new File(fileParentPath);
		    int[] changedChildrenIndices = { getIndexOfChild(parent, targetFile) };
		    Object[] changedChildren = { targetFile };
		    fireTreeNodesChanged(path.getParentPath(), changedChildrenIndices, changedChildren);
		 
		  }
		 
		  private void fireTreeNodesChanged(TreePath parentPath, int[] indices, Object[] children) {
		    TreeModelEvent event = new TreeModelEvent(this, parentPath, indices, children);
		    Iterator iterator = listeners.iterator();
		    TreeModelListener listener = null;
		    while (iterator.hasNext()) {
		      listener = (TreeModelListener) iterator.next();
		      listener.treeNodesChanged(event);
		    }
		  }
		 
		  public void addTreeModelListener(TreeModelListener listener) {
		    listeners.add(listener);
		  }
		 
		  public void removeTreeModelListener(TreeModelListener listener) {
		    listeners.remove(listener);
		  }
		 
		  private class TreeFile extends File {
		    public TreeFile(File parent, String child) {
		      super(parent, child);
		    }
		 
		    public String toString() {
		      return getName();
		    }
		  }
	}
	
  
}



class FileNode extends java.io.File 
{

    public FileNode(String directory) 
    {
        super(directory);
    }

    public FileNode(FileNode parent, String child) 
    {
        super(parent, child);
    }

    @Override
    public String toString() 
    {
        return (getName().length() == 0 ? getPath() : getName() );
    }
}


class FileSelectorModel implements TreeModel {

    private FileNode root;

    /**
    * the constructor defines the root.
    */
    public FileSelectorModel(String directory) {
        root = new FileNode(directory);
    }

    public Object getRoot() {
        return root;
    }

    /**
    * returns the <code>parent</code>'s child located at index <code>index</code>.
    */
    public Object getChild(Object parent, int index) {
        FileNode parentNode = (FileNode) parent;
        List<File> children = getSortedChildren(parentNode);

        return new FileNode(parentNode,
                            children.get(index).getName());
    }

    /**
    * returns the number of child.  If the node is not a directory, or its list of children
    * is null, returns 0.  Otherwise, just return the number of files under the current file.
    */
    public int getChildCount(Object parent) {
        FileNode parentNode = (FileNode) parent;
        if (parent == null
                || !parentNode.isDirectory()
                || parentNode.listFiles() == null) {
            return 0;
        }

        return parentNode.listFiles().length;
    }

    /**
    * returns true if {{@link #getChildCount(Object)} is 0.
    */
    public boolean isLeaf(Object node) {
        return (getChildCount(node) == 0);
    }

    /**
    * return the index of the child in the list of files under <code>parent</code>.
    */
    public int getIndexOfChild(Object parent, Object child) {
        FileNode parentNode = (FileNode) parent;
        FileNode childNode = (FileNode) child;

        List<File> children = getSortedChildren(parentNode);

        return children.indexOf(childNode);
    }

    private List<File> getSortedChildren(File node) {
        List<File> children = Arrays.asList(node.listFiles());
        Collections.sort(children, new Comparator<File>() {

            public int compare(File o1, File o2) {
                if (o1.isDirectory() == o2.isDirectory()) {
                    return o1.getName().compareTo(o2.getName());
                }

                if (o1.isDirectory()) {
                    return -1;
                }

                return 1;
            }
        });

        return children;
    }

    // The following methods are not implemented, as we won't need them for this example.

    public void valueForPathChanged(TreePath path, Object newValue) {
    }

    public void addTreeModelListener(TreeModelListener l) {
    }

    public void removeTreeModelListener(TreeModelListener l) {
    }
}
/****************************************************************************************/

// http://www.java2s.com/Code/Java/File-Input-Output/DisplayafilesysteminaJTreeview.htm

//https://stackoverflow.com/questions/23804675/list-files-and-directories-with-jtree-and-file-in-java

// https://www.rgagnon.com/javadetails/java-0324.html

// http://www.javaprogrammingforums.com/java-swing-tutorials/7944-how-use-jtree-create-file-system-viewer-tree.html